def assemble_at(addr, code): code_to_assemble = code.split(";") res, assembled_code = idautils.Assemble(addr, code_to_assemble) if not res: raise ValueError("Impossible to assemble <{0}> at <{1}>".format(code, hex(addr))) full_assembled_code = "".join(assembled_code) return midap.Buffer(addr, len(code)).patch([ord(x) for x in full_assembled_code])
def FindInstructions(instr, asm_where=None): """ Finds instructions/opcodes @return: Returns a tuple(True, [ ea, ... ]) or a tuple(False, "error message") """ if not asm_where: # get first segment seg = ida_segment.get_first_seg() asm_where = seg.start_ea if seg else ida_idaapi.BADADDR if asm_where == ida_idaapi.BADADDR: return (False, "No segments defined") # regular expression to distinguish between opcodes and instructions re_opcode = re.compile('^[0-9a-f]{2} *', re.I) # split lines lines = instr.split(";") # all the assembled buffers (for each instruction) bufs = [] for line in lines: if re_opcode.match(line): # convert from hex string to a character list then join the list to form one string buf = bytes(bytearray([int(x, 16) for x in line.split()])) else: # assemble the instruction ret, buf = idautils.Assemble(asm_where, line) if not ret: return (False, "Failed to assemble:" + line) # add the assembled buffer bufs.append(buf) # join the buffer into one string buf = b''.join(bufs) # take total assembled instructions length tlen = len(buf) # convert from binary string to space separated hex string bin_str = ' '.join( ["%02X" % (ord(x) if sys.version_info.major < 3 else x) for x in buf]) # find all binary strings print("Searching for: [%s]" % bin_str) ea = ida_ida.cvar.inf.min_ea ret = [] while True: ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN) if ea == ida_idaapi.BADADDR: break ret.append(ea) ida_kernwin.msg(".") ea += tlen if not ret: return (False, "Could not match [%s]" % bin_str) ida_kernwin.msg("\n") return (True, ret)
def assemble(self, ea, asm, save_state=True, opt_fix=True, opt_nop=True): """ Assemble into memory """ #Fixup the assemble if opt_fix: regvars = self._getregvars(ea) parts_arr = [self.PART_RE.split(i) for i in asm] asm = [] for parts in parts_arr: asm.append(self._fixup(parts, regvars)) #Assemble to a string success, data = idautils.Assemble(ea, asm) if not success: return success, data blob = ''.join(data) if len(blob) > instr_size(ea): if idaapi.askyn_c( 0, "The assembled instruction is bigger than the current instruction. This will clobber following instructions. Continue?" ) != 1: return #Pad the blob with nops if opt_nop: nsuccess, nop_instr = idautils.Assemble(ea, 'nop') if not nsuccess: return nsuccess, nop_instr i = ea while i < ea + len(blob): i += instr_size(i) #Only pad if we trashed the next instruction sz_diff = (i - (ea + len(blob))) / len(nop_instr) blob += nop_instr * sz_diff #Write out the data old = read_data(ea, len(blob)) if save_state: self._pushundo([(ea, old)]) self.redo_buffer = [] write_data(ea, blob) return success, old
def nopxrefs(self, ea): """ Nop out all xrefs to a function """ nsuccess, nop_instr = idautils.Assemble(ea, 'nop') if not nsuccess: return nsuccess, nop_instr xrefs = idautils.XrefsTo(ea) buf = [] for i in xrefs: success, old = self.assemble(i.frm, ['nop'], False) if not success: continue buf.append((ea, old)) self._pushundo(buf) self.redo_buffer = []
def patch_call(va, new_nm): """Patch the call at @va to target @new_nm. Args: va (numbers.Integral): Address of the call site new_nm (str): Name of the new call destination Returns: bool: True if successful """ is_call = idc.print_insn_mnem(va) == 'call' if is_call: opno = 0 new_asm = 'call %s' % (new_nm) else: logger.warn('Not a call instruction at %s' % (phex(va))) return False # Already done? if idc.print_operand(va, opno) == new_nm: return True ok, code = idautils.Assemble(va, new_asm) if not ok: logger.warn('Failed assembling %s: %s' % (phex(va), new_asm)) return False orig_opcode_len = idc.get_item_size(va) new_code_len = len(code) if orig_opcode_len < new_code_len: logger.warn('Not enough room or wrong opcode type to patch %s: %s' % (phex(va), new_asm)) return False # If we actually have too much room, then add filler if orig_opcode_len > new_code_len: delta = orig_opcode_len - new_code_len code += '\x90' * delta idaapi.patch_bytes(va, code) return True
def assemble(ea, what): succ, code = idautils.Assemble(ea, what) if not succ: raise Exception("failed to assemble " + what) return code
def nopout(self, ea, sz): """ NOP out a section of memory """ nsuccess, nop_instr = idautils.Assemble(ea, 'nop') if not nsuccess: return nsuccess, nop_instr return self.assemble(ea, ['nop'] * (sz / len(nop_instr)))