爆破 sha256 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import itertoolsimport hashlibimport refrom pwn import *import stringr=remote("111.186.58.164" ,30212 ) proof_of_work_line = r.recvline(keepends=False ).decode("utf-8" ) enc = re.search('== (.*)' ,proof_of_work_line).group(1 ) strlist=itertools.product(string.ascii_letters+string.digits,repeat=4 ) code="" key="hUsUzJ47UdPwwTns" enc="ac2b009cf8ab722c6417f0dff94a24434a7d7c43f12da21a042faa34295efe22" for i in strlist: code=i[0 ]+i[1 ]+i[2 ]+i[3 ] encinfo=hashlib.sha256(str (code+key).encode('utf-8' )).hexdigest() if encinfo == enc: print (code) break ;
1.itertools.product(‘ABCD’, repeat = 2) 排列组合(笛卡尔积)
结果:AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
也可以是两个元组排列组合
2.itertools.permutations(‘ABCD’, 2) 所有可能的排列,无重复元素
结果:AB AC AD BA BC BD CA CB CD DA DB DC
3.itertools.combinations(‘ABCD’, 2) 有序,无重复元素
结果:AB AC AD BC BD CD
4.itertools.combinations_with_replacement(‘ABCD’, 2) 有序,元素可重复
结果:AA AB AC AD BB BC BD CC CD DD
用插件去除 ollvm 混淆 插件介绍:https://eshard.com/posts/d810_blog_post_1/
下载地址:https://gitlab.com/eshard/d810
这个插件提供多个 rules 来反混淆,也可以自己添加规则 。在这题中使用了对控制流的混淆,勾选这一选项就可以实现反混淆
使用前后对比
用idaPython去除花指令
从简化后的流程看可以知道有两处反调试,还有一处 smc 自解密
smc 后 [rbp+s] 指向解密后的代码,因为代码比较长就用脚本提取出来分析
一些 idapython 函数 idaapi:
BADADDR:4294967295 地址上界
del_items(ea, flags=0, nbytes=1, may_destroy=None):Convert item (instruction/data) to unexplored bytes
create_insn(ea, out=None):Create an instruction at the specified address
get_first_cref_from(frm):Get first instruction referenced from the specified instruction
1 2 3 4 5 6 7 8 9 from idaapi import *start=0x00007F96D2BBB000 count = 0x100000 f=open ('C:\\Users\\chz\\Desktop\\smc' ,'wb' ) for i in range (0 ,count): f.write(get_byte(start+i).to_bytes(1 ,byteorder='big' )) f.close() print ("success" )
ida 分析后有一大堆花指令,手动分析时间太久考虑用脚本去除
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 import idaapiimport idcdef undefine (start,end ): curr=start while curr != idaapi.BADADDR and curr < end: idaapi.del_items(curr, 8 ) curr=curr+1 def make_code (start,end ): curr=start while curr != idaapi.BADADDR and curr < end: insn = idaapi.insn_t() ret = idaapi.create_insn(curr, insn) if ret == 0 : idaapi.del_items(curr, 8 ) idaapi.del_items(curr+1 , 8 ) ret = idaapi.create_insn(curr, insn) next_ea = idaapi.get_first_cref_from(curr) if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F : curr = curr+1 else : curr=next_ea print (curr) def clear (start,end ): curr=start while curr != idaapi.BADADDR and curr < end: insn = idaapi.insn_t() if idc.GetDisasm(curr)[0 :1 ]=='j' or idc.GetDisasm(curr)[0 :4 ]=='call' : jmp_addr=idc.GetOperandValue(curr,0 ) ret = idaapi.create_insn(jmp_addr, insn) if ret == 0 : idaapi.del_items(jmp_addr, 8 ) idaapi.del_items(jmp_addr+2 , 8 ) idaapi.del_items(jmp_addr+4 , 8 ) ret = idaapi.create_insn(curr, insn) next_ea = idaapi.get_first_cref_from(curr) if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F : curr = curr+1 else : curr=next_ea print (curr) def nop (start,end ): curr=start while curr != idaapi.BADADDR and curr < end: if idc.is_data(curr): idc.PatchByte(curr,0x90 ) next_ea = idaapi.get_first_cref_from(curr) if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F : curr = curr+1 else : curr=next_ea print (curr) nop(0x0 ,0x224c6 )
但是好像写得有点太复杂了,也没法完全实现自动 patch
参考资料