Babyre

IDA打开分析,TLS中有反调试,直接patch

来到主函数分析加密算法,主逻辑是个魔改的xtea算法

直接调试取出key和密文,写对应的解密逻辑解密即可

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
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(uint32_t v[2], uint32_t const key[4]) {
unsigned int i, j;
uint32_t v0 = v[0], v1 = v[1], sum = 0x90508D47;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 33; ++j)
{
v0 += (((32 * v1) ^ (v1 >> 4)) + v1) ^ (sum + key[sum & 3]) ^ sum;
v1 += (((32 * v0) ^ (v0 >> 4)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= 0x77BF7F99;
}
}
v[0] = v0; v[1] = v1;
}
void decipher(uint32_t v[2], uint32_t const key[4]) {
unsigned int i, j;
uint32_t v0 = v[0], v1 = v[1], sum = 0x90508D47;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 33; ++j)
{
sum -= 0x77BF7F99;
}
}
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 33; ++j)
{
sum += 0x77BF7F99;
v1 -= (((32 * v0) ^ (v0 >> 4)) + v0) ^ (sum + key[(sum >> 11) & 3]);
v0 -= (((32 * v1) ^ (v1 >> 4)) + v1) ^ (sum + key[sum & 3]) ^ sum;
}
}


v[0] = v0; v[1] = v1;
}


int main()
{
//char flag[] = "123456789012345678901234567890ab";
char flag[] = { 0xE0, 0xF2, 0x23, 0x95, 0x93, 0xC2, 0xD8, 0x8E, 0x93, 0xC3, 0x68, 0x86, 0xBC, 0x50, 0xF2, 0xDD, 0x99, 0x44, 0x0E, 0x51, 0x44, 0xBD, 0x60, 0x8C, 0xF2, 0xAB, 0xDC, 0x34, 0x60, 0xD2, 0x0F, 0xC1 ,0};
uint32_t * v = (uint32_t *)flag;
uint32_t const k[4] = { 0x62, 0x6F, 0x6D, 0x62 };

//for (int i = 0; i < 4; i++)
//{
// encipher(&v[2 * i], k);
//}

for (int i = 0; i < 4; i++)
{
decipher(&v[2 * i], k);
}

printf("%s", flag);
return 0;
}
//W31com3_2_Th3_QwbS7_4nd_H4v3_Fun

Flag为 flag{W31com3_2_Th3_QwbS7_4nd_H4v3_Fun}

dotdot

输入16位的key,将16位的key打乱,然后重组与密文对比,对比成功,用key进行RC4解密得到license.dat。爆破可解,用C爆破

贴出正向的代码

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
from utils_date import *

def GGG(v16):
array = bytearray(16)
array2 = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11]

for i in range(16):
array[i] = v16[array2[i]]

v16[:16] = array

def inverse_GGG(v16):
array = bytearray(16)
array2 = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11]

for i in range(16):
array[array2[i]] = v16[i]

v16[:16] = array

if __name__ == "__main__":
aaa = [ # 模拟输入。aaa是最终要解密的key
0x31,
0x32,
0x33,
0x34,
0x35,
0x36,
0x37,
0x38,
0x39,
0x30,
0x61,
0x62,
0x63,
0x64,
0x65,
0x66,
]

for i in range(9):
GGG(aaa)
for j in range(4):
num = v11[i][4 * j][aaa[4 * j]]
num2 = v11[i][4 * j + 1][aaa[4 * j + 1]]
num3 = v11[i][4 * j + 2][aaa[4 * j + 2]]
num4 = v11[i][4 * j + 3][aaa[4 * j + 3]]

num5 = v12[(num >> 28 & 0xF)][(num2 >> 28 & 0xF)]
num6 = v12[(num3 >> 28 & 0xF)][(num4 >> 28 & 0xF)]
num7 = v12[(num >> 24 & 0xF)][(num2 >> 24 & 0xF)]
num8 = v12[(num3 >> 24 & 0xF)][(num4 >> 24 & 0xF)]

aaa[4 * j] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 20 & 0xF)][(num2 >> 20 & 0xF)]
num6 = v12[(num3 >> 20 & 0xF)][(num4 >> 20 & 0xF)]
num7 = v12[(num >> 16 & 0xF)][(num2 >> 16 & 0xF)]
num8 = v12[(num3 >> 16 & 0xF)][(num4 >> 16 & 0xF)]

aaa[4 * j + 1] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 12 & 0xF)][(num2 >> 12 & 0xF)]
num6 = v12[(num3 >> 12 & 0xF)][(num4 >> 12 & 0xF)]
num7 = v12[(num >> 8 & 0xF)][(num2 >> 8 & 0xF)]
num8 = v12[(num3 >> 8 & 0xF)][(num4 >> 8 & 0xF)]

aaa[4 * j + 2] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 4 & 0xF)][(num2 >> 4 & 0xF)]
num6 = v12[(num3 >> 4 & 0xF)][(num4 >> 4 & 0xF)]
num7 = v12[(num & 0xF)][(num2 & 0xF)]
num8 = v12[(num3 & 0xF)][(num4 & 0xF)]

aaa[4 * j + 3] = v12[num5][num6] << 4 | v12[num7][num8]

num = v13[i][4 * j][aaa[4 * j]]
num2 = v13[i][4 * j + 1][aaa[4 * j + 1]]
num3 = v13[i][4 * j + 2][aaa[4 * j + 2]]
num4 = v13[i][4 * j + 3][aaa[4 * j + 3]]

num5 = v12[(num >> 28 & 0xF)][(num2 >> 28 & 0xF)]
num6 = v12[(num3 >> 28 & 0xF)][(num4 >> 28 & 0xF)]
num7 = v12[(num >> 24 & 0xF)][(num2 >> 24 & 0xF)]
num8 = v12[(num3 >> 24 & 0xF)][(num4 >> 24 & 0xF)]

aaa[4 * j] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 20 & 0xF)][(num2 >> 20 & 0xF)]
num6 = v12[(num3 >> 20 & 0xF)][(num4 >> 20 & 0xF)]
num7 = v12[(num >> 16 & 0xF)][(num2 >> 16 & 0xF)]
num8 = v12[(num3 >> 16 & 0xF)][(num4 >> 16 & 0xF)]

aaa[4 * j + 1] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 12 & 0xF)][(num2 >> 12 & 0xF)]
num6 = v12[(num3 >> 12 & 0xF)][(num4 >> 12 & 0xF)]
num7 = v12[(num >> 8 & 0xF)][(num2 >> 8 & 0xF)]
num8 = v12[(num3 >> 8 & 0xF)][(num4 >> 8 & 0xF)]

aaa[4 * j + 2] = v12[num5][num6] << 4 | v12[num7][num8]

num5 = v12[(num >> 4 & 0xF)][(num2 >> 4 & 0xF)]
num6 = v12[(num3 >> 4 & 0xF)][(num4 >> 4 & 0xF)]
num7 = v12[(num & 0xF)][(num2 & 0xF)]
num8 = v12[(num3 & 0xF)][(num4 & 0xF)]

aaa[4 * j + 3] = v12[num5][num6] << 4 | v12[num7][num8]

print(i, j, aaa, end="\n------------------\n")
# exit(-1)

GGG(aaa)
for k in range(16):
aaa[k] = v14[9][k][aaa[k]]

print(aaa)
bbb = [hex(i) for i in aaa]
print(bbb)

# 最终对比的密文, 即上面的bbb的结果应该是 [0x61, 0x93, 0x31, 0x7B, 0xF8, 0x96, 0xE0, 0x00, 0xA5, 0x27, 0xB7, 0x37, 0x4A, 0xE3, 0x03, 0xA8]

utils_date是我自己定义的,用到的数据都在里面(每次运行都一样), 太大了,直接调试获取数据即可

逻辑就是通过bbb,即[0x61, 0x93, 0x31, 0x7B, 0xF8, 0x96, 0xE0, 0x00, 0xA5, 0x27, 0xB7, 0x37, 0x4A, 0xE3, 0x03, 0xA8]反推出aaa就可以了,应该是需要爆破

先逆第一层

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
from utils_date import *

def inverse_GGG(v16):
array = bytearray(16)
array2 = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11]

for i in range(16):
array[array2[i]] = v16[i]

v16[:16] = array

a = [
0x61,
0x93,
0x31,
0x7B,
0xF8,
0x96,
0xE0,
0x00,
0xA5,
0x27,
0xB7,
0x37,
0x4A,
0xE3,
0x03,
0xA8,
]
for k in range(16):
a[k] = v14[9][k].index(a[k])

# print(a)
inverse_GGG(a)
print(a)

# [84, 198, 121, 220, 8, 66, 11, 175, 66, 40, 248, 34, 82, 252, 193, 146]
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

#include <windows.h>
#include <stdio.h>

char v3[] = {}; //数据太大
char v1[] = {}; //。。。
char v4[] = {};//。。。
int * v13_int = (int *)v3;
int (*v13)[0x10][0x100] = (int (*)[0x10][0x100]) v13_int;
int * v11_int = (int *)v1;
int(*v11)[0x10][0x100] = (int(*)[0x10][0x100]) v11_int;
unsigned char (*v14)[0x10][0x100] = (unsigned char (*)[0x10][0x100]) v4;
unsigned char v12[16][16] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
{2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13},
{3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
{4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11},
{5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10},
{6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9},
{7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8},
{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7},
{9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6},
{10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5},
{11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4},
{12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3},
{13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2},
{14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1},
{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
unsigned char v12[16][16] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
{2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13},
{3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
{4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11},
{5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10},
{6, 7, 4, 5, 2, 3, 0, 1, 14, 15, 12, 13, 10, 11, 8, 9},
{7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8},
{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7},
{9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6},
{10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5},
{11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4},
{12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3},
{13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2},
{14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1},
{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}};

void GGG(unsigned char v16[]) {
unsigned char array[16];
unsigned char array2[] = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 };

for (int i = 0; i < 16; i++) {
array[i] = v16[array2[i]];
}

for (int i = 0; i < 16; i++) {
v16[i] = array[i];
}
}


void inverse_GGG(unsigned char v16[]) {
unsigned char array[16];
unsigned char array2[] = { 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11 };

for (int i = 0; i < 16; i++) {
array[array2[i]] = v16[i];
}

for (int i = 0; i < 16; i++) {
v16[i] = array[i];
}
}

int baopo(unsigned char* res, int i, int j, unsigned char* target)
{
//res保存返回结果,即index1, index2, index3, index4
//i, j保存每次循环的轮数
//target保存要爆破的结果

unsigned char aaa[16] = {0};
unsigned int num, num2, num3, num4;
unsigned int num5, num6, num7, num8;
unsigned int index1, index2, index3, index4;
for (index1 = 0; index1 < 256; index1++)
{
printf("%d %d %d\r", i, j, index1);
for (index2 = 0; index2 < 256; index2++)
{
for (index3 = 0; index3 < 256; index3++)
{
for (index4 = 0; index4 < 256; index4++)
{
num = v11[i][4 * j][index1];
num2 = v11[i][4 * j + 1][index2];
num3 = v11[i][4 * j + 2][index3];
num4 = v11[i][4 * j + 3][index4];

num5 = v12[(num >> 28 & 0xF)][(num2 >> 28 & 0xF)];
num6 = v12[(num3 >> 28 & 0xF)][(num4 >> 28 & 0xF)];
num7 = v12[(num >> 24 & 0xF)][(num2 >> 24 & 0xF)];
num8 = v12[(num3 >> 24 & 0xF)][(num4 >> 24 & 0xF)];

aaa[4 * j] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 20 & 0xF)][(num2 >> 20 & 0xF)];
num6 = v12[(num3 >> 20 & 0xF)][(num4 >> 20 & 0xF)];
num7 = v12[(num >> 16 & 0xF)][(num2 >> 16 & 0xF)];
num8 = v12[(num3 >> 16 & 0xF)][(num4 >> 16 & 0xF)];

aaa[4 * j + 1] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 12 & 0xF)][(num2 >> 12 & 0xF)];
num6 = v12[(num3 >> 12 & 0xF)][(num4 >> 12 & 0xF)];
num7 = v12[(num >> 8 & 0xF)][(num2 >> 8 & 0xF)];
num8 = v12[(num3 >> 8 & 0xF)][(num4 >> 8 & 0xF)];

aaa[4 * j + 2] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 4 & 0xF)][(num2 >> 4 & 0xF)];
num6 = v12[(num3 >> 4 & 0xF)][(num4 >> 4 & 0xF)];
num7 = v12[(num & 0xF)][(num2 & 0xF)];
num8 = v12[(num3 & 0xF)][(num4 & 0xF)];

aaa[4 * j + 3] = v12[num5][num6] << 4 | v12[num7][num8];


num = v13[i][4 * j][aaa[4 * j]];
num2 = v13[i][4 * j + 1][aaa[4 * j + 1]];
num3 = v13[i][4 * j + 2][aaa[4 * j + 2]];
num4 = v13[i][4 * j + 3][aaa[4 * j + 3]];

num5 = v12[(num >> 28 & 0xF)][(num2 >> 28 & 0xF)];
num6 = v12[(num3 >> 28 & 0xF)][(num4 >> 28 & 0xF)];
num7 = v12[(num >> 24 & 0xF)][(num2 >> 24 & 0xF)];
num8 = v12[(num3 >> 24 & 0xF)][(num4 >> 24 & 0xF)];

aaa[4 * j] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 20 & 0xF)][(num2 >> 20 & 0xF)];
num6 = v12[(num3 >> 20 & 0xF)][(num4 >> 20 & 0xF)];
num7 = v12[(num >> 16 & 0xF)][(num2 >> 16 & 0xF)];
num8 = v12[(num3 >> 16 & 0xF)][(num4 >> 16 & 0xF)];

aaa[4 * j + 1] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 12 & 0xF)][(num2 >> 12 & 0xF)];
num6 = v12[(num3 >> 12 & 0xF)][(num4 >> 12 & 0xF)];
num7 = v12[(num >> 8 & 0xF)][(num2 >> 8 & 0xF)];
num8 = v12[(num3 >> 8 & 0xF)][(num4 >> 8 & 0xF)];

aaa[4 * j + 2] = v12[num5][num6] << 4 | v12[num7][num8];

num5 = v12[(num >> 4 & 0xF)][(num2 >> 4 & 0xF)];
num6 = v12[(num3 >> 4 & 0xF)][(num4 >> 4 & 0xF)];
num7 = v12[(num & 0xF)][(num2 & 0xF)];
num8 = v12[(num3 & 0xF)][(num4 & 0xF)];

aaa[4 * j + 3] = v12[num5][num6] << 4 | v12[num7][num8];

if (aaa[4 * j] == target[0] && aaa[4 * j + 1] == target[1] && aaa[4 * j + 2] == target[2] && aaa[4 * j + 3] == target[3])
{
printf("baopo success\n");
printf("0x%02X 0x%02X 0x%02X 0x%02X\n", index1, index2, index3, index4);
res[0] = index1;
res[1] = index2;
res[2] = index3;
res[3] = index4;
return 0;
}
}
}
}
}

printf("baopo failed\n");
return -1;
}

int main()
{
int i = 0, j = 0;
unsigned char res[4][4] = { 0 };
//unsigned char enddate[4][4] = { 0x45, 0xB2, 0xBB, 0xBE, 0x9E, 0x57, 0xF7, 0x2E, 0x23, 0xB1, 0x2B, 0xD7, 0x70, 0xD6, 0x80, 0x4E };
unsigned char enddate[4][4] = { 84, 198, 121, 220, 8, 66, 11, 175, 66, 40, 248, 34, 82, 252, 193, 146 };

for (int k = 0; k < 4; k++)
{
for (int m = 0; m < 4; m++)
{
res[k][m] = enddate[k][m];
}
}
for (i = 8; i >=0; i--)
{
for (j = 3; j >=0; j--)
{
baopo(&res[j][0], i, j, &res[j][0]);
}

inverse_GGG((unsigned char *)res);
printf("RES -->");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {

printf("0x%02X ", res[i][j]);
}
}
printf("\n");
}



for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {

printf("0x%02X ", res[i][j]);
}
}

return 0;
}

最终爆破res是WelcomeToQWB2023,这是RC4的key,解密license.dat,发现里面有FFF函数,去观察FFF函数

FFF函数tea解密得到b

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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0xDEADBEEF; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0; v[1] = v1;
}

//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xDEADBEEF * 32, i; /* set up */
uint32_t delta = 0xDEADBEEF; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}

int main()
{
uint32_t k[4] = { 0x636C6557,0x54656D6F,0x4257516F,0x33323032 };
char v28[24] = {0x45, 0xB6, 0xAB, 0x21, 0x79, 0x6B, 0xFE, 0x96, 0x5C, 0x1D, 0x04, 0xB2, 0x8A, 0xA6, 0xB8, 0x6A,
0x35, 0xF1, 0x2A, 0xBF, 0x17, 0xD3, 0x03, 0x6B };
uint32_t* encc = (uint32_t*)v28;

for (int i = 0; i < 3; i++)
{
decrypt(&encc[2 * i], k);
}

printf("%s", encc);
//dotN3t_Is_1nt3r3sting
return 0;
}

程序在执行binaryFormatter.Deserialize(memoryStream); 老是失败,结合题目提示Fix the lincense,再加上解密后的Lincense.dat并不包含FFF的参数dotN3t_Is_1nt3r3sting 和WelcomeToQWB2023,需要修复下V7,即RC4解密后的Lincense.dat,

自己写了点C#代码,序列化对象观察对应的dat文件

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
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public SerializableAction MyFunction;

public void ExecuteFunction()
{
MyFunction?.Invoke();
}
}

[Serializable]
class SerializableAction : ISerializable
{
public string Parameter1 { get; set; }
public string Parameter2 { get; set; }

public SerializableAction()
{
}

public SerializableAction(SerializationInfo info, StreamingContext context)
{
Parameter1 = info.GetString("Parameter1");
Parameter2 = info.GetString("Parameter2");
Invoke();
}

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Parameter1", Parameter1);
info.AddValue("Parameter2", Parameter2);
}

public void Invoke()
{
Console.WriteLine($"Parameter1: {Parameter1}, Parameter2: {Parameter2}");
}
}

class Program
{
static void Main()
{
// 创建要序列化的对象
var obj = new MyClass
{
Id = 1,
Name = "Example",
MyFunction = new SerializableAction
{
Parameter1 = "WelcomeToQWB2023",
Parameter2 = "dotN3t_Is_1nt3r3sting"
}
};

// 创建 BinaryFormatter 对象
var formatter = new BinaryFormatter();

// 创建文件流
var fileStream = new FileStream("serialized_object.dat", FileMode.Create);

try
{
// 使用 BinaryFormatter 将对象序列化到文件流中
formatter.Serialize(fileStream, obj);
Console.WriteLine("对象已成功序列化并保存到文件中!");
}
catch (Exception ex)
{
Console.WriteLine("序列化对象时出现错误:" + ex.Message);
}
finally
{
// 关闭文件流
fileStream.Close();
}
}
}

发现是先小端形式保存大小,再后面跟着字符串,直接找Lincense.dat找对应的空闲空间

将其补入

直接调试起来,修改对应的V7

可以发现反序列化成功,flag直接被打印了出来

flag为flag{d0tN3t_I5_Ea57_2_y09!G00d_Luck}

ezre

D-810插件去混淆, 去混淆后SM4算法

密文: 067519471663887C8B6655FF3F7D0D4AF5D24E383FE9C2DEDB7C7F6F74B11F3C

KEY: 0123456789abcdef0123456789abcdef

直接在线网站解密即可

flag: flag{h3kk0_w0rld_sur3_3n0ugh}

unname

初步看,flag的check逻辑在so文件里

但是apk没有加android:extractNativeLibs="true" 所以没法调试so,用脚本给apk这个属性设置为true且重新打包签名

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
import sys
import subprocess
import os
from xml.dom.minidom import parse

# 1、先解包APK
# 2、打开xml文件分析,android:debuggable 和 android:extractNativeLibs属性
# 3、如果没有android:debuggable,则可以加入并且设置为属性为 true
# 4、如果有android:debuggable, 则直接设置为true
# 5、如果没有android:extractNativeLibs 则不管,如果有且为false,则改为true
# 6、apktool重新打包
# 7、生成签名文件
# 8、将签名加入到apk中

def handle_xml():
# 3,4,5 处理XML文件并写回
# AndroidManifest.xml
dom = parse("AndroidManifest.xml")
data = dom.documentElement
# android:extractNativeLibs="true"
# android:debuggable="true"
application = data.getElementsByTagName("application")
print("[+] 正在修改 android:debuggable 属性")
application[0].setAttribute("android:debuggable", "true")
if application[0].getAttribute("android:extractNativeLibs") == 'false':
print("[+] 正在修改android:extractNativeLibs 属性")
application[0].setAttribute("android:extractNativeLibs", "true")
f = open("AndroidManifest.xml", 'w')
dom.writexml(f, encoding="utf-8")
f.close()
with open("AndroidManifest.xml", "r", encoding="utf-8") as f:
c = f.read()
c = c.replace('encoding="utf-8"', 'encoding="utf-8" standalone="no"')
f.close()
with open("AndroidManifest.xml", "w", encoding="utf-8")as f:
f.write(c)

if __name__ == "__main__":
if len(sys.argv) != 2:
print("[X] 格式有错! python后跟apk名字")
sys.exit(-1)

apkpath = sys.argv[1]
apkname = os.path.splitext(apkpath)[0]
apkdirpath = apkname + "_DIR"
# 1、解包APK
print("[+] 解包APK文件")
subprocess.run(['apktool.bat', 'd', apkpath, "-o", apkdirpath])
os.chdir(apkdirpath)
# 2、打开xml文件
print("[+] 当前工作路径为: " + os.getcwd())
handle_xml()
print("[+] 修改XML文件成功")
# 6、重新打包为APK
os.chdir('../')
print("[+] 重新打包APK文件")
print("[+] 当前工作路径为: " + os.getcwd())
apkpath_new = apkname + "_new.apk"
subprocess.run(['apktool.bat', 'b', apkdirpath, "-o", apkpath_new])
# 7、生成签名文件
print("[+] 密码请输入123456,否则会出错")
# keytool -genkey -keystore 签名文件的文件名 -keyalg RSA -validity 10000 -alias 签名文件别名
subprocess.run(['keytool', '-genkey', '-keystore', apkname + "_new.keystore",
'-keyalg', 'RSA', '-validity', '10000', '-alias', apkname])
# 8、给APK文件添加签名
print(f"[+] 给{apkname}_new.apk添加签名")
subprocess.run(['jarsigner.exe', '-verbose', '-keystore', apkname + "_new.keystore", '-storepass', '123456', '-signedjar',
apkname + '_new_sign.apk', '-digestalg', 'SHA1', '-sigalg', 'MD5withRSA', apkname + "_new.apk", apkname])

调试起来

找到了关键验证逻辑

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
do
{
while ( 1 )
{
v62 = v50 & 7;
if ( (v50 & 3) != 0 )
break;
v53 = (char *)&unk_7AA8BD6750 + 2 * v62;// v53 = unk_7AA8BC0750[2*v62]
v54 = (int64x2_t *)&ptr[4 * (v50 >> 2)];// v54 为QWORD v54[2] [0x465F5530595F4E6F, 0xB378E3C5C3A47B89]
v55 = vaddq_s64(v54[1], v52); // v55 = vaddq_s64(0xB378E3C5C3A47B89, [0x3433323130393837, 0x6261303938373635])
v56 = v54->n128_u64[1] + *((_QWORD *)&flag_0 + 1);// v54[1] + flag0[1] flag0是QWORD [2]类型 v56 = 0xB378E3C5C3A47B89 +0x3635343332313039
// 即v56 = 0xe9ae17f8f5d5abc2
x11 = v54->n128_u64[0] + flag_0 + v56;// x11 = v54[0] + flag0[0] + v56 = 0x465F5530595F4E6F + 0x3837363534333231 + 0xe9ae17f8f5d5abc2
// x11 = 0x6844a35e83682c62
x12 = __ROR8__(v56, -*v53) ^ x11;// ROR8(v56, -0xe) ^ x11| 0x85fe3d756af0ba6b ^ v11 =0x85fe3d756af0ba6b ^0x6844a35e83682c62
// x12 = 0xedba9e2be9989609
*(_QWORD *)&flag_0 = x11; // flag_0[0] = x11(0x6844a35e83682c62)
v59 = __ROR8__(v55.n128_u64[1], -v53[1]);// v59 = ROR8(v55[1], -16)
// v59 = 0x6779797C887CB6D5
// v55[1]=0XB6D56779797C887C
v52.n128_u64[1] = x12; // v52[1] = 0xedba9e2be9989609
x13 = vaddvq_s64(v55); // x13 = vaddvq_s64(v55) = 0xBEAD2E3D5A3D5376
x14 = v59 ^ x13; // x14 = 0x6779797C887CB6D5 ^ 0xBEAD2E3D5A3D5376
// x14 = 0xd9d45741d241e5a3
*((_QWORD *)&flag_0 + 1) = x14; // flag0[1] = x14 = 0xd9d45741d241e5a3
++v50;
v52.n128_u64[0] = x13; // v52[0] = 0xBEAD2E3D5A3D5376
if ( v50 == 72 )
goto LABEL_147;
}
v63 = (char *)&unk_7AA8BD6750 + 2 * v62;// v63 = (char *)&unk_7AA8BC0750[2]
x11 = *((_QWORD *)&flag_0 + 1) + flag_0;// x11 =0xd9d45741d241e5a3+ 0x6844a35e83682c62
// x11 = 0x4218FAA055AA1205

*(_QWORD *)&flag_0 = x11; // flag0[0] = x11(0x4218FAA055AA1205)
x12 = __ROR8__(*((_QWORD *)&flag_0 + 1), -*v63) ^ x11;// ROR8( 0xd9d45741d241e5a3, -0X34) ^ 0x4218FAA055AA1205
// x12 = 0x182567e521b7361b
v52.n128_u64[0] = vaddvq_s64(v52);// v52[0] = 0xBEAD2E3D5A3D5376 + 0xedba9e2be9989609
// v52[0] = 0xAC67CC6943D5E97F
v64 = __ROR8__(v52.n128_u64[1], -v63[1]);// v64 = ROR8(v52[1], -0X39) = 0x13db753c57d3312c
x13 = v52.n128_u64[0]; // x13 = 0xAC67CC6943D5E97F
v52.n128_u64[1] = x12; // v52[1] = x12 = 0x182567e521b7361b
x14 = v64 ^ v52.n128_u64[0]; // x14 = 0x13db753c57d3312c ^0xAC67CC6943D5E97F
// x14 = 0xbfbcb9551406d853
*((_QWORD *)&flag_0 + 1) = x14; // flag0[1] = x14
++v50;
}
while ( v50 != 72 );

模拟了一遍程序逻辑

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
#include <stdio.h>


unsigned long long key[80] = {
0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455247,
0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6366,
0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E71,
0x5474374041455247, 0x823ECE10EBF188BE, 0xBAD39663B0B3ADD3, 0x6523745F644E5633,
0x33E95EAA8C9B6365, 0xBAD39663B0B3ADD3, 0x9F44A2B46C50D06D, 0x5F30535F59333363,
0x465F5530595F4E6F, 0x9F44A2B46C50D06D, 0xAD85C2C5B88958B8, 0x547437404145524C,
0x6523745F644E5630, 0xAD85C2C5B88958B8, 0xC8E878739899B1AB, 0x33E95EAA8C9B636B,
0x5F30535F5933335F, 0xC8E878739899B1AB, 0x6E0A8CFF949DDDA2, 0x465F5530595F4E76,
0x5474374041455247, 0x6E0A8CFF949DDDA2, 0x94B4C496B8B573C8, 0x6523745F644E5638,
0x33E95EAA8C9B6365, 0x94B4C496B8B573C8, 0xD997B592BBA2B594, 0x5F30535F59333368,
0x465F5530595F4E6F, 0xD997B592BBA2B594, 0x995181B46135AD9C, 0x5474374041455251,
0x6523745F644E5630, 0x995181B46135AD9C, 0xA2C9A6A6A09B77A0, 0x33E95EAA8C9B6370,
0x5F30535F5933335F, 0xA2C9A6A6A09B77A0, 0xA85D9FDDE3EFC2C9, 0x465F5530595F4E7B,
0x5474374041455247, 0xA85D9FDDE3EFC2C9, 0x808083856161C8AC, 0x6523745F644E563D,
0x33E95EAA8C9B6365, 0x808083856161C8AC, 0xB378E3C5C3A47B89, 0x5F30535F5933336D,
0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455256,
0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6375,
0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E80,
0x0000007A414B22C2, 0x0000000000000028, 0x0000000000000000, 0xB400007B596C6C00,
0xB400007A99ABAC40, 0x0000000000000010, 0x0000000000000010, 0x0000000000000001
};

//x11, x12, x13, x14最终的结果
unsigned long long res[4] = {
0x13c17ce8fc8b8157,
0x477d6619faa7d1c7,
0x6096448f5a2d874c,
0x645d9ac2d095d15b
};

unsigned char ror_num[16] = {
0x0E, 0x10, 0x34, 0x39, 0x17, 0x28, 0x05, 0x25, 0x19, 0x21, 0x2E, 0x0C, 0x3A, 0x16, 0x20, 0x20
};

unsigned long long rotateRight64(unsigned long long num, unsigned int shift)
{
unsigned int bits = sizeof(unsigned long long) * 8;
shift = shift % bits; // 确保位移值在合理范围内

if (shift == 0)
return num;

return (num >> shift) | (num << (bits - shift));
}


void vaddq_s64(unsigned long long* a, unsigned long long* b, unsigned long long * res)
{
res[0] = a[0] + b[0];
res[1] = a[1] + b[1];
}

unsigned long long vaddvq_s64(unsigned long long* a)
{
return a[0] + a[1];
}


int main()
{
//模拟输入
unsigned long long input[4] = {
0x3837363534333231, 0x3635343332313039, 0x3433323130393837, 0x6261303938373635
};
int v50 = 0;
int v62 = 0;
unsigned char * v53, * v63;
unsigned long long* v54;
unsigned long long v55[2] = { 0 };
unsigned long long * v52 = &input[2];
unsigned long long v56, v59, v64;
unsigned long long x11, x12, x13, x14;
do {
while (1)
{
v62 = v50 % 8;
if (v50 % 4 != 0)
{
break;
}
v53 = &ror_num[2 * v62];
v54 = &key[4 * (v50 >> 2)];
vaddq_s64(v54+2, &input[2], v55);
v56 = v54[1] + input[1];
x11 = v54[0] + input[0] + v56;
x12 = rotateRight64(v56, 64 - v53[0]) ^ x11;
input[0] = x11;
v59 = rotateRight64(v55[1], 64 - v53[1]);
v52[1] = x12;
x13 = vaddvq_s64(v55);
x14 = v59 ^ x13;
input[1] = x14;
v50++;
v52[0] = x13;
printf("v50: %d\n", v50);
printf("0x%llX\n", x11);
printf("0x%llX\n", x12);
printf("0x%llX\n", x13);
printf("0x%llX\n", x14);
printf("-----------------------------------\n");
if (v50 == 72)
goto LABEL_147;
}
v63 = &ror_num[2 * v62];
x11 = input[1] + input[0];
input[0] = x11;
x12 = rotateRight64(input[1], 64 - v63[0]) ^ x11;
v52[0] = vaddvq_s64(v52);
v64 = rotateRight64(v52[1], 64 - v63[1]);
x13 = v52[0];
v52[1] = x12;
x14 = v64 ^ v52[0];

input[1] = x14;

++v50;
printf("v50: %d\n", v50);
printf("0x%llX\n", x11);
printf("0x%llX\n", x12);
printf("0x%llX\n", x13);
printf("0x%llX\n", x14);
printf("-----------------------------------\n");
} while (v50 != 72);


LABEL_147:

x11 = 0xbad39663b0b3add3 + x13;


printf("end\n");
printf("0x%llX\n", x11);
printf("0x%llX\n", x12);
printf("0x%llX\n", x13);
printf("0x%llX\n", x14);



return 0;
}

逆回去

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
#include <stdio.h>


unsigned long long key[80] = {
0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455247,
0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6366,
0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E71,
0x5474374041455247, 0x823ECE10EBF188BE, 0xBAD39663B0B3ADD3, 0x6523745F644E5633,
0x33E95EAA8C9B6365, 0xBAD39663B0B3ADD3, 0x9F44A2B46C50D06D, 0x5F30535F59333363,
0x465F5530595F4E6F, 0x9F44A2B46C50D06D, 0xAD85C2C5B88958B8, 0x547437404145524C,
0x6523745F644E5630, 0xAD85C2C5B88958B8, 0xC8E878739899B1AB, 0x33E95EAA8C9B636B,
0x5F30535F5933335F, 0xC8E878739899B1AB, 0x6E0A8CFF949DDDA2, 0x465F5530595F4E76,
0x5474374041455247, 0x6E0A8CFF949DDDA2, 0x94B4C496B8B573C8, 0x6523745F644E5638,
0x33E95EAA8C9B6365, 0x94B4C496B8B573C8, 0xD997B592BBA2B594, 0x5F30535F59333368,
0x465F5530595F4E6F, 0xD997B592BBA2B594, 0x995181B46135AD9C, 0x5474374041455251,
0x6523745F644E5630, 0x995181B46135AD9C, 0xA2C9A6A6A09B77A0, 0x33E95EAA8C9B6370,
0x5F30535F5933335F, 0xA2C9A6A6A09B77A0, 0xA85D9FDDE3EFC2C9, 0x465F5530595F4E7B,
0x5474374041455247, 0xA85D9FDDE3EFC2C9, 0x808083856161C8AC, 0x6523745F644E563D,
0x33E95EAA8C9B6365, 0x808083856161C8AC, 0xB378E3C5C3A47B89, 0x5F30535F5933336D,
0x465F5530595F4E6F, 0xB378E3C5C3A47B89, 0xD3A49492B08792C3, 0x5474374041455256,
0x6523745F644E5630, 0xD3A49492B08792C3, 0x8E9565954947CC84, 0x33E95EAA8C9B6375,
0x5F30535F5933335F, 0x8E9565954947CC84, 0x823ECE10EBF188BE, 0x465F5530595F4E80,
0x0000007A414B22C2, 0x0000000000000028, 0x0000000000000000, 0xB400007B596C6C00,
0xB400007A99ABAC40, 0x0000000000000010, 0x0000000000000010, 0x0000000000000001
};

//x11, x12, x13, x14最终的结果
unsigned long long res[4] = {
0x13c17ce8fc8b8157,
0x477d6619faa7d1c7,
0x6096448f5a2d874c,
0x645d9ac2d095d15b
};

unsigned char ror_num[16] = {
0x0E, 0x10, 0x34, 0x39, 0x17, 0x28, 0x05, 0x25, 0x19, 0x21, 0x2E, 0x0C, 0x3A, 0x16, 0x20, 0x20
};

unsigned long long rotateRight64(unsigned long long num, unsigned int shift)
{
unsigned int bits = sizeof(unsigned long long) * 8;
shift = shift % bits; // 确保位移值在合理范围内

if (shift == 0)
return num;

return (num >> shift) | (num << (bits - shift));
}


void vaddq_s64(unsigned long long* a, unsigned long long* b, unsigned long long* res)
{
res[0] = a[0] + b[0];
res[1] = a[1] + b[1];
}

unsigned long long vaddvq_s64(unsigned long long* a)
{
return a[0] + a[1];
}



int main()
{

unsigned long long input[4] = { 0 };


int v50 = 72;
int v62 = 0;
unsigned char* v53, * v63;
unsigned long long* v54;
unsigned long long v55[2] = { 0 };
unsigned long long* v52 = &input[2];
unsigned long long v56, v59, v64;
unsigned long long x11 = 0x13c17ce8fc8b8157;
unsigned long long x12 = 0x477d6619faa7d1c7;
unsigned long long x13 = 0x6096448f5a2d874c;
unsigned long long x14 = 0x645d9ac2d095d15b;


while (v50 >= 1)
{
--v50;
v62 = v50 % 8;
if (v50 % 4 != 0)
{
v63 = &ror_num[2 * v62];

input[1] = x14;
v52[1] = x12;
v52[0] = x13;
v64 = v52[0] ^ x14;
v52[1] = rotateRight64(v64, v63[1]);
v52[0] = v52[0] - v52[1];
input[1] = rotateRight64(x11 ^ x12, v63[0]);
input[0] = x11 - input[1];
}
else {
v53 = &ror_num[2 * v62];
v54 = &key[4 * (v50 >> 2)];

v52[0] = x13;
input[1] = x14;
v59 = x13 ^ x14;
v52[1] = x12;
v55[1] = rotateRight64(v59, v53[1]);
v55[0] = x13 - v55[1];
input[0] = x11;

v56 = rotateRight64(x11 ^ x12, v53[0]);
input[0] = x11 - v56 - v54[0];
input[1] = v56 - v54[1];

unsigned long long* v54_2 = v54 + 2;
input[2] = v55[0] - v54_2[0];
input[3] = v55[1] - v54_2[1];
}
x11 = input[0];
x14 = input[1];
x13 = input[2];
x12 = input[3];
}

printf("%s", (char*)input);
//
return 0;
}



//v50: 1
//0x6844A35E83682C62
//0xEDBA9E2BE9989609
//0xBEAD2E3D5A3D5376
//0xD9D45741D241E5A3
//---------------------------------- -
//v50 : 2
//0x4218FAA055AA1205
//0x182567E521B7361B
//0xAC67CC6943D5E97F
//0xBFBCB9551406D853
//v50: 72
//0x502B4560187D82BE
//0x893D3A3DAA3E518D
//0x9C3963553FA89D18
//0xB82C1832ED0CEB1A

flag为 flag{7hIs_I$_nEw_Try1N9_@cu7U@1}

比赛结束后做出来的,迟到了4h,主要是vaddq_s64函数这里浪费了太长的时间了

强网先锋_ezre

flag的长度是34

换表的base64 + 伪随机数,sub_402230那里有个反调试,需要patch掉

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
unsigned int v3; // eax
unsigned __int64 v4; // rsi
unsigned int v5; // eax
int k; // [rsp+12Ch] [rbp-114h]
int j; // [rsp+130h] [rbp-110h]
int i; // [rsp+134h] [rbp-10Ch]
int v10; // [rsp+13Ch] [rbp-104h]
char v11[64]; // [rsp+140h] [rbp-100h] BYREF
char v12[64]; // [rsp+180h] [rbp-C0h] BYREF
char v13[64]; // [rsp+1C0h] [rbp-80h] BYREF
char s[52]; // [rsp+200h] [rbp-40h] BYREF
int v15; // [rsp+234h] [rbp-Ch]
size_t v16; // [rsp+238h] [rbp-8h]

v15 = 0;
printf("Welcome to the CTF world:");
memset(s, 0, 0x32uLL);
__isoc99_scanf("%s", s);
v16 = strlen(s);
v3 = strlen(s);
v10 = 0;
sub_401980((__int64)s, (__int64)v11, v3);
while ( v10 < 4 )
{
srand(aFgsevd3ibthwr1[2]);
v4 = strlen((const char *)(unsigned int)aFgsevd3ibthwr1);
sub_401D10((__int64)aFgsevd3ibthwr1, v4); // 表格变换
if ( (v10 & 1) != 0 )
{ // 奇数
v5 = strlen(v11);
sub_401980((__int64)v11, (__int64)v12, v5); //base64加密
}
else
{
sub_401250(v11, v12); // 偶数 //base64解密
}
memset(v11, 0, 0x32uLL);
memcpy(v11, v12, 0x32uLL);
++v10;
}
if ( dword_4062C0 == 1 ) // 如果在调试状态
{
sub_402EE0(aFgsevd3ibthwr1, &aFgsevd3ibthwr1[64]);
for ( i = 0; i < 64; ++i )
aFgsevd3ibthwr1[i] = (5 * (aFgsevd3ibthwr1[i] + 3)) ^ 0x15;
}
else
{
for ( j = 0; j < 64; ++j )
aFgsevd3ibthwr1[j] ^= 0x27u;
}
sub_401EB0(v12, v13); //错位异或
for ( k = 0; ; ++k )
{
if ( k >= strlen(v12) )
{
printf("right!");
return 0;
}
if ( byte_406180[k] != v13[k] )
break;
}
printf("wrong!");
return 0;
}

整体逻辑为输入flag,然后base64加密,然后换表,再base64解密,然后换表,再base64加密,然后换表,再base64解密,然后换表,再base64加密,然后一个错位异或得到密文,写对应的解密脚本即可

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
import base64
import string

enc = [
0x3A,
0x2C,
0x4B,
0x51,
0x68,
0x46,
0x59,
0x63,
0x24,
0x04,
0x5E,
0x5F,
0x00,
0x0C,
0x2B,
0x03,
0x29,
0x5C,
0x74,
0x70,
0x6A,
0x62,
0x7F,
0x3D,
0x2C,
0x4E,
0x6F,
0x13,
0x06,
0x0D,
0x06,
0x0C,
0x4D,
0x56,
0x0F,
0x28,
0x4D,
0x51,
0x76,
0x70,
0x2B,
0x05,
0x51,
0x68,
0x48,
0x55,
0x24,
0x19,
]
flag = [0] * 48
v3s = [
109,
76,
22,
73,
110,
77,
74,
78,
16,
98,
22,
109,
16,
126,
78,
109,
76,
22,
73,
110,
77,
74,
78,
16,
98,
22,
109,
16,
126,
78,
109,
76,
22,
73,
110,
77,
74,
78,
16,
98,
22,
109,
16,
126,
78,
109,
76,
]
flag[0] = enc[0] ^ v3s[0]
for i in range(1, 47):
flag[i] = enc[i] ^ enc[i - 1] ^ v3s[i]
flag[-1] = enc[-2] ^ enc[-1]

print(flag)
print(bytes(flag))
# WZqSWcUtWBLlOriEfcajWBSRstLlkEfFWR7j/R7dMCDGnp==



# str1 = b"1234567890123456789012345678901234"

# string1 = "l+USN4J5Rfj0TaVOcnzXiPGZIBpoAExuQtHyKD692hwmqe7/Mgk8v1sdCW3bYFLr"

# string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

# string3 = "FGseVD3ibtHWR1czhLnUfJK6SEZ2OyPAIpQoqgY0w49u+7rad5CxljMXvNTBkm/8" # 随机后
# enc_str1 = base64.b64encode(str1).decode()
# enc_str2 = enc_str1.translate(str.maketrans(string2, string1))
# print(enc_str2)

def enc_str(_str: bytes, _base64_table):
string1 = _base64_table
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

enc_str1 = base64.b64encode(_str).decode()
enc_str2 = enc_str1.translate(str.maketrans(string2, string1))
print(enc_str2)
return enc_str2 # 加密

def dec_str(_str: str, _base64_table):
str1 = _str
string1 = _base64_table
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
dec = base64.b64decode(str1.translate(str.maketrans(string1, string2)))
print(dec)
return dec

string1 = "l+USN4J5Rfj0TaVOcnzXiPGZIBpoAExuQtHyKD692hwmqe7/Mgk8v1sdCW3bYFLr"
string2 = "FGseVD3ibtHWR1czhLnUfJK6SEZ2OyPAIpQoqgY0w49u+7rad5CxljMXvNTBkm/8"
string3 = "Hc0xwuZmy3DpQnSgj2LhUtrlVvNYks+BX/MOoETaKqR4eb9WF8ICGzf6id1P75JA"
string4 = "pnHQwlAveo4DhGg1jE3SsIqJ2mrzxCiNb+Mf0YVd5L8c97/WkOTtuKFZyRBUPX6a"
string5 = "plxXOZtaiUneJIhk7qSYEjD1Km94o0FTu52VQgNL3vCBH8zsA/b+dycGPRMwWfr6"

enc = "WZqSWcUtWBLlOriEfcajWBSRstLlkEfFWR7j/R7dMCDGnp=="
dec = dec_str(enc, string5)
print(dec)
enc = enc_str(dec, string4)
print(enc)
dec = dec_str(enc, string3)
print(dec)
enc = enc_str(dec, string2)
print(enc)
dec = dec_str(enc, string1)
print(dec)

# flag{3ea590ccwxehg715264fzxnzepqz\x7f

代码可能有点小错误,直接修改flag的最后一个字符为}

得到flag为flag{3ea590ccwxehg715264fzxnzepqz}