gatesXgame
1 upx
直接百度得到脱壳机
2 花指令
研究了一下发现模式固定=.=,直接010editor替换即可
1 2 3 4 5 6 7 8 9 10 11
| In [2]: asm('jmp $+5') Out[2]: '\xeb\x03'
In [3]: asm('jmp $+6') Out[3]: '\xeb\x04'
In [4]: asm('jmp $+8') Out[4]: '\xeb\x06'
In [5]: asm('jmp $+7') Out[5]: '\xeb\x05'
|
然后nop掉没用的东西
3 小插曲
不知道为啥动态调试总是出问题(输入的第一字节位空),猜测可能是壳子的问题?=.=不影响解题,判断逻辑直接暴力jmp即可
4 retfq
ida调试炸了,x64dbg调试炸了=.=,上网搜了搜发现是一种反调试
CTF中32位程序调用64位代码的逆向方法
根据解决办法找到了windbg/x64
调试即可
发现逻辑并不复杂,但是数量很多
5 dump&分析程序
通过上述操作,发现关键点在动态的那段代码,直接dump+修复花指令
得到稍微能看的汇编,理出程序逻辑(我一开始还单纯以为只是简单的几条,准备手动搞来着
发现数据极多
写出脚本提取数据
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 49 50 51
| def searchip(ip,tstr): ends = False while not ends: asm = GetDisasm(ip) if 'mov' in asm and 'sp' in asm and 'h' in asm: ends = True return str(int('0'+asm.split(',')[-1][:-1].replace(' ','').split(';')[0].replace('h',''),16)) ip+=1 def search(ip,tstr): ends = False while not ends: asm = GetDisasm(ip) if 'cmp' in asm and 'al' in asm: ttstr=tstr+'\t'+ asm.split(';')[-1].replace('\'','')+'\t' ip+=2 asm = GetDisasm(ip) if 'jz' in asm: nextip = int(asm.split('_')[-1],16) ttstr+=searchip(nextip,tstr) print(ttstr) if 'xor' in asm and 'ax' in asm: ends = True break ip+=1
count = 0 ip = 0 while ip < 0x30D0: asm = GetDisasm(ip) if 'cmp' in asm and "ecx" in asm: print('+'*20) tstr = str(ip) ip = ip+2 search(ip,tstr) count+=1 elif 'cmp' in asm and "rcx" in asm: print('+'*20) tstr = str(ip) ip=ip+3 search(ip,tstr) count+=1 else: ip+=1 print('count %d'%count)
|
6 最短路求解=.=
得到flag
npointer{f4fce95b63f57187c9424ae06cf1a86f}