巅峰极客reverse baby_maze 这题通过ida64打开后发现是很多个函数写的地图,人看傻了`(>﹏< )′
后来一想 直接找到终点的函数,然后利用交叉引用溯回到起点就行了(”好像”还挺简单的😃)
通过字符串.
Good Job. \nAnd the flag is flag md5(your input)\nIf not, you may need to go faster!
找到终点sub_54DE35
通过Welcome to TastelessMaze! 找到主函数再找到起点sub_40187C()
我原本一个一个慢慢往上溯回,结果卡死了
出现了这种情况
我需要看是谁走到了sub_53E6B7 一看D先走了sub_53CE65()这个函数,再来走sub_53E6B7
sub_53CE65()里面又是switch 人麻了🤡
我莫得办法
事后看师傅们的wp,QAQ,直接正面暴力莽,利用idapython中的gen_r_call_chain
函数
学习网址:
https://blog.51cto.com/watertoeast/2287039
https://zhuanlan.zhihu.com/p/395205287
但是基于本题的话,一直递推到终点就可以回溯了,所以要再gen_r_call_chain中添加一个终点的参数
还要查询函数get_my_callee
,来得到xref的引用函数列表
也就是
ida快捷键 Shift+F2
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 from __future__ import print_functionimport idautilsvisited_func = set () steps = [] r_call_chain = [] idx2chr = {4 : 'W' ,5 : 'D' ,6 : 'S' ,7 : 'A' } def gen_r_call_chain (func_name, osintneting,destination ): del r_call_chain[:] del steps[:] visited_func = set () get_my_caller(func_name, osintneting,destination) def get_my_caller (func_name, osintneting,destination ): cstr = '{0}\t' .format (func_name) if cstr not in visited_func: r_call_chain.append(cstr) visited_func.add(cstr) else : return addr = get_name_ea(0 , func_name) addr_ref_to = get_first_fcref_to(addr) osinteneting_end = False if addr_ref_to == BADADDR: osinteneting_end = True elif osintneting == -1 : osinteneting_end = False elif osintneting == 1 : osinteneting_end = True if (destination == func_name or osintneting == 1 ): length = len (steps) for idx in range (length): sys.stdout.write(steps[length - idx - 1 ]) sys.stdout.write(' ' + func_name) sys.stdout.write("\n" ) r_call_chain.pop() return if osinteneting_end is True : return while (addr_ref_to != BADADDR) and (addr_ref_to != addr): parent_func_name = get_func_name(addr_ref_to) callee_list = get_my_callee(parent_func_name) ids = callee_list.index(func_name) steps.append(idx2chr[ids]) get_my_caller(parent_func_name, osintneting - 1 ,destination) steps.pop() addr_ref_to = get_next_fcref_to(addr, addr_ref_to) if addr_ref_to == BADADDR: r_call_chain.pop() break def get_my_callee (func_name ): addr = get_name_ea(0 , func_name) dism_addr = list (idautils.FuncItems(addr)) xref_froms = [] for ea in dism_addr: if ida_idp.is_call_insn(ea) is False : continue else : callee = get_first_fcref_from(ea) if callee != addr: xref_froms.append(callee) names = [get_func_name(callee) for callee in xref_froms] return names gen_r_call_chain('sub_54DE35' , 600 , 'sub_40187C' )
idx2chr = {4: 'W',5: 'D',6: 'S',7: 'A'}
的原因是从汇编来看
callee_list , func_name , cur_id
[‘sub_55D500’, ‘sub_597460’, ‘sub_55F1F0’, ‘sub_597460’, ‘sub_4EB7E3’, ‘sub_4ED806’, ‘sub_4F11F5’, ‘sub_55D500’, ‘sub_55BD20’]
sub_4F11F5
6
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 void sub_4ED753() { char v0; // [rsp+Fh] [rbp-1h] sub_55D500((__int64)"Just do it"); while ( 1 ) { sub_597460(0LL); v0 = sub_55F1F0(); sub_597460(0LL); switch ( v0 ) { case 'A': goto LABEL_6; case 'D': goto LABEL_4; case 'Q': sub_55BD20(0); case 'S': goto LABEL_5; case 'W': sub_4EB7E3(0LL, 0LL); LABEL_4: sub_4ED806(0LL, 0LL); LABEL_5: sub_4F11F5(0LL, 0LL); LABEL_6: sub_55D500((__int64)"OUCH!!!!"); break; default: continue; } } }
对应的就是4: ‘W’,5: ‘D’,6: ‘S’,7: ‘A’
运行脚本后,第一个最短而且到达了终点
由于开始的时候需要“S”一下进入地图,所以在加上一个S,md5后得到flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void __noreturn sub_40180E () { char v0; sub_55D500((__int64)"This is the beginning. You can only go south." ); do { sub_597460(0LL ); v0 = sub_55F1F0(); sub_597460(0LL ); if ( v0 == 'Q' ) goto LABEL_5; } while ( v0 != 'S' ); sub_40187C(); LABEL_5: sub_55BD20(0 ); }