def extract_insn_number_features(f, bb, insn): """parse instruction number features args: f (IDA func_t) bb (IDA BasicBlock) insn (IDA insn_t) example: push 3136B0h ; dwControlCode """ if idaapi.is_ret_insn(insn): # skip things like: # .text:0042250E retn 8 return if capa.features.extractors.ida.helpers.is_sp_modified(insn): # skip things like: # .text:00401145 add esp, 0Ch return for op in capa.features.extractors.ida.helpers.get_insn_ops( insn, target_ops=(idaapi.o_imm, idaapi.o_mem)): # skip things like: # .text:00401100 shr eax, offset loc_C if capa.features.extractors.ida.helpers.is_op_offset(insn, op): continue if op.type == idaapi.o_imm: const = capa.features.extractors.ida.helpers.mask_op_val(op) else: const = op.addr yield Number(const), insn.ea yield Number(const, arch=get_arch(f.ctx)), insn.ea
def extract_insn_number_features(f, bb, insn): """ parse instruction number features args: f (IDA func_t) bb (IDA BasicBlock) insn (IDA insn_t) example: push 3136B0h ; dwControlCode """ if idaapi.is_ret_insn(insn): # skip things like: # .text:0042250E retn 8 return if capa.features.extractors.ida.helpers.is_sp_modified(insn): # skip things like: # .text:00401145 add esp, 0Ch return for op in capa.features.extractors.ida.helpers.get_insn_ops( insn, target_ops=(idaapi.o_imm, )): const = capa.features.extractors.ida.helpers.mask_op_val(op) if not idaapi.is_mapped(const): yield Number(const), insn.ea yield Number(const, arch=get_arch(f.ctx)), insn.ea
def is_ret(self): """ Property indicating if this instruction is a ret. :return bool: True if this instruction is a ret, False otherwise. """ return idaapi.is_ret_insn(self.ea)
def decode_instruction(address): # DEBUG #print("Decoding instruction: 0x%x" % address) i = DecodeInstruction(address) mnemonic = i.get_canon_mnem() ops = [] ignore_ops = False if isinstance(__builtin__.REGISTERS, RegistersX64): # uses floating point register "st" which has # overlapping index with "rax" and so on ignore_ops = mnemonic in [ "fabs,", "fadd", "faddp", "fbld", "fbstp", "fchs", "fclex", "fcmov", "fcmovb", "fcmovbe", "fcmove", "fcmovnb", "fcmovnbe", "fcmovne", "fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp", "fcompp", "fdecstp", "fdiv", "fdivp", "fdivr", "fdivrp", "ffree", "fiadd", "ficom", "ficomp", "fidiv", "fidivr", "fild", "fimul", "fincstp", "finit", "fist", "fistp", "fisub", "fisubr", "fld," "fld1", "fldcw", "fldenv", "fldenvw", "fldl2e", "fldl2t", "fldlg2", "fldln2", "fldpi", "fldz", "fmul", "fmulp", "fnclex", "fndisi", "fneni", "fninit", "fnop", "fnsave", "fnsavew", "fnstcw", "fnstenv", "fnstenvw", "fnstsw", "fpatan", "fprem", "fptan", "frndint", "frstor", "frstorw", "fsave", "fsavew", "fscale", "fsqrt", "fst", "fstcw", "fstenv", "fstenvw", "fstp", "fstsw", "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucomi", "fucomip", "fwait", "fxam", "fxch", "fxtract", "fyl2x", "fyl2xp1" ] if not ignore_ops: for o in range(6): if i[o].type == o_void: break # NOTE: for x64 we only consider 64 bit granularity at the moment. ida_operand_str = GetOpnd(address, o) # Some instructions like "stosq" do not have string operands # => ignore for now. if ida_operand_str == "": break # DEBUG #print(ida_operand_str) operand = instruction.Operand(get_operand_access_type(i, o), i[o], ida_operand_str=ida_operand_str, address=address, op_num=o) normalized = normalize_operand(operand) ops.extend(normalized) is_control_flow = is_ret_insn(address) or \ len(list(CodeRefsFrom(address, 1))) > 1 return instruction.Instruction(address, mnemonic, ops, is_control_flow)
def extract_insn_number_features(f, bb, insn): """parse instruction number features args: f (IDA func_t) bb (IDA BasicBlock) insn (IDA insn_t) example: push 3136B0h ; dwControlCode """ if idaapi.is_ret_insn(insn): # skip things like: # .text:0042250E retn 8 return if capa.features.extractors.ida.helpers.is_sp_modified(insn): # skip things like: # .text:00401145 add esp, 0Ch return for i, op in enumerate(insn.ops): if op.type == idaapi.o_void: break if op.type not in (idaapi.o_imm, idaapi.o_mem): continue # skip things like: # .text:00401100 shr eax, offset loc_C if capa.features.extractors.ida.helpers.is_op_offset(insn, op): continue if op.type == idaapi.o_imm: const = capa.features.extractors.ida.helpers.mask_op_val(op) else: const = op.addr yield Number(const), insn.ea yield OperandNumber(i, const), insn.ea if insn.itype == idaapi.NN_add and 0 < const < MAX_STRUCTURE_SIZE and op.type == idaapi.o_imm: # for pattern like: # # add eax, 0x10 # # assume 0x10 is also an offset (imagine eax is a pointer). yield Offset(const), insn.ea yield OperandOffset(i, const), insn.ea
def is_ret(self, ea): return idaapi.is_ret_insn(ea)
def is_ret(self): """Is the instruction a return instruction.""" return idaapi.is_ret_insn(self._ea)
def is_ret(self): """Is the instruction a return instruction.""" return idaapi.is_ret_insn(self._insn)
def raw_main(p=True): global res # find .text section startEA first #text_startEA = None #for s in Segments(): # if SegName(s) == '.text': # text_startEA = s # break #if text_startEA is None: # text_startEA = 0 #f = idaapi.get_func(text_startEA) f = idaapi.get_next_func(0) fc = idaapi.FlowChart(f) while f: funcea = f.startEA fn = GetFunctionName(funcea) # if "Pl" in fn: # funcaddr = f.startEA # f = idaapi.get_next_func(funcaddr) # continue q = idaapi.qflow_chart_t("The title", f, 0, 0, idaapi.FC_PREDS) res.append("##############################\n") for n in xrange(0, q.size()): b = q[n] if p: res.append("%x - %x [%d]:\n" % (b.startEA, b.endEA, n)) for ns in xrange(0, q.nsucc(n)): res.append("SUCC: %d->%d\n" % (n, q.succ(n, ns))) pred_set = set() for ns in xrange(0, q.npred(n)): res.append("PRED: %d->%d\n" % (n, q.pred(n, ns))) pred_set.add(q.pred(n, ns)) if q.nsucc(n) == 0: # this is a block with no successors last_insn = None for h in Heads(b.startEA, b.endEA): last_insn = h if last_insn is None: continue insn = DecodeInstruction(last_insn) if idaapi.is_ret_insn(insn): continue disasm_str = GetDisasm(last_insn) if 'abort' in disasm_str or 'exit' in disasm_str or 'hlt' in disasm_str or '___stack_chk_fail' in disasm_str or '___assert_fail' in disasm_str: continue if idaapi.is_indirect_jump_insn(insn): # if this function ends with an indirect jump, it means ida failed to # determine the successors. We treat all blocks in this function as possible successors #with open('wierd_jump.txt', 'a') as tmp_f: # tmp_f.write(disasm_str + '\n') for tn in xrange(0, q.size()): res.append("SUCC: %d->%d\n" % (n, tn)) if tn not in pred_set: res.append("PRED: %d->%d\n" % (tn, n)) elif idaapi.is_call_insn(insn): # if this function ends with a call (not something like abort), it is somewhat wierd. # do not solve this temporarily #with open('wierd_call.txt', 'a') as tmp_f: # tmp_f.write(disasm_str + '\n') for tn in xrange(0, q.size()): res.append("SUCC: %d->%d\n" % (n, tn)) if tn not in pred_set: res.append("PRED: %d->%d\n" % (tn, n)) funcaddr = f.startEA f = idaapi.get_next_func(funcaddr)
def isReturn(ea): return idaapi.is_ret_insn(ea)