网鼎杯-re-joker

打开后是一个windows下的pe文件,查壳,无壳,为32位的可执行文件,使用IDA(32)打开,f5一键反编译,发现反编译不了,显示positive sp value has been found,那就开始看汇编把!

这里需要我们输入flag,通过后面的判断可以知道,输入字符长度为24,继续往下:

 ,,

这里可以看出来,flag经过了两个函数,__Z5wrongPc和__Z3omgPc如下:

前者主要对flag进行一些操作,偶数位(从0开始)^i,奇数位-1,得到的结果值传入后者再与字符串unk_4030C0进行比较

 这里,发现有错误的输出,但输出错误并不会影响到整个程序的进行,而且后序的传参传的仍是原来的值,所以这里是个假的flag!!!好把,做题的时候我没有发现,(把假的flag求出来后才发现是假的>~<,但不影响啦)继续,

这里,进去__Z7encryptPc函数后,什么都没有,而箭头指向的地方是个循环解密的过程,换至OD中动态调试,运行到 call 401500处,

 f7单步跟踪,发现函数流程如下:

 判断[ebp+0x1c](计数器,起始值为0)的值是否等于0x12,然后从input中取出对应的字符与404012处对应的字符进行异或,异或后的值再与[ebp+eax*4-0x6c]中的值相比较,相等则继续直至退出循环,若有一个不相等则退出程序, 查看[ebp+eax*4-0x6c]中的值,如图:

 因此可以求出flag[0:19]的值,还剩下最后5个,往后继续,有提示"come here",因此继续往下运行,必要时更改标志寄存器的值,跳过一些判断,跳出该函数处

 运行到call 40159a处,f7单步进入,函数开头为,

结尾为

函数开头将5个数,放入了[ebp-0x11]地址处,继续运行至0x401617处,发现就是将flag的第一个字符与开头的第一个字符相比较,若相等则输出Really???若不相等就是输出I hide the last past,但这肯定是不相等的,再结合提示猜测与最后flag的五个字符有关,因为flag最后一位为'}',故猜测flag即为开头五个字符与ord('}')-0x3a异或得到,脚本如下:

c=[0x0E,0x0D,0x09, 0x06,0x13,0x05,0x58, 0x56,0x3E,0x06,0x0C, 0x3C,0x1F,0x57,0x14, 0x6B,0x57,0x59,0xd]

d=[0x25,0x74,0x70,0x26,0x3A]


b='hahahaha_do_you_find_me?'
print(len(a),len(b),len(c))

for i in range(19):
    temp=ord(b[i])^c[i]
    print(chr(temp),end='')

for i in d:
    x=i^(ord('}')^0x3a)
    print(chr(x),end='')

得到结果即为flag!!!

原文地址:https://www.cnblogs.com/jane315/p/13753043.html