彩笔一个,还请大佬多多指正
这道题说简单也不简单,有点小难度,主要是他的代码混淆太恶心了
首先ida打开,f12关键字,转到main函数
底下wrong的地方进行判断,把数据弄下来
a=[0xC6, 0x6A, 0xC0, 0x27, 0xEB, 0xCA, 0x65, 0x02, 0x61, 0xCA,
0x68, 0x27, 0x6B, 0xE2, 0xC0, 0xE0, 0x00, 0x80, 0x22, 0x27,
0xE1, 0xA1, 0x02, 0x27, 0x63, 0x4B, 0xA8, 0xE3]
然后倒着看,v2来自v16(sub_401880那个函数就是原地tp函数)
v16来自v15,v15来自v17,这里来到关键函数
sub_401960这个函数应该是一吧v17给了v15(混淆太多,应该是这样,大神勿喷)
然后看v17,sub_4014d0是个加密函数,参数分别是v9和v18,v18在上面有定义,r一下转字符串会发现v18=“nctf”(注意是小端存储)
然后看v9,v9来自v13(sub_401AD0实现的就是普通的赋值),v13来自v14,sub_401B70如图
这里只有标注的那个函数有意义,其他的都是些混淆,那么就很明了了,v13就等于v14,v14就是输入
之后是构造脚本,把关键加密函数弄下来
发现这加密太多了,不好逆向解,于是考虑到爆破
a=[0xC6, 0x6A, 0xC0, 0x27, 0xEB, 0xCA, 0x65, 0x02, 0x61, 0xCA,
0x68, 0x27, 0x6B, 0xE2, 0xC0, 0xE0, 0x00, 0x80, 0x22, 0x27,
0xE1, 0xA1, 0x02, 0x27, 0x63, 0x4B, 0xA8, 0xE3]
v18='nctf'
for i in range(len(a)):
for j in range(0,255):
a1=j
a2=ord(v18[i%4])
v2 = (~a2 | ~a1) & (~a2 | a1) & (a2 | a1) | (~a2 | ~a1) & (a2 | ~a1) & a2 & a1 | a2 & ~a1 | ~a2 & a1
v2 = 0xff&((~(32 * v2) | ~(v2 >> 3)) & (~(32 * v2) | (v2 >> 3)) & (32 * v2 | (v2 >> 3)) | (~(32 * v2) | ~(v2 >> 3)) & (32 * v2 | ~(v2 >> 3)) & (32 * v2 | (v2 >> 3)))
if(v2 == a[i]):
print(chr(j),end='')
break
值得注意的一点:
这里需要与一个0xff,因为
这里定义v15的时候,v15是unsigned int类型,在32位程序里占4字节,所以每个v2可能超出4字节(实际上都超出了),需要与上一个0xff(可以这么解释吧…)
感想:相较于re2,这个混淆有点多,需要耐心去看,有些小细节的地方需要注意一下。