AntCTF X D³CTF Reverse white give

警告
本文最后更新于 2021-03-11,文中内容可能已过时。

1.去除简单的混淆

代码存在一些混淆导致浏览伪代码的体验较差,从其他师傅的wp那里学习到可以利用IDA的优化来去除一些简单的混淆,要做的就是用Y键来在变量类型之前加一个const,IDA识别为常量以后就会自动优化处理

2.分析程序逻辑

sha256编码

图片

首先来看这一段代码,先判断了输入字符串的长度要等于64,接着使用一个循环把字符串四个四个的送入sha256函数中,我们知道sha256生成的长度有0x40,但是通过Buf1[0x20 * v12]可以得知,程序实际上只保留了前0x20长度的结果(后面生成的数据会覆盖掉前面的)

生成SBOX并移动数据位置

图片

通过循环生成了一个sbox,并且在后面的循环中用sbox来更换了数据位置。这部分内容,我们可以通过生成invSbox来还原信息,所以不重要。

生成异或数据

图片

这部分内容生成了异或数据,但是调试可以发现生成的**v28变量(异或数据)**虽然每一轮都不一样,但是上图中的v29变量的信息,在每一次生成的时候都是一致的,而v28数据就是由v29的数据变换而来,虽然我们可以提取出v29的数据,并且在每一次循环的时候动态生成v28。

1
2
3
4
5
6
7
for (jj = 1i64; jj < 0x11; jj++)
{
    for (kk = 0i64; kk < 0x10; kk++)
    {
        v28[16 * jj - 16 + kk] = ida_chars[kk + 16 * n] * jj;
    }
}

对Buf1进行异或

图片

我们知道Buf1数据就是之前来自于sha256之后且通过sbox移位的数据。

这部分代码的混淆虽然很恶心,但是我们可以通过调试来猜测混淆的真实信息。最终还原出这部分的代码,也就是对Buf1的内容进行了异或一次v28的内容,并且加上了循环变量x。

1
2
3
4
5
for (x = 0i64; x < 0x100; x++)
{
    Buf1[m * 0x100 + x] ^= v28[x];
    Buf1[m * 0x100 + x] += x;
}

还原这部分整体的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void encode()
{
    unsigned char Buf1[0x200], v28[0x100];
    int m, n, ii, jj, ll, kk, x;
    for (m = 0; m < 2; m++)
    {
        for (n = 0i64; n < 0x10; n++)
        {
            for (ii = 0i64; ii < 0x100; ii++)
                Buf1[m * 0x100 + ii] = table[(unsigned __int8)Buf1[m * 0x100 + ii]];
            for (jj = 1i64; jj < 0x11; jj++)
            {
                for (kk = 0i64; kk < 0x10; kk++)
                {
                    v28[16 * jj - 16 + kk] = ida_chars[kk + 16 * n] * jj;
                }
            }
            for (x = 0i64; x < 0x100; x++)
            {
                Buf1[m * 0x100 + x] ^= v28[x];
                Buf1[m * 0x100 + x] += x;
            }
        }
    }
}

3.编写解密程序

程序在最后部分,对Buf1的内容进行了比对用于判定输入的flag是否正确。

图片

而我们所需要做的就是从Buf2的内容反推到Buf1最初的内容,最后通过爆破来得到sha256之前的值。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <cstdio>
#include "defs.h"

unsigned char ida_chars[] =
{
  0x26, 0x27, 0xF6, 0x85, 0x97, 0x15, 0xAD, 0x1D, 0xD2, 0x94,
  0xDD, 0xC4, 0x76, 0x19, 0x39, 0x31, 0xF1, 0xAD, 0xB5, 0x58,
  0xF0, 0x93, 0x97, 0x32, 0x19, 0x2B, 0xD1, 0xC0, 0xFD, 0x16,
  0x8E, 0x4E, 0x48, 0x9B, 0x0B, 0xF5, 0x3B, 0x49, 0xA8, 0x63,
  0x5D, 0xDE, 0x3F, 0xDF, 0x6D, 0x68, 0xB4, 0x87, 0x9A, 0xAA,
  0xCD, 0xDC, 0xF7, 0xC1, 0x44, 0x81, 0x29, 0x08, 0x1B, 0x40,
  0x62, 0x38, 0x30, 0x4E, 0x94, 0xD4, 0x11, 0xD0, 0xDE, 0xC4,
  0x11, 0x9D, 0x4B, 0x3F, 0x9C, 0x46, 0xBB, 0xEF, 0xC7, 0x54,
  0x21, 0x50, 0x2B, 0xD0, 0xEF, 0x5A, 0xF4, 0x09, 0xCF, 0x5F,
  0x35, 0x91, 0x94, 0x36, 0x7F, 0x89, 0x70, 0x99, 0xB1, 0x1E,
  0x67, 0xCC, 0x11, 0x54, 0x03, 0x7F, 0x9C, 0x03, 0x4A, 0xF6,
  0x9B, 0x1E, 0xED, 0x67, 0x77, 0x3B, 0xC2, 0xA4, 0xCE, 0x50,
  0x74, 0xF9, 0xC6, 0xBB, 0x7A, 0x58, 0xA2, 0x86, 0x45, 0xB3,
  0x93, 0xE8, 0xBE, 0xAA, 0xD0, 0x0F, 0xEF, 0x66, 0xE8, 0x1C,
  0x00, 0xC5, 0x57, 0x70, 0x66, 0xB7, 0x58, 0x26, 0x57, 0xE8,
  0xFB, 0xE0, 0x81, 0x9F, 0x77, 0xC7, 0xFB, 0xE6, 0xC1, 0xCD,
  0x7C, 0xEB, 0x5E, 0x36, 0xCB, 0xA6, 0x75, 0x56, 0x76, 0xBC,
  0x28, 0x9C, 0xC7, 0xA3, 0x24, 0xCF, 0xF4, 0x07, 0x77, 0x98,
  0x96, 0x6D, 0xA3, 0x41, 0x5C, 0x17, 0xF0, 0xBC, 0x01, 0x27,
  0x06, 0xE7, 0x7B, 0x07, 0xBA, 0x0E, 0x76, 0x07, 0x29, 0xB1,
  0x00, 0x48, 0x03, 0x88, 0x86, 0xDA, 0x2A, 0xC5, 0xFF, 0x21,
  0x7C, 0x99, 0x67, 0x7D, 0xEC, 0xF9, 0x6F, 0x29, 0xD8, 0xA2,
  0x73, 0x64, 0x97, 0x5B, 0xAC, 0xCF, 0x51, 0x7A, 0xA7, 0x17,
  0x13, 0xA9, 0xF5, 0xD3, 0x22, 0xEA, 0x25, 0xB0, 0x90, 0xD9,
  0xEF, 0xCB, 0x0E, 0x31, 0xB2, 0x5E, 0x01, 0x92, 0x21, 0x9F,
  0xD8, 0x82, 0x38, 0xE5, 0x9C, 0xB1
};

unsigned char endata[] =
{
  0x2B, 0x75, 0xDD, 0x89, 0x55, 0x4C, 0x62, 0xE2, 0xF0, 0xFC,
  0x2A, 0x56, 0x51, 0x4D, 0x41, 0x44, 0x1E, 0x7C, 0x88, 0x17,
  0x92, 0xBD, 0xA5, 0xE6, 0xF1, 0xAD, 0x27, 0xE0, 0xE0, 0x19,
  0xFD, 0x3F, 0xC7, 0x5A, 0x87, 0xD2, 0xF9, 0x77, 0xD7, 0x26,
  0x7C, 0xA6, 0xCA, 0xBF, 0x72, 0x69, 0x03, 0x6B, 0xDE, 0x54,
  0xD0, 0xDD, 0xE6, 0x8A, 0x2E, 0xDE, 0x61, 0x47, 0x76, 0x5C,
  0xB2, 0x66, 0xB0, 0x9B, 0x77, 0xBC, 0xE4, 0x90, 0xDC, 0x57,
  0x9C, 0x81, 0x61, 0x63, 0x2D, 0x6D, 0xDB, 0x73, 0x1A, 0xE3,
  0x7E, 0xB7, 0xC2, 0x96, 0x68, 0x4C, 0xAC, 0x2E, 0x1F, 0x04,
  0x79, 0x0B, 0x37, 0xE3, 0x7E, 0xF6, 0x2E, 0x1D, 0x91, 0xF8,
  0x70, 0xF5, 0x7C, 0xDC, 0x16, 0x29, 0x9A, 0x14, 0xD9, 0xE8,
  0xE8, 0xF0, 0xB8, 0x9B, 0xA7, 0xD4, 0xE3, 0x87, 0xA8, 0x0D,
  0x36, 0x8C, 0x47, 0xA4, 0x37, 0x67, 0x7C, 0x9F, 0x18, 0xB0,
  0x39, 0xC3, 0xF9, 0x31, 0xB6, 0x2B, 0xC6, 0x21, 0x17, 0x74,
  0x47, 0x6A, 0x87, 0xDB, 0x3A, 0xAB, 0x1D, 0xFF, 0x14, 0x76,
  0xF2, 0x5E, 0x33, 0xC4, 0xCC, 0xAA, 0xFB, 0xA9, 0x39, 0x3F,
  0xFD, 0xD6, 0x64, 0xC6, 0x41, 0x5F, 0xB8, 0x70, 0xF3, 0x00,
  0x0F, 0x6D, 0xC6, 0x63, 0xFA, 0xC3, 0x36, 0xD3, 0x44, 0x12,
  0xE6, 0x9A, 0xCC, 0x36, 0xB0, 0x96, 0x60, 0x05, 0x03, 0x91,
  0x29, 0x22, 0xB7, 0x1A, 0xD1, 0x74, 0xB9, 0x9C, 0x6F, 0xA9,
  0x1E, 0x39, 0x90, 0x1D, 0xD8, 0xD1, 0x29, 0x83, 0xFA, 0x65,
  0xD9, 0x73, 0x1B, 0x69, 0x1E, 0xDD, 0xE1, 0x71, 0x11, 0xA6,
  0xB1, 0xD4, 0x44, 0x7E, 0x7D, 0xC4, 0xD9, 0x97, 0xF1, 0x45,
  0xA3, 0x34, 0x96, 0xD8, 0x64, 0x60, 0x51, 0x86, 0x13, 0xE6,
  0x79, 0x90, 0x7C, 0x22, 0x49, 0x9A, 0x33, 0xC8, 0x6D, 0x9C,
  0x1F, 0xC4, 0x69, 0x10, 0xB0, 0x15, 0xFC, 0x9A, 0xC8, 0xAC,
  0x2A, 0xDD, 0x84, 0xE4, 0xE5, 0x89, 0x0F, 0x8B, 0x69, 0x0E,
  0x3A, 0xFE, 0xE0, 0xE6, 0x98, 0x36, 0x65, 0x42, 0xF2, 0x66,
  0x40, 0x43, 0xBE, 0x26, 0x8F, 0x15, 0x58, 0x7A, 0x21, 0xEE,
  0xEB, 0xF0, 0x9D, 0xF7, 0x33, 0x4D, 0xAA, 0x3B, 0x63, 0xA6,
  0x0D, 0xB8, 0x3A, 0x4E, 0x11, 0x80, 0x36, 0x3F, 0xD0, 0xB4,
  0x5E, 0xBA, 0xBB, 0x92, 0x57, 0xF5, 0x7B, 0x33, 0xF9, 0x66,
  0xBB, 0xD2, 0xCE, 0xC8, 0x19, 0x8B, 0x1D, 0x67, 0x39, 0xAB,
  0xFF, 0x3D, 0xEA, 0x3F, 0xE6, 0x15, 0xFB, 0xA9, 0x46, 0x4F,
  0xFF, 0xF7, 0x00, 0xF5, 0x1F, 0xB6, 0x5F, 0xCE, 0x32, 0x2E,
  0x28, 0xD2, 0xF1, 0x21, 0x7E, 0x7A, 0xA3, 0x0C, 0xDE, 0x2E,
  0xBD, 0x1C, 0x88, 0x9E, 0x7F, 0x12, 0xCD, 0x59, 0x9D, 0x45,
  0x13, 0x45, 0x19, 0x75, 0x0F, 0x6B, 0xBA, 0x74, 0x20, 0x74,
  0x18, 0xA0, 0x89, 0xD3, 0x01, 0x63, 0xE6, 0x11, 0x34, 0x04,
  0x68, 0x5A, 0x6A, 0xB7, 0xB2, 0x36, 0x6E, 0x16, 0x6E, 0xA0,
  0x06, 0x52, 0xEC, 0x7C, 0x0F, 0xC0, 0x3D, 0x37, 0xCF, 0xDF,
  0x80, 0x74, 0x69, 0x20, 0x5D, 0xBE, 0x8C, 0xAB, 0x5E, 0x11,
  0x1A, 0x44, 0x4A, 0xE0, 0x6A, 0xAF, 0x3B, 0x04, 0x7D, 0x79,
  0x09, 0xE5, 0x46, 0x0E, 0xEE, 0x9D, 0x36, 0xA8, 0xB1, 0x39,
  0xB0, 0xF0, 0x5F, 0x02, 0x60, 0x63, 0xBB, 0xFB, 0xC4, 0xBB,
  0x01, 0xF4, 0x8A, 0xDE, 0x3C, 0x06, 0x90, 0x1F, 0x8C, 0x47,
  0xC4, 0x04, 0x8E, 0x9D, 0xBF, 0xAD, 0x95, 0x84, 0x68, 0x89,
  0x9A, 0x4F, 0xF4, 0x6B, 0x52, 0x73, 0x0D, 0xEC, 0x99, 0x83,
  0x61, 0x2F, 0xB3, 0x1B, 0x8F, 0xD8, 0x84, 0x1F, 0x91, 0xA6,
  0xBF, 0xBE, 0x63, 0xA0, 0xEE, 0x16, 0xD5, 0x70, 0x73, 0xFC,
  0xD9, 0x4E, 0x8E, 0xE0, 0x92, 0xEF, 0x4A, 0xEB, 0xEB, 0xCB,
  0x7E, 0xA7
};
unsigned char table[256], inv[256];

void encode()
{
    unsigned char Buf1[0x200], v28[0x100];
    int m, n, ii, jj, ll, kk, x;

    for (m = 0; m < 2; m++)
    {
        for (n = 0i64; n < 0x10; n++)
        {
            for (ii = 0i64; ii < 0x100; ii++)
                Buf1[m * 0x100 + ii] = table[(unsigned __int8)Buf1[m * 0x100 + ii]];
            for (jj = 1i64; jj < 0x11; jj++)
            {
                for (kk = 0i64; kk < 0x10; kk++)
                {
                    v28[16 * jj - 16 + kk] = ida_chars[kk + 16 * n] * jj;
                }
            }
            for (x = 0i64; x < 0x100; x++)
            {
                Buf1[m * 0x100 + x] ^= v28[x];
                Buf1[m * 0x100 + x] += x;
            }
        }
    }
}


void decode()
{
    unsigned char v28[0x100];
    for (int m = 1; m >= 0; m--)
    {
        for (int n = 0x10 - 1; n >= 0; n--)
        {
            for (int jj = 1i64; jj < 0x11; jj++)
            {
                for (int kk = 0i64; kk < 0x10; kk++)
                {
                    v28[16 * jj - 16 + kk] = ida_chars[kk + 16 * n] * jj;
                }
            }

            for (int x = 0x100 - 1; x >= 0; x--)
            {
                endata[m * 0x100 + x] -= x;
                endata[m * 0x100 + x] ^= v28[x];
            }
            for (int i = 0; i < 0x100; i++)
            {
                endata[m * 0x100 + i] = inv[endata[m * 0x100 + i]];
            }
        }
    }
}

int main()
{
    int k, l;
    for (k = 0i64; k < 0x10; k += (~k | 1) + (k | 1) + 1)
    {
        for (l = 0i64; l < 0x10; l = 2 * (l | 1) - ((l & 1) == 0) - ((l | 1) & 0xFFFFFFFFFFFFFFFEui64))
            table[16 * k + l] = 2 * (l | (16 * (15 - k))) - (l & ~(16 * (15 - k))) - (~(_BYTE)l & (l | (16 * (15 - k))));
    }
    for (int i = 0; i < 0x100; i++)  inv[table[i]] = i;

    //fun();
    decode();
    for (int i = 0; i < 0x10; i++)
    {
        printf("\"");
        for (int j = 0; j < 0x20; j++)
            printf("%02x", endata[i * 0x20 + j]);
        printf("\", \n");
    }
	return 0;
}

最后我们再将endata的数据导出,并使用python进行爆破。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import string
from hashlib import sha256
from tqdm import tqdm


def solve(sha, list):
    sz = len(sha)
    input = ["" for i in range(sz)]
    count = 0
    with tqdm(total=len(list) ** 4) as pbar:
        for i in list:
            for j in list:
                for k in list:
                    for l in list:
                        pbar.update(1)
                        en = i + j + k + l
                        s = sha256(en.encode()).hexdigest()
                        for n in range(sz):
                            if sha[n] == s:
                                count += 1
                                input[n] = en
                                if sz == count:
                                    return input
                                break
    print("error")
    exit(0)


data = ["6a7aa7c652828c0cb35e5bf1af01bace5cde7099b4f1711ab74dfdfa3c7d1f73",
        "e8f3319f242de58c4d308936200d3ee5fab8a8818aca3ece4d2772c07ade4ce3",
        "22db56772f1db2bf16bdf0367dcfbd15a07982985a5068227d404f2963ff283e",
        "c5ac1fa5b947b626b3f73d3d73cc29b6f043077cab47f88d8ecc7f9c4757c45f",
        "911383e076c35855ed8b4677a98e3c053051ed89da7aa6f2bd50b6e0874d0ba3",
        "2a0fb2bbb4d56a0aaab27c00b4ef0fdd6a47bc7eb2aa0c4674069ce13b11fd9a",
        "da6da393e2cad94781334dde4e4dae354c532929c1bd6af92b916fd0a54892b6",
        "fe1107763047291e7bfaab119bb2124409f0bcc219ca5398bdcc8f24c920a005",
        "bd81823f7d8fb2a246c35610f76ab1e0a21480d4233e569a46c3a42433c9d24a",
        "8e4f05e930adf1277b39d04fbfcc7724358ce64b2c548ebad70213d9b36b252e",
        "eedd647fda4133016e65c2e64c43696f253f2e259d33b4517dfa51f0c67ace9a",
        "9a10401b6ada34d4581ea7eb252e5cabd5fdc32d11d5cfab42f4a86c68b03143",
        "88d42ca6cb9afe44c1b95be960b2f52acc101cb6d1f4997b616f0ad6f554174e",
        "5b1e18308f8a889a93ed50810fbdcc5f1ac24ef92278915974d823b6182b5773",
        "a908b3133180f238cf5949b042d0d90789db1d92325dae533e6b04e939403737",
        "e2f67582ae662e1d7c10085349644fb4e59013fc895e8e9042bf9a2b4b7bce97"]
de = solve(data, string.ascii_lowercase + string.ascii_uppercase + string.digits + "{}^_")
flag = ""
for i in de:
    flag += i
print(flag)

4.检验flag

图片

0%