查壳:
有壳32位,脱了,看看运行:无法运行,那么进IDA看看:
找个主函数:
发现没了,那么再找找
密文?不确定,跟进看看:
来到一个输出正确flag的地方,可以知道Des就是我们要找的东西:去看看有谁调用过它:
有两,第一个就是上图的输出,那么我们看第二个:
在这里我们看到一个方法:sub_411190() --> 这不就是输出正确的flag的方法吗?说明这里才是正确的主函数:
那么我们往上看:
这个就是我们一开始以为的主函数的方法的调用,接下去看看:
将Source赋值给Des,那么我们看看Source是个啥,跟进:
发现内存里是空的?那么我们猜测,这是不是初始化空间?接着向下看:
不认识这两:查呗:
构建两个线程?跟进第一个线程:
又出现了Source,后边还跟了一个内存,里边是一个数据:1D --> 29,看看调用他两的方法:sub_41112C(有些人进不去伪代码,这是由于堆栈不平衡,调成平衡后就好了),发现是将字符经过变化后给Source
这里大概是讲,先判断是否是字母,再判断是否是小写字母,然后操作result和off_418000中的数据。先看看off_418000中是个啥:"QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
跟进第二个线程:
hObject?Wait?(暂停第一个线程吗?)查:
跟我们想的一样:那么主要去分析第一个线程就好了:
在第一个线程中,我们能看到,是先将字符给了result后才进行操作的,结合上述,也就是奇数位不变,偶数位改变,但是先别急,怎么变化我们并没有弄清楚,再看看。它说的是(a2+a1),根据传参我们能知道,这是指想Source中的字符,也就是说,是在off_418000中找到Source的字符然后进行变化。那么Source的字符串就是我们接下来要找的,之前我们访问过它的内存,却没有任何东西,但是还记最后的比较方法吗,那里提供了最后的加密字符串:
回去:
跟进:off_418004查看:"TOiZiZtOrYaToUwPnToBsOaOapsyS"
可以得到Source的字符串:"TOiZiZtOrYaToUwPnToBsOaOapsyS",写个脚本:
Des = 'TOiZiZtOrYaToUwPnToBsOaOapsyS'
D = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasd'
flag = ''
for i in range(len(Des)):
if i % 2 == 0:
flag += Des[i]
else:
if ord(Des[i]) < ord('A') or ord(Des[i]) > ord('Z'):
flag += chr(D.find(Des[i]) + 38)
else:
flag += chr(D.find(Des[i]) + 96)
print(flag)