def __call__(self): if self.op == "hex": ida_bytes.op_hex(self.ea, self.n) if self.op == "bin": ida_bytes.op_bin(self.ea, self.n) if self.op == "dec": ida_bytes.op_dec(self.ea, self.n) if self.op == "chr": ida_bytes.op_chr(self.ea, self.n) if self.op == "oct": ida_bytes.op_oct(self.ea, self.n) if self.op == "offset": ida_idc.op_plain_offset(self.ea, self.n, 0) if self.op == "enum": id = ida_enum.get_enum(self.extra["ename"]) ida_bytes.op_enum(self.ea, self.n, id, self.extra["serial"]) if self.op == "struct": path_len = len(self.extra["spath"]) path = ida_pro.tid_array(path_len) for i in range(path_len): sname = self.extra["spath"][i] path[i] = ida_struct.get_struc_id(sname) insn = ida_ua.insn_t() ida_ua.decode_insn(insn, self.ea) ida_bytes.op_stroff(insn, self.n, path.cast(), path_len, self.extra["delta"]) if self.op == "stkvar": ida_bytes.op_stkvar(self.ea, self.n)
def __call__(self): if self.op == 'hex': ida_bytes.op_hex(self.ea, self.n) if self.op == 'bin': ida_bytes.op_bin(self.ea, self.n) if self.op == 'dec': ida_bytes.op_dec(self.ea, self.n) if self.op == 'chr': ida_bytes.op_chr(self.ea, self.n) if self.op == 'oct': ida_bytes.op_oct(self.ea, self.n) if self.op == 'enum': id = ida_enum.get_enum(Event.encode(self.extra['ename'])) ida_bytes.op_enum(self.ea, self.n, id, self.extra['serial']) if self.op == 'struct': path_len = len(self.extra['spath']) path = ida_pro.tid_array(path_len) for i in xrange(path_len): sname = Event.encode(self.extra['spath'][i]) path[i] = ida_struct.get_struc_id(sname) insn = ida_ua.insn_t() ida_ua.decode_insn(insn, self.ea) ida_bytes.op_stroff(insn, self.n, path.cast(), path_len, self.extra['delta']) if self.op == 'stkvar': ida_bytes.op_stkvar(self.ea, self.n)
def _on_optypechanged(self, ea, n, op, extra): if op == 'hex': ida_bytes.op_hex(ea, n) if op == 'bin': ida_bytes.op_bin(ea, n) if op == 'dec': ida_bytes.op_dec(ea, n) if op == 'chr': ida_bytes.op_chr(ea, n) if op == 'oct': ida_bytes.op_oct(ea, n) if op == 'stkvar': ida_bytes.op_stkvar(ea, n) if op == 'enum': enum_id = ida_enum.get_enum(str(extra['ename'])) ida_bytes.op_enum(ea, n, enum_id, extra['serial']) if op == 'struct': path_length = len(extra['spath']) path = ida_pro.tid_array(path_length) for i in range(path_length): sname = str(extra['spath'][i]) path[i] = ida_struct.get_struc_id(sname) insn = ida_ua.insn_t() ida_ua.decode_insn(insn, ea) ida_bytes.op_stroff(insn, n, path.cast(), path_length, extra['delta'])
def apply_struct_offset(inst, operand_no, struct_name): if not import_type(struct_name): print "ERROR: Can't import '{}'".format(struct_name) return path_len = 1 path = ida_pro.tid_array(path_len) path[0] = ida_struct.get_struc_id(struct_name) ida_bytes.op_stroff(inst, operand_no, path.cast(), path_len, 0)
def op_type_changed(self, ea, n): self._plugin.logger.debug("op_type_changed(ea = %x, n = %d)" % (ea, n)) def gather_enum_info(ea, n): id = ida_bytes.get_enum_id(ea, n)[0] serial = ida_enum.get_enum_idx(id) return id, serial extra = {} mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE flags = ida_bytes.get_full_flags(ea) self._plugin.logger.debug("op_type_changed: flags = 0x%X)" % flags) def is_flag(type): return flags & mask == mask & type if is_flag(ida_bytes.hex_flag()): op = "hex" elif is_flag(ida_bytes.dec_flag()): op = "dec" elif is_flag(ida_bytes.char_flag()): op = "chr" elif is_flag(ida_bytes.bin_flag()): op = "bin" elif is_flag(ida_bytes.oct_flag()): op = "oct" elif is_flag(ida_bytes.off_flag()): op = "offset" elif is_flag(ida_bytes.enum_flag()): op = "enum" id, serial = gather_enum_info(ea, n) ename = ida_enum.get_enum_name(id) extra["ename"] = Event.decode(ename) extra["serial"] = serial elif flags & ida_bytes.stroff_flag(): op = "struct" path = ida_pro.tid_array(1) delta = ida_pro.sval_pointer() path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea, n) spath = [] for i in range(path_len): sname = ida_struct.get_struc_name(path[i]) spath.append(Event.decode(sname)) extra["delta"] = delta.value() extra["spath"] = spath elif is_flag(ida_bytes.stkvar_flag()): op = "stkvar" # FIXME: No hooks are called when inverting sign # elif ida_bytes.is_invsign(ea, flags, n): # op = 'invert_sign' else: return 0 # FIXME: Find a better way to do this self._send_packet(evt.OpTypeChangedEvent(ea, n, op, extra)) return 0
def op_type_changed(self, ea, n): def gather_enum_info(ea, n): id = ida_bytes.get_enum_id(ea, n)[0] serial = ida_enum.get_enum_idx(id) return id, serial extra = {} mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE flags = ida_bytes.get_full_flags(ea) & mask def is_flag(type): return flags == mask & type if is_flag(ida_bytes.hex_flag()): op = 'hex' elif is_flag(ida_bytes.dec_flag()): op = 'dec' elif is_flag(ida_bytes.char_flag()): op = 'chr' elif is_flag(ida_bytes.bin_flag()): op = 'bin' elif is_flag(ida_bytes.oct_flag()): op = 'oct' elif is_flag(ida_bytes.enum_flag()): op = 'enum' id, serial = gather_enum_info(ea, n) ename = ida_enum.get_enum_name(id) extra['ename'] = Event.decode(ename) extra['serial'] = serial elif is_flag(flags & ida_bytes.stroff_flag()): op = 'struct' path = ida_pro.tid_array(1) delta = ida_pro.sval_pointer() path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea, n) spath = [] for i in range(path_len): sname = ida_struct.get_struc_name(path[i]) spath.append(Event.decode(sname)) extra['delta'] = delta.value() extra['spath'] = spath elif is_flag(ida_bytes.stkvar_flag()): op = 'stkvar' # IDA hooks for is_invsign seems broken # Inverting sign don't trigger the hook # elif ida_bytes.is_invsign(ea, flags, n): # op = 'invert_sign' else: return 0 # FIXME: Find a better way self._send_event(OpTypeChangedEvent(ea, n, op, extra)) return 0
def op_type_changed(self, ea, n): extra = {} mask = ida_bytes.MS_0TYPE if not n else ida_bytes.MS_1TYPE flags = ida_bytes.get_full_flags(ea) & mask if flags == mask & ida_bytes.hex_flag(): op = 'hex' elif flags == mask & ida_bytes.dec_flag(): op = 'dec' elif flags == mask & ida_bytes.char_flag(): op = 'chr' elif flags == mask & ida_bytes.bin_flag(): op = 'bin' elif flags == mask & ida_bytes.oct_flag(): op = 'oct' elif flags == mask & ida_bytes.enum_flag(): op = 'enum' enum_id = ida_bytes.get_enum_id(ea, n)[0] enum_serial = ida_enum.get_enum_idx(enum_id) ename = ida_enum.get_enum_name(enum_id) extra['ename'] = Unicoder.decode(ename) extra['serial'] = enum_serial elif flags == mask & ida_bytes.stroff_flag(): op = 'struct' path = ida_pro.tid_array(1) delta = ida_pro.sval_pointer() path_len = ida_bytes.get_stroff_path(path.cast(), delta.cast(), ea, n) spath = [] for i in range(path_len): sname = ida_struct.get_struc_name(path[i]) spath.append(Unicoder.decode(sname)) extra['delta'] = delta.value() extra['spath'] = spath elif flags == mask & ida_bytes.stkvar_flag(): op = 'stkvar' else: return 0 self._network.send_event( EventType.OPTYPECHANGED, ea=ea, n=n, op=Unicoder.decode(op), extra=extra, ) return 0
def analyze_function_frame(self, function: Function) -> None: """ inspect the given function to determine the frame layout and set references appropriately. args: function (Function): function instance. """ # given a function prologue like the following: # # 23 80 80 80 80 00 get_global $global0 # 21 04 set_local $local4 # 41 20 i32.const 0x20 # 21 05 set_local $local5 # 20 04 get_local $local4 # 20 05 get_local $local5 # 6B i32.sub # 21 06 set_local $local6 # # recognize that the function frame is 0x20 bytes. if not self.has_llvm_prologue(function): return bc = self.get_prologue_bc(function['offset']) if len(bc) == 0: return global_frame_pointer = bc[0].imm.global_index frame_size = bc[2].imm.value local_frame_pointer = bc[7].imm.local_index # add a frame structure to the function f = ida_funcs.get_func(function['offset']) ida_frame.add_frame(f, 0x0, 0x0, frame_size) ida_struct.set_struc_name(f.frame, 'frame%d' % function['index']) # ensure global variable $frame_stack is named appropriately ida_name.set_name(self.proc.globals[global_frame_pointer]['offset'], '$frame_stack') # re-map local variable to $frame_pointer ida_frame.add_regvar(f, function['offset'], function['offset'] + function['size'], '$local%d' % local_frame_pointer, '$frame_pointer', '') # define the frame structure layout by scanning for references within this function frame_references = self.find_function_frame_references( function, local_frame_pointer) for frame_offset, refs in frame_references.items(): member_name = 'field_%x' % frame_offset for ref in refs: if 'parameter' in ref: member_name = 'param%d' % (ref['parameter']) # pick largest element size for the element type flags = 0 size = 0 for ref in refs: fl = { 'i8': ida_bytes.FF_BYTE | ida_bytes.FF_DATA, 'i16': ida_bytes.FF_WORD | ida_bytes.FF_DATA, 'i32': ida_bytes.FF_DWORD | ida_bytes.FF_DATA, 'i64': ida_bytes.FF_QWORD | ida_bytes.FF_DATA, 'f32': ida_bytes.FF_FLOAT | ida_bytes.FF_DATA, 'f64': ida_bytes.FF_DOUBLE | ida_bytes.FF_DATA, }[ref['element_size']] s = { 'i8': 1, 'i16': 2, 'i32': 4, 'i64': 8, 'f32': 4, 'f64': 8, }[ref['element_size']] # by luck, FF_BYTE < FF_WORD < FF_DWORD < FF_QWORD, # so we can order flag values. if fl > flags: flags = fl size = s logger.debug('adding frame member %s to function %d', member_name, function['index']) ida_struct.add_struc_member(ida_struct.get_struc(f.frame), member_name, frame_offset, flags & 0xFFFFFFFF, None, size) # mark struct references for refs in frame_references.values(): for ref in refs: # set type of operand 0 to function frame structure offset # ref: https://github.com/idapython/src/blob/a3855ab969fd16758b3de007525feeba3a920344/tools/inject_pydoc/bytes.py#L5 insn = ida_ua.insn_t() if not ida_ua.decode_insn(insn, ref['offset']): continue path = ida_pro.tid_array(1) path[0] = f.frame ida_bytes.op_stroff(insn, 0, path.cast(), 1, 0)
def get_operand_struct_name(inst, op_no): path_len = 1 path = ida_pro.tid_array(path_len) if ida_bytes.get_stroff_path(path.cast(), None, inst.ea, op_no): return ida_struct.get_struc_name(path[0]) return ''