前言
之前一直想找个方法实现IDA调试的时候自动执行操作,现在终于找到了
ida里面有一个api:ida_dbg.step_into(),效果是执行一次步入,通过循环这个指令就可以实现自动步入的效果,在步过后写自己需要的效果就好
实现
下面是一个对于dasctf,BabyEnc的指令还原脚本,这个题将真的逻辑用汇编写了出来,并把每句汇编放在格式相同的花指令中,通过下面这个脚本可以提取每组汇编中的真实代码,组合成一个函数
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
   | from idc import * import idaapi import idautils import ida_dbg
  statx = 0
  def check_address(target_ea):     with open("trace_output.bin", "ab") as f:         while True:             ida_dbg.wait_for_next_event(ida_dbg.WFNE_SUSP, -1)             current_ea = ida_dbg.get_reg_val("EIP")             if current_ea == target_ea:                 print("finished")                 break             else:                 handle_instruction(current_ea, f)                 ida_dbg.step_into()
  def handle_instruction(ea, file):     global statx     statx-=1     if(statx <= 0):         instr = idc.GetDisasm(ea)         if "jmp     ebx" in instr:             statx = 11             count = 0             ea_temp = ea             prev_instr = ""             while count < 11:                 ea_temp = idc.prev_head(ea_temp)                 prev_instr = idc.GetDisasm(ea_temp)                 count += 1             if "popa" not in prev_instr and "cmp" not in prev_instr:                 machine_code = ida_bytes.get_bytes(ea_temp, idc.get_item_size(ea_temp))                 file.write(machine_code)                 print(prev_instr)
  check_address(0x0041F082)
   | 
 
另一种实现是依赖断点的实现,继承DBG_hooks实现断点钩子,需要准确知道在哪里下断点才行,感觉有点麻烦,不过要是能算出来具体的位置,那也很简单,速度也更快
缺点
需要的时间太长了,尤其是在有长花指令的情况下,这段代码大概执行了90分钟左右,但是没有花指令一般好像也不需要这种操作(也许控制流混淆需要?)。不过另外一方面,编写这种脚本不需要脑子,不需要主动获取寄存器的值,模拟执行可能写的有偏差,但是这种就肯定不会错。