2021西湖论剑线上初赛-两道简单re

本文最后更新于:2 年前

水了一道题,自我感觉良好,没有像去年那样爆零了

TacticalArmed

ida 载入

image-20211120184128658

我们可以知道, 由 sub_4011f0 动态生成指令, 然后执行, 加密 输入的字符串

image-20211120183815603

动态调试提取指令

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
00644D68 | 81E9 D2965A7E            | sub ecx,7E5A96D2                        |
00644D68 | 890D 48574000 | mov dword ptr ds:[sum],ecx |

00644D68 | 8B15 4C564000 | mov edx,dword ptr ds:[r] |
00644D68 | C1EA 05 | shr edx,5 |
00644D68 | A1 04504000 | mov eax,dword ptr ds:[key1] |
00644D68 | 03C2 | add eax,edx |
00644D68 | 8B0D 48574000 | mov ecx,dword ptr ds:[sum] |
00644D68 | 030D 4C564000 | add ecx,dword ptr ds:[r] |
00644D68 | 33C1 | xor eax,ecx |
00644D68 | 8B15 4C564000 | mov edx,dword ptr ds:[r] |
00644D68 | C1E2 04 | shl edx,4 |
00644D68 | 8B0D 00504000 | mov ecx,dword ptr ds:[key0] |
00644D68 | 03CA | add ecx,edx |
00644D68 | 33C1 | xor eax,ecx |
00644D68 | 8B15 48564000 | mov edx,dword ptr ds:[l] |
00644D68 | 03D0 | add edx,eax |
00644D68 | 8915 48564000 | mov dword ptr ds:[l],edx |

00644D68 | A1 48564000 | mov eax,dword ptr ds:[l] |
00644D68 | C1E8 05 | shr eax,5 |
00644D68 | 8B0D 0C504000 | mov ecx,dword ptr ds:[key3] |
00644D68 | 03C8 | add ecx,eax |
00644D68 | 8B15 48574000 | mov edx,dword ptr ds:[sum] |
00644D68 | 0315 48564000 | add edx,dword ptr ds:[l] |
00644D68 | 33CA | xor ecx,edx |
00644D68 | A1 48564000 | mov eax,dword ptr ds:[l] |
00644D68 | C1E0 04 | shl eax,4 |
00644D68 | 8B15 08504000 | mov edx,dword ptr ds:[key2] |
00644D68 | 03D0 | add edx,eax |
00644D68 | 33CA | xor ecx,edx |
00644D68 | A1 4C564000 | mov eax,dword ptr ds:[r] |
00644D68 | 03C1 | add eax,ecx |
00644D68 | A3 4C564000 | mov dword ptr ds:[r],eax |
00644D68 | 8B0D 48574000 | mov ecx,dword ptr ds:[sum] |

然后分析得到

1
2
3
sum = sum - 0x7E5A96D2;
l = l + ((r << 4) + key0) ^ ((r << 5) + key1) ^ (r + sum);
r = r + ((l << 4) + key2) ^ ((l << 5) + key3) ^ (sum + l);

是个 tea 加密, 经过了魔改, delta 为 0x7E5A96D2, sum 为 减法, 并且,这里的 tea 每次加密 8位字符串一组,sum不会进行初始化,而是继续累加, round 为 33 轮

提取数据

1
2
3
4
5
6
7
8
9
key2 = 405008 = 2035759140
key3 = 40500C = 856380911
key0 = 405000 = 579036953
key1 = 405004 = 2778172449

sum = 405748 = 0

r = 40564C
l = 405648 = inputflag

经过调试发现, 真正的key会发生改变

img

然后我们就可以写解密代码了

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
#include <iostream>

unsigned int test(unsigned int index) {

unsigned int sum = 0;
sum = 0;

for (size_t i = 0; i < 33 * index; i++) {
sum -= 0x7E5A96D2;
}
//printf("next sum value:%x\n", sum);
return sum;
}

void decrypt(unsigned int* v, unsigned int* key, int index) {
unsigned int l = v[0], r = v[1], sum = 0, delta = 0x7E5A96D2;
// sum 需要先得到上一轮加密后的 value
sum = test(index) - delta * 33;

for (size_t i = 0; i < 33; i++) {
r -= ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
l -= ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
sum += delta;
}
v[0] = l;
v[1] = r;


}

void encrypt(unsigned int* v, unsigned int* key) {
unsigned int l = v[0], r = v[1], sum = 0, delta = 0x7E5A96D2;
sum = 0;

for (size_t i = 0; i < 33; i++) {
sum -= delta;
l += ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
r += ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
printf("第%d轮, l:%x, r:%x, sum:%x\n", i, l, r, sum);
}
//v[0] = l;
//v[1] = r;
//printf("sum:%x", sum);
}



int main()
{
unsigned int key[] = { 0x7ce45630,0x58334908,0x66398867,0xc35195b1 };
//unsigned int key[] = { 0x22836719,0xa5978c21,0x79573824,0x330b55ef };
unsigned int v[] = { 0x422f1ded,0x1485e472,0x035578d5,0xbf6b80a2,0x97d77245,0x2dae75d1,0x665fa963,0x292e6d74,0x9795fcc1,0x0bb5c8e9 };

for (int index = 0; index < 5; index++) {
decrypt(&v[index*2], key, index);


}
for (int i = 0; i < 40; i++) {
printf("%c", *((char*)v + i));
}


printf("\n");


//test(1);
//encrypt((unsigned int*)"11111111", key);
}

getflag

kgD1ogB2yGa2roiAeXiG8_aqnLzCJ_rFHSPrn55K

ROR

我自己是看不明白的, 感觉脑子绣住了,问的园子师傅

八位一组计算出每一组的索引,之后根据索引在 256 大小的数组中定位元素

索引生成方式为 每一组(8位) 转换二进制位后,排列 组成矩阵,然后转置,形成新的

img

解题脚本(部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
result = []
matrix = [0x65,0x08,0xf7,0x12,0xbc,0xc3,0xcf,0xb8,0x83,0x7b,0x02,0xd5,0x34,0xbd,0x9f,0x33,0x77,0x76,0xd4,0xd7,0xeb,0x90,0x89,0x5e,0x54,0x01,0x7d,0xf4,0x11,0xff,0x99,0x49,0xad,0x57,0x46,0x67,0x2a,0x9d,0x7f,0xd2,0xe1,0x21,0x8b,0x1d,0x5a,0x91,0x38,0x94,0xf9,0x0c,0x00,0xca,0xe8,0xcb,0x5f,0x19,0xf6,0xf0,0x3c,0xde,0xda,0xea,0x9c,0x14,0x75,0xa4,0x0d,0x25,0x58,0xfc,0x44,0x86,0x05,0x6b,0x43,0x9a,0x6d,0xd1,0x63,0x98,0x68,0x2d,0x52,0x3d,0xdd,0x88,0xd6,0xd0,0xa2,0xed,0xa5,0x3b,0x45,0x3e,0xf2,0x22,0x06,0xf3,0x1a,0xa8,0x09,0xdc,0x7c,0x4b,0x5c,0x1e,0xa1,0xb0,0x71,0x04,0xe2,0x9b,0xb7,0x10,0x4e,0x16,0x23,0x82,0x56,0xd8,0x61,0xb4,0x24,0x7e,0x87,0xf8,0x0a,0x13,0xe3,0xe4,0xe6,0x1c,0x35,0x2c,0xb1,0xec,0x93,0x66,0x03,0xa9,0x95,0xbb,0xd3,0x51,0x39,0xe7,0xc9,0xce,0x29,0x72,0x47,0x6c,0x70,0x15,0xdf,0xd9,0x17,0x74,0x3f,0x62,0xcd,0x41,0x07,0x73,0x53,0x85,0x31,0x8a,0x30,0xaa,0xac,0x2e,0xa3,0x50,0x7a,0xb5,0x8e,0x69,0x1f,0x6a,0x97,0x55,0x3a,0xb2,0x59,0xab,0xe0,0x28,0xc0,0xb3,0xbe,0xcc,0xc6,0x2b,0x5b,0x92,0xee,0x60,0x20,0x84,0x4d,0x0f,0x26,0x4a,0x48,0x0b,0x36,0x80,0x5d,0x6f,0x4c,0xb9,0x81,0x96,0x32,0xfd,0x40,0x8d,0x27,0xc1,0x78,0x4f,0x79,0xc8,0x0e,0x8c,0xe5,0x9e,0xae,0xbf,0xef,0x42,0xc5,0xaf,0xa0,0xc2,0xfa,0xc7,0xb6,0xdb,0x18,0xc4,0xa6,0xfe,0xe9,0xf5,0x6e,0x64,0x2f,0xf1,0x1b,0xfb,0xba,0xa7,0x37,0x8f]

# 这里暂时提取八位
s1 = [0x65, 0x55, 0x24, 0x36, 0x9D, 0x71, 0xB8, 0xC8]
for i in s1:
# 提取对应索引
i1 = matrix.index(i)
# 转换八位二进制加入到二维数组中
t = bin(i1)[2:]
t1 = ((8 - len(t)) * '0') + t
# print(t1)
result.append(t1)

flag = ""
# 矩阵转置
for i in range(8):
bin_num = ''
for j in range(8):
bin_num += result[j][i]

flag += chr(int(bin_num, 2))

print(flag)

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