WMCTF-2021-re部分wp

本文最后更新于:2021年9月4日 下午

re1

无法F5,栈帧太大,看了看汇编。

image-20210903134108044

通过alt+k调整栈帧或者把相应的汇编代码nop掉。

然后分析伪代码,输入,check长度和flag格式

image-20210903143509630

之后会对几个block块进行赋值:

image-20210903143605191

image-20210903143645703

1
2
3
4
5
6
7
8
block块:
0-0xff flag{xxxx} 中的第一个x 取余 256
0x101-0x200 flag{xxxx} 中的第二个x 加1 取余 256
0x201-0x20f flag{xxxx} 中的第三个x 加2 取余 256
0x210 0x10
0x212-0x221 flag{xxxx yyyyyyyyyyyyyyyy } 存储16个y
0x222 0xdead
0x224-0x240 flag{xxxx} 中的第三个x 加3 取余 256

image-20210904163749317

1
2
3
4
z字符决定block块的改变
flag{xxxx yyyyyyyyyyyyyyyy z1234 z4321 ......}
如:_1234 0x12表示block的位置,将0x34赋值给这个位置
9个字符,决定block该去怎么改变

image-20210904164112631

根据block计算值,然后加减check,这里使用z3可以解出四个值。

image-20210904164220956

设置key,然后对16个y 进行xtea加密。

image-20210904164308703

xtea加密结果最后的比较。

1
2
3
4
解题思路:
1. z3解得到四个值,然后爆破得出前四个字符。
2. 根据结果进行xtea解密,得到中间16个值。(注意结果的顺序)
3. 最后反推block块的设置得到后边的值。

1:

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
from z3 import *
import ctypes
s = Solver()
x1 = Int("x1")
x2 = Int("x2")
x3 = Int("x3")
x4 = Int("x4")
s.add((x2 + x1) == 0x11AB7A7A)
s.add((x2 - x3) == 0x1CD4F222)
s.add((x4 + x3) == 0xC940F021)
s.add((x3 + x1 - x4) == 0x7C7D68D1)
if (s.check() == sat):
model = s.model()
print(model)
# [-5839603778, 6136054460,5652336794, -2275860601]
result1 = [-5839603778, 6136054460,5652336794, -2275860601]
for i in range(len(result1)):
result1[i] = hex(ctypes.c_int32(result1[i]).value & 0xffffffff)
print(result1)
# # ['0xa3eeb7be', '0x6dbcc2bc', '0x50e7d09a', '0x78591f87']

inx_arr = [0x00000000, 0x703A11DE, 0xE07423BC, 0x904E3262, 0xC6A99C09, 0xB6938DD7, 0x26DDBFB5, 0x56E7AE6B, 0x8B12E363, 0xFB28F2BD, 0x6B66C0DF, 0x1B5CD101, 0x4DBB7F6A, 0x3D816EB4, 0xADCF5CD6, 0xDDF54D08, 0x10641DB7, 0x605E0C69, 0xF0103E0B, 0x802A2FD5, 0xD6CD81BE, 0xA6F79060, 0x36B9A202, 0x4683B3DC, 0x9B76FED4, 0xEB4CEF0A, 0x7B02DD68, 0x0B38CCB6, 0x5DDF62DD, 0x2DE57303, 0xBDAB4161, 0xCD9150BF, 0x20C83B6E, 0x50F22AB0, 0xC0BC18D2, 0xB086090C, 0xE661A767, 0x965BB6B9, 0x061584DB, 0x762F9505, 0xABDAD80D, 0xDBE0C9D3, 0x4BAEFBB1, 0x3B94EA6F, 0x6D734404, 0x1D4955DA, 0x8D0767B8, 0xFD3D7666, 0x30AC26D9, 0x40963707, 0xD0D80565, 0xA0E214BB, 0xF605BAD0, 0x863FAB0E, 0x1671996C, 0x664B88B2, 0xBBBEC5BA, 0xCB84D464, 0x5BCAE606, 0x2BF0F7D8, 0x7D1759B3, 0x0D2D486D, 0x9D637A0F, 0xED596BD1, 0x419076DC, 0x31AA6702, 0xA1E45560, 0xD1DE44BE, 0x8739EAD5, 0xF703FB0B, 0x674DC969, 0x1777D8B7, 0xCA8295BF, 0xBAB88461, 0x2AF6B603, 0x5ACCA7DD, 0x0C2B09B6, 0x7C111868, 0xEC5F2A0A, 0x9C653BD4, 0x51F46B6B, 0x21CE7AB5, 0xB18048D7, 0xC1BA5909, 0x975DF762, 0xE767E6BC, 0x7729D4DE, 0x0713C500, 0xDAE68808, 0xAADC99D6, 0x3A92ABB4, 0x4AA8BA6A, 0x1C4F1401, 0x6C7505DF, 0xFC3B37BD, 0x8C012663, 0x61584DB2, 0x11625C6C, 0x812C6E0E, 0xF1167FD0, 0xA7F1D1BB, 0xD7CBC065, 0x4785F207, 0x37BFE3D9, 0xEA4AAED1, 0x9A70BF0F, 0x0A3E8D6D, 0x7A049CB3, 0x2CE332D8, 0x5CD92306, 0xCC971164, 0xBCAD00BA, 0x713C5005, 0x010641DB, 0x914873B9, 0xE1726267, 0xB795CC0C, 0xC7AFDDD2, 0x57E1EFB0, 0x27DBFE6E, 0xFA2EB366, 0x8A14A2B8, 0x1A5A90DA, 0x6A608104, 0x3C872F6F, 0x4CBD3EB1, 0xDCF30CD3, 0xACC91D0D, 0x8320EDB8, 0xF31AFC66, 0x6354CE04, 0x136EDFDA, 0x458971B1, 0x35B3606F, 0xA5FD520D, 0xD5C743D3, 0x08320EDB, 0x78081F05, 0xE8462D67, 0x987C3CB9, 0xCE9B92D2, 0xBEA1830C, 0x2EEFB16E, 0x5ED5A0B0, 0x9344F00F, 0xE37EE1D1, 0x7330D3B3, 0x030AC26D, 0x55ED6C06, 0x25D77DD8, 0xB5994FBA, 0xC5A35E64, 0x1856136C, 0x686C02B2, 0xF82230D0, 0x8818210E, 0xDEFF8F65, 0xAEC59EBB, 0x3E8BACD9, 0x4EB1BD07, 0xA3E8D6D6, 0xD3D2C708, 0x439CF56A, 0x33A6E4B4, 0x65414ADF, 0x157B5B01, 0x85356963, 0xF50F78BD, 0x28FA35B5, 0x58C0246B, 0xC88E1609, 0xB8B407D7, 0xEE53A9BC, 0x9E69B862, 0x0E278A00, 0x7E1D9BDE, 0xB38CCB61, 0xC3B6DABF, 0x53F8E8DD, 0x23C2F903, 0x75255768, 0x051F46B6, 0x955174D4, 0xE56B650A, 0x389E2802, 0x48A439DC, 0xD8EA0BBE, 0xA8D01A60, 0xFE37B40B, 0x8E0DA5D5, 0x1E4397B7, 0x6E798669, 0xC2B09B64, 0xB28A8ABA, 0x22C4B8D8, 0x52FEA906, 0x0419076D, 0x742316B3, 0xE46D24D1, 0x9457350F, 0x49A27807, 0x399869D9, 0xA9D65BBB, 0xD9EC4A65, 0x8F0BE40E, 0xFF31F5D0, 0x6F7FC7B2, 0x1F45D66C, 0xD2D486D3, 0xA2EE970D, 0x32A0A56F, 0x429AB4B1, 0x147D1ADA, 0x64470B04, 0xF4093966, 0x843328B8, 0x59C665B0, 0x29FC746E, 0xB9B2460C, 0xC98857D2, 0x9F6FF9B9, 0xEF55E867, 0x7F1BDA05, 0x0F21CBDB, 0xE278A00A, 0x9242B1D4, 0x020C83B6, 0x72369268, 0x24D13C03, 0x54EB2DDD, 0xC4A51FBF, 0xB49F0E61, 0x696A4369, 0x195052B7, 0x891E60D5, 0xF924710B, 0xAFC3DF60, 0xDFF9CEBE, 0x4FB7FCDC, 0x3F8DED02, 0xF21CBDBD, 0x8226AC63, 0x12689E01, 0x62528FDF, 0x34B521B4, 0x448F306A, 0xD4C10208, 0xA4FB13D6, 0x790E5EDE, 0x09344F00, 0x997A7D62, 0xE9406CBC, 0xBFA7C2D7, 0xCF9DD309, 0x5FD3E16B, 0x2FE9F0B5]
result1 = ['0xa3eeb7be', '0x6dbcc2bc', '0x50e7d09a', '0x78591f87']
flag = ""
# 1
result2 = []
a1 = 0xfffffffe
for i in range(len(inx_arr)):
v4 = 0xfffffffe
for j in range(len(inx_arr)):
v4 = (((v4 >> 8)) ^ inx_arr[(((j + i) % 256) ^ v4) & 0xff]) & 0xffffffff
result2.append(hex(v4 ^ a1))
flag += chr(result2.index(result1[0]))
# 2
result2 = []
a1 = 0xa3eeb7be
for i in range(len(inx_arr)):
v4 = 0xa3eeb7be
for j in range(len(inx_arr)):
v4 = (((v4 >> 8)) ^ inx_arr[(((j + i + 1) % 256) ^ v4) & 0xff]) & 0xffffffff
result2.append(hex(v4 ^ a1))
flag += chr(result2.index(result1[1]))
# 3
result2 = []
a1 = 0x6dbcc2bc
for i in range(len(inx_arr)):
v4 = 0x6dbcc2bc
for j in range(0xf):
v4 = (((v4 >> 8)) ^ inx_arr[(((j + i + 2) % 256) ^ v4) & 0xff]) & 0xffffffff
result2.append(hex(v4 ^ a1))
flag += chr(result2.index(result1[2]))
# 4
result2 = []
a1 = 0x50e7d09a
for i in range(len(inx_arr)):
v4 = 0x50e7d09a
for j in range(0x1c):
v4 = (((v4 >> 8)) ^ inx_arr[(((j + i + 3) % 256) ^ v4) & 0xff]) & 0xffffffff
result2.append(hex(v4 ^ a1))
flag += chr(result2.index(result1[3]))
print(flag)

2:

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
#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(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9981abcd;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3)]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3)]);
}
v[0]=v0; v[1]=v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9981abcd, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3)]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3)]);
}
v[0]=v0; v[1]=v1;
}
int str_num(uint8_t *s1, uint8_t *s2){
int num = 0;
for(int i = 0;i < 8; i++){
if(s1[i]>=33 && s1[i]<=126){
num++;
}
}
for(int i = 0;i < 8; i++){
if(s2[i]>=33 && s2[i]<=126){
num++;
}
}
return num;
}
int main()
{
//uint32_t v1[2]={0x556E2853, 0x4393DF16};
//uint32_t v2[2]={0x1989FB2B, 0x83F5A243};
//uint32_t v1[2]={0x5f30445f, 0x2174495f};
// 6269756F 72657762 0x6F657776, 0x6F766272 b22e38fe 30fbef03
//unsigned int key1[4] = {0xa3eeb7be, 0x50e7de9a, 0x6dbcc2bc, 0x78591fad};
//unsigned int key2[4] = {0x78591fad, 0x6dbcc2bc, 0xa3eeb7be, 0x50e7de9a};
//unsigned int key2[4] = {0xEC465DAD, 0x8186CB90, 0x1456A6EF, 0x0D528DEF7};

unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
// printf("加密前原始数据:%x %x\n",v[0],v[1]);
// encipher(r, v2, key2);
// printf("加密后的数据:%x %x\n",v2[0],v2[1]);
// encipher(r, v0, key1);
// printf("加密后的数据:%x %x\n",v0[0],v0[1]);
for(int i =0;i<0xffff;i++){
unsigned int a1 = 0x50e7009a ^ (i & 0xff00);
unsigned int a2 = 0x78591f00 ^ (i & 0x00ff);
uint32_t v1[2]={0x556E2853, 0x4393DF16};
uint32_t v2[2]={0x1989FB2B, 0x83F5A243};
unsigned int key1[4] = {0xa3eeb7be, a1, 0x6dbcc2bc, a2};
unsigned int key2[4] = {a2, 0x6dbcc2bc, 0xa3eeb7be, a1};
decipher(r, v1, key1);
//printf("解密后的数据:%x %x ",v1[0],v1[1]);
decipher(r, v2, key2);
//printf("%x %x\n",v2[0],v2[1]);
if(str_num(v1,v2)>=16){
printf("%x\n", i);
printf("解密后的数据:%x %x ",v1[0],v1[1]);
printf("%x %x\n",v2[0],v2[1]);
}
}
// encipher(r, v1, key1);
// printf("%x %x\n",v1[0],v1[1]);
return 0;
}

3:

发现 block+0x222 的位置应该为0xb7ad

然后反推得到:

1
!@FFFE#0F20-11B7

组合起来就是最后的flag。

re2


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!