image-crackme

想用IDA Pro逆向结果打开到一半就崩溃了,只能靠猜了。试着运行几次image-crackme.exe,发现生成的MeePwn.ascii的内容总是160x160的一大堆乱七八糟的字符,同时目录下还有一个MeePwn.jpg,尺寸同样是160x160,而且缺少这个文件程序就没法运行,推测图片中的像素和输出有某种联系,用画图做了一张160x160的纯白色图片替换了原来的图(为了使所有的像素都相同),然后试着输入0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}(ASCII48-126)作为key,产生了十分有规律的输出:

这个pattern就很有意思了,可以推测输入的key是被循环扩展到160x160(即ABCDEF->ABCDEFABCDEF…),然后每个字节分别和MeePwn.jpg中对应的像素进行某种运算,才会产生这种循环的输出。

题目提示说flag是MeePwn{…}的形式,可以根据这一特点,用不同长度的flag作为输入,比较输出的MeePwn.ascii和MeePwn.ascii.bak中相同符号的个数,从而得出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
import os


def march():
maxlen=160
marches=0
s1=open('MeePwn.ascii').read().split('\n')
s2=open('MeePwn.ascii.bak').read().split('\n')
for i in range(maxlen):
for j in range(maxlen):
if s1[i][j]==s2[i][j]:
marches+=1
return marches


def main():
alla=160*160
maxklen=40
mars=[]
keys=[]
for klen in range(1,maxklen):
key='MeePwn{'+'?'*klen+'}'
os.system('echo %s|.\\image_crackme.exe'%key)
marches=march()
mars.append(marches)
keys.append(key)
print(mars)
print(keys)
for i in range(len(mars)):
print('%d/%d %s %d'%(mars[i],alla,keys[i],len(keys[i])))


if __name__=='__main__':
main()


'''RESULT
2880/25600 MeePwn{????????????????????????} 32
8107/25600 MeePwn{?????????????????????????} 33
2836/25600 MeePwn{??????????????????????????} 34
'''

结果中key长度为33时相同符号个数明显高于其他(同样高的还有33的因数11),因此flag长度为33,得到这一长度后,只要逐字符爆破就可以了,即比对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
import os


def march(index,klen):
alla=25600
i=index
marches=0
s1=''.join(open('MeePwn.ascii').read().split('\n'))
s2=''.join(open('MeePwn.ascii.bak').read().split('\n'))
while i<alla:
if s1[i]==s2[i]:
marches+=1
i+=klen
return marches


def test(rawkey,index,charset):
keylen=33
keys=[]
mars=[]
for ch in charset:
key=rawkey[:index]+ch+rawkey[index+1:]
os.system('echo %s|.\\image_crackme.exe'%key)
marches=march(index,keylen)
mars.append(marches)
keys.append(key)
keychars=[]
for i in range(len(charset)):
if mars[i]>700:
keychars.append(charset[i])
print(keychars)
return keychars


def main():
keycharss=[]
rawkey='MeePwn{?????????????????????????}'
charset='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-=?!+@%*/\\'
for index in range(7,32):
keycharss.append(test(rawkey,index,charset))
#keycharss=[['g'], ['0'], ['l'], ['4'], ['n'], ['g'], ['_'], ['A'], ['s'], ['c'], ['1'], ['1'], ['A'], ['r'], ['t'], ['_'], ['1'], ['S'], ['_'], ['4'], ['w'], ['S'], ['0'], ['m'], ['e']]
flag='MeePwn{'+(''.join(map(lambda x:x[0],keycharss)))+'}'
assert(len(flag)==33)
print(flag)


if __name__=='__main__':
main()

flag:MeePwn{g0l4ng_Asc11Art_1S_4wS0me}

不得不承认自己和真正的CTF选手还是有很大的差距的,别的题看的一头雾水,毫无思路。