2020湖湘杯

总的来说这次的re都还好。

RE

easyZ

一个不太常见架构S/390的程序,ida后发现不能反汇编,报错。。

然后在linux下使用qemu来模拟了程序的运行,确定关键字符串:Please input your string:

在所给的hex.txt搜索该字符串定位关键字符串的地址,再到dis.txt文件中搜索该地址定位到关键汇编指令地址处。

接着使用qemu在gdb一个端口进行下断调试验证一下:

剩下就是查看文档z Architecture汇编手册来手撸汇编代码。最后整理关键函数:

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
 1000910:	eb bf f0 58 00 24 	stmg	%r11,%r15,88(%r15)  //第一个关键函数
1000916: e3 f0 ff 50 ff 71 lay %r15,-176(%r15) //lea
100091c: b9 04 00 bf lgr %r11,%r15
1000920: e3 20 b0 a0 00 24 stg %r2,160(%r11) //r2 = r11+160 input
1000926: e3 20 b0 a0 00 04 lg %r2,160(%r11)
100092c: c0 e5 ff ff ff 02 brasl %r14,0x1000730
1000932: b9 04 00 12 lgr %r1,%r2 //mov
1000936: a7 1f 00 20 cghi %r1,32 //cmp len(input), 32
100093a: a7 84 00 06 je 0x1000946
100093e: a7 18 00 00 lhi %r1,0
1000942: a7 f4 00 56 j 0x10009ee
1000946: e5 4c b0 ac 00 00 mvhi 172(%r11),0
100094c: a7 f4 00 49 j 0x10009de
1000950: e3 10 b0 ac 00 14 lgf %r1,172(%r11)
1000956: e3 10 b0 a0 00 08 ag %r1,160(%r11)
100095c: 43 10 10 00 ic %r1,0(%r1)
1000960: b9 94 00 11 llcr %r1,%r1
1000964: c2 1f 00 00 00 2f clfi %r1,47
100096a: a7 c4 00 11 jle 0x100098c
100096e: e3 10 b0 ac 00 14 lgf %r1,172(%r11)
1000974: e3 10 b0 a0 00 08 ag %r1,160(%r11)
100097a: 43 10 10 00 ic %r1,0(%r1)
100097e: b9 94 00 11 llcr %r1,%r1
1000982: c2 1f 00 00 00 39 clfi %r1,57
1000988: a7 c4 00 24 jle 0x10009d0
100098c: e3 10 b0 ac 00 14 lgf %r1,172(%r11)
1000992: e3 10 b0 a0 00 08 ag %r1,160(%r11)
1000998: 43 10 10 00 ic %r1,0(%r1)
100099c: b9 94 00 11 llcr %r1,%r1
10009a0: c2 1f 00 00 00 60 clfi %r1,96
10009a6: a7 c4 00 11 jle 0x10009c8
10009aa: e3 10 b0 ac 00 14 lgf %r1,172(%r11)
10009b0: e3 10 b0 a0 00 08 ag %r1,160(%r11)
10009b6: 43 10 10 00 ic %r1,0(%r1)
10009ba: b9 94 00 11 llcr %r1,%r1
10009be: c2 1f 00 00 00 66 clfi %r1,102
10009c4: a7 c4 00 09 jle 0x10009d6
10009c8: a7 18 00 00 lhi %r1,0
10009cc: a7 f4 00 11 j 0x10009ee
10009d0: 18 00 lr %r0,%r0
10009d2: a7 f4 00 03 j 0x10009d8
10009d6: 18 00 lr %r0,%r0
10009d8: eb 01 b0 ac 00 6a asi 172(%r11),1
10009de: 58 10 b0 ac l %r1,172(%r11)
10009e2: a7 1e 00 1f chi %r1,31
10009e6: a7 c4 ff b5 jle 0x1000950
10009ea: a7 18 00 01 lhi %r1,1
10009ee: b9 14 00 11 lgfr %r1,%r1
10009f2: b9 04 00 21 lgr %r2,%r1
10009f6: e3 40 b1 20 00 04 lg %r4,288(%r11)
10009fc: eb bf b1 08 00 04 lmg %r11,%r15,264(%r11)
1000a02: 07 f4 br %r4
1000a04: 07 07 nopr %r7
1000a06: 07 07 nopr %r7
1000a08: b3 c1 00 2b ldgr %f2,%r11 //加密判断函数
1000a0c: b3 c1 00 0f ldgr %f0,%r15
1000a10: e3 f0 ff 48 ff 71 lay %r15,-184(%r15)
1000a16: b9 04 00 bf lgr %r11,%r15
1000a1a: e3 20 b0 a0 00 24 stg %r2,160(%r11) //input
1000a20: e5 4c b0 a8 00 00 mvhi 168(%r11),0 //mov 立即数
1000a26: a7 f4 00 4b j 0x1000abc

1000a2a: e3 10 b0 a8 00 14 lgf %r1,168(%r11) //循环
1000a30: e3 10 b0 a0 00 08 ag %r1,160(%r11) //r1 = input[i]
1000a36: 43 10 10 00 ic %r1,0(%r1)
1000a3a: b9 94 00 11 llcr %r1,%r1
1000a3e: 50 10 b0 b4 st %r1,180(%r11) //r11[180] = r1
1000a42: 58 30 b0 b4 l %r3,180(%r11) //r3 = r1
1000a46: 71 30 b0 b4 ms %r3,180(%r11) //r3*r3
1000a4a: c0 10 00 04 d3 ef larl %r1,0x109b228 //
1000a50: e3 20 b0 a8 00 14 lgf %r2,168(%r11) //i
1000a56: eb 22 00 02 00 0d sllg %r2,%r2,2 // << 2 (*4)
1000a5c: 58 12 10 00 l %r1,0(%r2,%r1) // 0x109b228[i<<2]
1000a60: b2 52 00 31 msr %r3,%r1 //input[i]*input[i]*0x109b228[i<<2]

1000a64: c0 10 00 04 d3 e2 larl %r1,0x109b228
1000a6a: e3 20 b0 a8 00 14 lgf %r2,168(%r11) //i
1000a70: a7 2b 00 20 aghi %r2,32 //add + 32
1000a74: eb 22 00 02 00 0d sllg %r2,%r2,2 // << 2
1000a7a: 58 12 10 00 l %r1,0(%r2,%r1) //0x109b228[(i+32)<<2]

1000a7e: 71 10 b0 b4 ms %r1,180(%r11) //0x109b228[(i+32)<<2]*input[i]
1000a82: 1a 31 ar %r3,%r1 //input[i]*input[i]*0x109b228[i<<2] + 0x109b228[(i+32)<<2]*input[i]

1000a84: c0 10 00 04 d3 d2 larl %r1,0x109b228
1000a8a: e3 20 b0 a8 00 14 lgf %r2,168(%r11) //i
1000a90: a7 2b 00 40 aghi %r2,64 //i+64
1000a94: eb 22 00 02 00 0d sllg %r2,%r2,2 //(i+64) << 2
1000a9a: 58 12 10 00 l %r1,0(%r2,%r1) //r1 = 0x109b228[(i+64) << 2]
1000a9e: 1a 31 ar %r3,%r1 //add r3 + 0x109b228[(i+64) << 2]

1000aa0: c4 18 00 04 d3 68 lgrl %r1,0x109b170
1000aa6: e3 20 b0 a8 00 14 lgf %r2,168(%r11) //i
1000aac: eb 22 00 02 00 0d sllg %r2,%r2,2 // i << 2
1000ab2: 50 32 10 00 st %r3,0(%r2,%r1) r1[r2] = r3, 0x109dd08
1000ab6: eb 01 b0 a8 00 6a asi 168(%r11),1 //i++;

1000abc: 58 10 b0 a8 l %r1,168(%r11) //mov eax, i(168(%r11));
1000ac0: a7 1e 00 1f chi %r1,31
1000ac4: a7 c4 ff b3 jle 0x1000a2a //cmp

1000ac8: e5 4c b0 ac 00 01 mvhi 172(%r11),1 //j = 1
1000ace: e5 4c b0 b0 00 00 mvhi 176(%r11),0 //i = 0
1000ad4: a7 f4 00 21 j 0x1000b16

1000ad8: c4 18 00 04 d3 4c lgrl %r1,0x109b170 //判断循环 加密后的数据
1000ade: e3 20 b0 b0 00 14 lgf %r2,176(%r11) //i
1000ae4: eb 22 00 02 00 0d sllg %r2,%r2,2 //i << 2
1000aea: 58 32 10 00 l %r3,0(%r2,%r1) //enc[i<<2]
1000aee: c0 10 00 04 d3 5d larl %r1,0x109b1a8
1000af4: e3 20 b0 b0 00 14 lgf %r2,176(%r11) //i
1000afa: eb 22 00 02 00 0d sllg %r2,%r2,2 // i << 2
1000b00: 58 12 10 00 l %r1,0(%r2,%r1) //d[i<<2]
1000b04: 19 31 cr %r3,%r1
1000b06: a7 84 00 05 je 0x1000b10
1000b0a: e5 4c b0 ac 00 00 mvhi 172(%r11),0
1000b10: eb 01 b0 b0 00 6a asi 176(%r11),1 //add

1000b16: 58 10 b0 b0 l %r1,176(%r11) //i
1000b1a: a7 1e 00 1f chi %r1,31 //cmp
1000b1e: a7 c4 ff dd jle 0x1000ad8

1000b22: 58 10 b0 ac l %r1,172(%r11)
1000b26: b9 14 00 11 lgfr %r1,%r1
1000b2a: b9 04 00 21 lgr %r2,%r1
1000b2e: b3 cd 00 b2 lgdr %r11,%f2
1000b32: b3 cd 00 f0 lgdr %r15,%f0
1000b36: 07 fe br %r14

1000b38: eb bf f0 58 00 24 stmg %r11,%r15,88(%r15) //main函数
1000b3e: e3 f0 ff 20 ff 71 lay %r15,-224(%r15)
1000b44: b9 04 00 bf lgr %r11,%r15
1000b48: b2 4f 00 10 ear %r1,%a0
1000b4c: eb 11 00 20 00 0d sllg %r1,%r1,32
1000b52: b2 4f 00 11 ear %r1,%a1
1000b56: d2 07 b0 d8 10 28 mvc 216(8,%r11),40(%r1)
1000b5c: c0 20 00 03 82 84 larl %r2,0x1071064 //please input ...
1000b62: c0 e5 00 00 40 43 brasl %r14,0x1008be8 //printf
1000b68: ec 1b 00 a6 00 d9 aghik %r1,%r11,166
1000b6e: b9 04 00 31 lgr %r3,%r1
1000b72: c0 20 00 03 82 87 larl %r2,0x1071080 // %s
1000b78: c0 e5 00 00 3a 5c brasl %r14,0x1008030 // scanf(" ");
1000b7e: ec 1b 00 a6 00 d9 aghik %r1,%r11,166 //add
1000b84: b9 04 00 21 lgr %r2,%r1 %r1 : input
1000b88: c0 e5 ff ff fe c4 brasl %r14,0x1000910 //关键加密函数。
1000b8e: b9 04 00 12 lgr %r1,%r2 //mov
1000b92: 12 11 ltr %r1,%r1 //cmp test
1000b94: a7 84 00 17 je 0x1000bc2
1000b98: ec 1b 00 a6 00 d9 aghik %r1,%r11,166
1000b9e: b9 04 00 21 lgr %r2,%r1
1000ba2: c0 e5 ff ff ff 33 brasl %r14,0x1000a08
1000ba8: b9 04 00 12 lgr %r1,%r2
1000bac: 12 11 ltr %r1,%r1
1000bae: a7 84 00 0a je 0x1000bc2
1000bb2: c0 20 00 03 82 69 larl %r2,0x1071084 // lea "you win"
1000bb8: c0 e5 00 00 40 18 brasl %r14,0x1008be8
1000bbe: a7 f4 00 08 j 0x1000bce
1000bc2: c0 20 00 03 82 66 larl %r2,0x107108e //lea "you lose!"
1000bc8: c0 e5 00 00 40 10 brasl %r14,0x1008be8

提取处数据,在gdb中使用x/100xw查看的数据然后提取出(直接找到地址让hex.txt文件找也可以)。

然后解密:

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
#include <stdio.h>
unsigned int data[] = { 0x0000b2b0, 0x00006e72, 0x00006061, 0x0000565d,
0x0000942d, 0x0000ac79, 0x0000391c, 0x0000643d,
0x0000ec3f, 0x0000bd10, 0x0000c43e, 0x00007a65,
0x0000184b, 0x0000ef5b, 0x00005a06, 0x0000a8c0,
0x0000f64b, 0x0000c774, 0x000002ff, 0x00008e57,
0x0000aed9, 0x0000d8a9, 0x0000230c, 0x000074e8,
0x0000c2a6, 0x000088b3, 0x0000af2a, 0x00009ea7,
0x0000ce8a, 0x00005924, 0x0000d276, 0x000056d4,
0x000077d7, 0x0000990e, 0x0000b585, 0x00004bcd,
0x00005277, 0x00001afc, 0x00008c8a, 0x0000cdb5,
0x00006e26, 0x00004c22, 0x0000673f, 0x0000daff,
0x00000fac, 0x000086c7, 0x0000e048, 0x0000c483,
0x000085d3, 0x00002204, 0x0000c2ee, 0x0000e07f,
0x00000caf, 0x0000bf76, 0x000063fe, 0x0000bffb,
0x00004b09, 0x0000e5b3, 0x00008bda, 0x000096df,
0x0000866d, 0x00001719, 0x00006bcf, 0x0000adcc,
0x00000f2b, 0x000051ce, 0x00001549, 0x000020c1,
0x00003a8d, 0x000005f5, 0x00005403, 0x00001125,
0x00009161, 0x0000e2a5, 0x00005196, 0x0000d8d2,
0x0000d644, 0x0000ee86, 0x00003896, 0x00002e71,
0x0000a6f1, 0x0000dfcf, 0x00003ece, 0x00007d49,
0x0000c24d, 0x0000237e, 0x00009352, 0x00007a97,
0x00007bfa, 0x0000cbaa, 0x000010dc, 0x00003bd9,
0x00007d7b, 0x00003b88, 0x0000b0d0, 0x0000e8bc };

unsigned int result[] = { 0x08a73233, 0x116db0f6, 0x0e654937, 0x03c374a7,
0x16bc8ed9, 0x0846b755, 0x08949f47, 0x04a13c27,
0x0976cf0a, 0x07461189, 0x1e1a5c12, 0x11e64d96,
0x03cf09b3, 0x093cb610, 0x0d41ea64, 0x07648050,
0x092039bf, 0x08e7f1f7, 0x004d871f, 0x1680f823,
0x06f3c3eb, 0x2205134d, 0x015c6a7c, 0x11c67ed0,
0x0817b32e, 0x06bd9b92, 0x08806b0c, 0x06aaa515,
0x205b9f76, 0x0de963e9, 0x2194e8e2, 0x047593bc };
int main()
{
unsigned int a = 0;
for (int i = 0; i < 32; i++)
{
for (int input = 0x20; input < 0x7e; input++)
{
a = input*input*data[i]+ data[i + 32] * input+ data[i + 64];

if (a == result[i])
{
printf("%c", input);
break;
}
}
}
getchar();
}
//8eb5d8b632dae2a5167e3e1c4884eef9

easyre

直接拖入ida分析完main函数后没有发现加密判断函数,直接动调跟流程,也很简单,整理了下加密与最后比较数据的笔记:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a = input[0] << 3
b = input[1] >> 5
a = a|b
a = a ^ i;

input[i] = (input[i] << 3) | (input[(i+1)%24] & 0xE0) >> 5

unsigned char ida_chars[] =
{
43, 8, 169, 200, 151, 47, 255, 140, 146, 240,
163, 137, 247, 38, 7, 164, 218, 234, 179, 145,
239, 220, 149, 171
};

sar:算术右移指令。右移时保留操作数的符号,即用符号位来补足。
shr:逻辑右移指令。右移时总是用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
#include <stdio.h>

unsigned char ida_chars[] =
{
43, 8, 169, 200, 151, 47, 255, 140, 146, 240,
163, 137, 247, 38, 7, 164, 218, 234, 179, 145,
239, 220, 149, 171
};

int main(void)
{
int i = 0;
unsigned char ch1 = 0;
ch1 = (ida_chars[0] >> 3) | (ida_chars[23] << 5);
putchar(ch1);
for(i = 1; i < 23; i++)
{
ch1 = (((ida_chars[i]^i) >> 3) | ((ida_chars[i-1]^(i-1)) << 5))&0xff;
putchar(ch1);
}
ch1 = (ida_chars[23] >> 3 ) | ((ida_chars[22]^22) << 5);
putchar(ch1);
//ea5yre_1s_50_ea5y_t0_y0u
}

easy_c++

很简单,ida打开后简单分析以下,只是对输入进行了一个异或,然后与指定编码字符串进行比较。。

直接在ida-python解决:

1
2
3
4
5
6
7
s = '7d21e<e3<:3;9;ji t r#w\"$*{*+*$|,'
flag = ''
for i in range(32):
flag += chr(ord(s[i])^i)
print(flag)

#7e02a9c4439056df0e2a7b432b0069b3

ReMe

首先从程序图标可以想到python,然后ida载入查看字符串,发现很多PY相关的字符且程序不寻常。这时候基本可以确定是python打包成的exe程序了。

然后使用python pyinstxtractor.py ReMe.exe解包,从得到的包里可以pyc文件看到ReMe,但是缺少文件头的,找到包里的另一个stuct文件,对ReMe的文件头进行补齐。

https://bbs.pediy.com/upload/attach/202011/909254_VRZ57MQQAC3H4EX.png

使用uncompyle6 -o re.py ReMe.pyc转化为py文件。

py代码很简单,把原来的代码稍微修改以下可以直接爆破出flag:

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
import sys, hashlib
check = [
'e5438e78ec1de10a2693f9cffb930d23',
'08e8e8855af8ea652df54845d21b9d67',
'a905095f0d801abd5865d649a646b397',
'bac8510b0902185146c838cdf8ead8e0',
'f26f009a6dc171e0ca7a4a770fecd326',
'cffd0b9d37e7187483dc8dd19f4a8fa8',
'4cb467175ab6763a9867b9ed694a2780',
'8e50684ac9ef90dfdc6b2e75f2e23741',
'cffd0b9d37e7187483dc8dd19f4a8fa8',
'fd311e9877c3db59027597352999e91f',
'49733de19d912d4ad559736b1ae418a7',
'7fb523b42413495cc4e610456d1f1c84',
'8e50684ac9ef90dfdc6b2e75f2e23741',
'acb465dc618e6754de2193bf0410aafe',
'bc52c927138231e29e0b05419e741902',
'515b7eceeb8f22b53575afec4123e878',
'451660d67c64da6de6fadc66079e1d8a',
'8e50684ac9ef90dfdc6b2e75f2e23741',
'fe86104ce1853cb140b7ec0412d93837',
'acb465dc618e6754de2193bf0410aafe',
'c2bab7ea31577b955e2c2cac680fb2f4',
'8e50684ac9ef90dfdc6b2e75f2e23741',
'f077b3a47c09b44d7077877a5aff3699',
'620741f57e7fafe43216d6aa51666f1d',
'9e3b206e50925792c3234036de6a25ab',
'49733de19d912d4ad559736b1ae418a7',
'874992ac91866ce1430687aa9f7121fc']

def func(num):
result = []
while num != 1:
num = num * 3 + 1 if num % 2 else num // 2
result.append(num)

return result


if __name__ == '__main__':

flag = ''
for i in range(27):
for ch in range(32, 127):
ret_list = func(ch)
s = ''
for idx in range(len(ret_list)):
s += str(ret_list[idx])
s += str(ret_list[(len(ret_list) - idx - 1)])
md5 = hashlib.md5()
md5.update(s.encode('utf-8'))
if md5.hexdigest() == check[i]:
flag += chr(ch)
break
md5 = hashlib.md5()
md5.update(flag.encode('utf-8'))
print('flag{' + md5.hexdigest() + '}')

#flag{0584cfa2ce502951ef5606f6b99fc921}
-------------本文结束感谢您的阅读-------------