-
-
[原创]2019KCTF总决赛 第六题:三道八佛 WP
-
发表于: 2019-12-14 22:11 4286
-
先拉到x32dbg粗略分析下。
注意到用户名后面有填充数据。
密码则是从十六进制文本转换成字节数据,然后程序开始自解码。
$calleax = 0 $num = 0 $jnzaddr = 0 $f = 0 $prevaddr = 0 $retaddr=0 $hasj=0 bph 004014DF run //input the username and password bphc start: find cip,FFD0,0x200 cmp $result,0 je over mov $calleax,$result bph $calleax run bphc inc $num StepInto StepInto StepOver mov $jnzaddr,cip find_jnz: find cip,8BE55DC3,0x220 cmp $result,0 je nobp mov $retaddr,$result bph $retaddr+3 run bphc StepInto StepInto inc $num mov $jnzaddr,cip nobp: find jnzaddr,75??,0x200 cmp $result,0 jnz isjnz jnzs: find cip,0F85????????,0x200 cmp $result,0 jnz isjnzs jmp nofound runtojnz: mov f,0 bph $jnzaddr+2 mov $hasj,1 jmp jnzs runtojnzs: mov f,0 mov $jnzaddr,$result bph $jnzaddr+6 run bphc mov $hasj,0 nofound: cmp $hasj,1 jnz nojump mov $hasj,0 run bphc nojump: jmp start isjnz: mov $jnzaddr,$result $prevaddr = dis.prev($jnzaddr) $prevaddr = $prevaddr + dis.len($prevaddr) cmp $prevaddr,$jnzaddr je runtojnz add $jnzaddr,2 jmp find_jnz isjnzs: mov $jnzaddr,$result $prevaddr = dis.prev($jnzaddr) $prevaddr = $prevaddr + dis.len($prevaddr) cmp $prevaddr,$jnzaddr je runtojnzs cmp $hasj,1 jnz noj jmp nofound noj: add $jnzaddr,2 jmp find_jnz over: cmp f,0 jnz end mov f,1 jnzaddr=cip jmp find_jnz end: log decryptnum:{$num} msg "over"
$calleax = 0 $num = 0 $jnzaddr = 0 $f = 0 $prevaddr = 0 $retaddr=0 $hasj=0 bph 004014DF run //input the username and password bphc start: find cip,FFD0,0x200 cmp $result,0 je over mov $calleax,$result bph $calleax run bphc inc $num StepInto StepInto StepOver mov $jnzaddr,cip find_jnz: find cip,8BE55DC3,0x220 cmp $result,0 je nobp mov $retaddr,$result bph $retaddr+3 run bphc StepInto StepInto inc $num mov $jnzaddr,cip nobp: find jnzaddr,75??,0x200 cmp $result,0 jnz isjnz jnzs: find cip,0F85????????,0x200 cmp $result,0 jnz isjnzs jmp nofound runtojnz: mov f,0 bph $jnzaddr+2 mov $hasj,1 jmp jnzs runtojnzs: mov f,0 mov $jnzaddr,$result bph $jnzaddr+6 run bphc mov $hasj,0 nofound: cmp $hasj,1 jnz nojump mov $hasj,0 run bphc nojump: jmp start isjnz: mov $jnzaddr,$result $prevaddr = dis.prev($jnzaddr) $prevaddr = $prevaddr + dis.len($prevaddr) cmp $prevaddr,$jnzaddr je runtojnz add $jnzaddr,2 jmp find_jnz isjnzs: mov $jnzaddr,$result $prevaddr = dis.prev($jnzaddr) $prevaddr = $prevaddr + dis.len($prevaddr) cmp $prevaddr,$jnzaddr je runtojnzs cmp $hasj,1 jnz noj jmp nofound noj: add $jnzaddr,2 jmp find_jnz over: cmp f,0 jnz end mov f,1 jnzaddr=cip jmp find_jnz end: log decryptnum:{$num} msg "over"
跑完发现有1403层smc,相比之前的题算是手下留情了吧。
用脚本跑到最后一层,发现下面的代码是完整的函数,代码很长,还有很多重定位和混淆,故先全部提取到code文件并修正一下esi。
用IDA分析code文件,先修改基址为0x1A1857E,F5代码如下。
代码比较清晰了,serial经过计算,跟用户名比较,如果相同则成功。
注意KCTF用户名不足16位,后面的填充数据也是要比较的。也就是说实际上比较的是
4B 43 54 46 00 1A 19 18 17 16 15 14 13 12 11 10 00
提取反编译以后的代码,重新编译成exe以后使用angr跑出来flag。 这部分交给队友FiveEyes处理了。
python代码如下
# coding=utf-8 import angr import claripy import base64 def main(): load_option = {} b = angr.Project("./ConsoleApplication21.exe", load_options=load_option) state = b.factory.blank_state(addr=0x401040) concrete_addr = 0x404378 flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(30)] flag = claripy.Concat(*flag_chars) state.memory.store(concrete_addr, flag) sm = b.factory.simulation_manager(state) print sm.explore(find=0x4013A3) found = sm.found[0] temp = (found.posix.dumps(0)) print temp solution = found.solver.eval(flag, cast_to=str) s = [] for i in solution: s.append(ord(i)) print s print solution.encode("hex").upper() print(solution) print flag, found if __name__ == '__main__': main()
运行结果
得到flag:6CCDE9D2EC1D469DC67C647E66B4C565
用脚本跑到最后一层,发现下面的代码是完整的函数,代码很长,还有很多重定位和混淆,故先全部提取到code文件并修正一下esi。
用IDA分析code文件,先修改基址为0x1A1857E,F5代码如下。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-12-15 00:24
被梦游枪手编辑
,原因:
赞赏
他的文章
谁下载
无
谁下载
无
看原图
赞赏
雪币:
留言: