Fork me on GitHub

CISCN-2018-reverse

这题比赛的时候没做出来,主要是心态崩了看不下去。。赛后看了下网上的wp发现不难,是自己想复杂了。这里将我的思路和exp放出来,希望大家一起交流学习。

main函数

它首先是check了输入的前六个字符是否与“CISCN{”匹配,接着使用strtok函数将字符串以“_”分割为三部分,然后分别对这三部分check。

sub_4012DE函数

关键部分如下

1

将第一部分的字符串经过以上变换后与一串MD5值5BH8170528842F510K70EGH31F44M24B比较。

那么我们可以直接逆出原本的md5,这个函数的脚本如下。

1
2
3
4
5
6
7
8
9
10
11
def change1(str0):
#str0即要逆的md5
str00 = ''
for i in range(len(str0)):
temp = ord(str0[i])-i%10
if temp <= ord('A') + 5 and temp >= ord('A'):
str00 += chr(temp)
else:
str00 += str0[i]

return str00

得到5AF8170528842C510D70EFF31A44E24A ,在线解密得到tima

sub_401411函数

这个函数相较上个只是多了个亦或的过程,同样可逆,脚本如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def change2(str0):
#str0是已经经过change1处理的md5
byte_603860 = [0x92,0x84,0x3d,0xa7,0x14,0xf2,0xfb,0x4b,0xee,0x8a,0xc2,0xc3,0x76,0x68,0x13,0x1e]
str2 = '['
for i in range(32):
if i%2 == 0:
str2 += '0x' + str0[i]
elif i != len(str1) - 1 :
str2 += str0[i] + ','
else:
str2 += str0[i] + ']'
#print str2
str2 = eval(str2)
str2_2 = ''
for i in range(len(str2)):
str2_2 += str( hex(str2[i] ^ byte_603860[i])[2:] )
return str2_2

得到c87c2aa23c76d71ae3fa2d306c2cf154 ,在线解密得到yefb

sub_401562函数

这个函数除了有sub_401411的全部加密过程,还会生成一个flag文件,但由于其中未知数太多,所以不采用逆向全部过程,生成flag文件的代码如下。

2

可以看到,我们只需爆破出v15,v16的值即可得到正确的flag文件,爆破脚本如下,这里我只取了前500个byte,能识别出文件格式即可,其实更少也行。

(这里使用了python的库filetype,pip安装即可)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import filetype

data = [0xc7,0xb7,0xc7,0x8f,0x38,0x7f,0x72,0x29,0x71,0x29,0x38,0x6e,0x39,0x6e,0x39,0x43,0x39,0x43,0x38,0x6f,0xc7,0xb4,0x38,0x2c,0x38,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x90,0xe3,0x6f,0x7b,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0xc7,0xaf,0x38,0x7e,0x30,0x6f,0x2e,0x6f,0xb8,0x6c,0x39,0x4e,0x38,0x6d,0x29,0x6e,0x3b,0x7e,0x39,0x90,0xfc,0x6f,0x27,0x6f,0x38,0x6e,0x3d,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6f,0x38,0x6f,0x38,0x6f,0x38,0x6f,0x38,0x6e,0x3a,0x6c,0x3c,0x6a,0x3e,0x68,0x30,0x66,0x32,0x64,0xc7,0xab,0x38,0xda,0x28,0x6f,0x3a,0x6e,0x3b,0x6c,0x3a,0x6b,0x3b,0x6a,0x3d,0x6b,0x3c,0x6f,0x38,0x6e,0x45,0x6e,0x3a,0x6c,0x38,0x6b,0x29,0x6a,0x2a,0x4e,0x9,0x2e,0x3e,0x7c,0x69,0xe,0x3f,0x4d,0x49,0x7b,0xa,0xee,0xa9,0xce,0x30,0x4c,0x7a,0xde,0xf9,0x7a,0x6a,0xbe,0xc8,0x4b,0xb,0xd,0x4a,0xed,0x31,0x65,0x2e,0x78,0x20,0x76,0x22,0x4a,0x1e,0x48,0x10,0x46,0x12,0x5b,0xd,0x59,0xf,0x57,0x1,0x55,0x7b,0x2b,0x7d,0x29,0x7f,0x27,0x71,0x25,0x6b,0x3b,0x6d,0x39,0x6f,0x37,0x61,0x35,0x5b,0xb,0x5d,0x9,0x5f,0x7,0x51,0x5,0x4b,0x1b,0x4d,0x19,0x4f,0x17,0x41,0x15,0xbb,0xeb,0xbd,0xe9,0xbf,0xe7,0xb1,0xe5,0xaa,0xfc,0xac,0xfa,0xae,0xf8,0xa0,0xf6,0xa2,0xcd,0x9b,0xcb,0x9d,0xc9,0x9f,0xc7,0x91,0xc5,0x8a,0xdc,0x8c,0xda,0x8e,0xd8,0x80,0xd6,0x82,0xad,0xfb,0xab,0xfd,0xa9,0xff,0xa7,0xf1,0xa5,0xea,0xbc,0xec,0xba,0xee,0xb8,0xe0,0xb6,0xe2,0x8e,0xda,0x8c,0xdc,0x8a,0xde,0x88,0xd0,0x86,0xd2,0x9e,0xca,0x9c,0xcc,0x9a,0xce,0x98,0xc0,0x96,0xc2,0x90,0xfc,0x6f,0x27,0x6e,0x38,0x6c,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6e,0x39,0x6f,0x38,0x6f,0x38,0x6f,0x38,0x6e,0x3a,0x6c,0x3c,0x6a,0x3e,0x68,0x30,0x66,0x32,0x64,0xc7,0xab,0x38,0xda,0x29,0x6f,0x3a,0x6e,0x3a,0x6b,0x3c,0x6c,0x3c,0x68,0x3d,0x6b,0x3c,0x6f,0x39,0x6d,0x4f,0x6f,0x39,0x6d,0x3b,0x7e,0x3c,0x6a,0x19,0x5e,0x3e,0x7d,0x79,0x3e,0x3f,0xe,0x49,0x7c,0x1a,0x5d,0xb9,0x67,0x2c,0x2d,0xa9,0xce,0x89,0xae,0x31,0x4c,0xb,0x3d,0xc8,0x7a,0x5a,0x1d,0xe9,0x65,0x2e,0x4b,0xc,0x8e,0x1d,0x9e,0x2f,0x77,0x21,0x75,0x1e,0x48,0x10,0x46,0x12,0x5a]

for i in range(256):
for j in range(256):

result = ''
for k in range(len(data)):
if k&1 :
result += chr( data[k]^i )
else:
result += chr( data[k]^j )
a = open('re_guess','w')
a.write(result)
a.close()
kind = filetype.guess('re_guess')
if kind is None:
continue
else:
print i,j,kind.extension

结果如下

1
2
3
4
5
6
7
23 216 Z
42 216 Z
76 56 mp3
111 56 jpg
150 226 ps
237 138 exe
250 133 bmp

jpg很可疑,于是生成完整文件看看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x = open('data.txt','r').read().replace('\n','')
data = eval('[' + x + ']')

i = 111
j = 56

a = open('flag.jpg','w')
temp = ''
for k in range(len(data)):
if k&1:
temp += chr( data[k] ^ i )
else:
temp += chr( data[k] ^ j )
a.write(temp)
a.close()

idc提取data.txt的脚本如下(shift+F2打开Execute script)

1
2
3
4
5
6
7
auto addr1 = 0x006020E0;
auto i,x;

for(i=0; i < 6016 ; i ++ )
{
Message("0x%x,",Byte(i+addr1));
}

得到第三部分的flag

3

验证

将以上得到的三部分以下划线拼接得到

CISCN{tima_yefb_MayDetyU$hhtIm2}

运行结果如下图

4