def btn_save_on_click(self): flags = 0 if self.f_prev_inuse.isChecked(): flags |= PREV_INUSE if self.f_is_mmaped.isChecked(): flags |= IS_MMAPPED if self.f_non_main_arena.isChecked(): flags |= NON_MAIN_ARENA try: size = eval(self.t_size.text()) size |= flags fd = eval(self.t_fd.text()) bk = eval(self.t_bk.text()) fd_nextsize = eval(self.t_fd_nextsize.text()) bk_nextsize = eval(self.t_bk_nextsize.text()) self.chunk.size = size self.chunk.fd = fd self.chunk.bk = bk self.chunk.fd_nextsize = fd_nextsize self.chunk.bk_nextsize = bk_nextsize idaapi.patch_bytes(self.addr, self.chunk.data) idaapi.info("Chunk saved") self.done(1) except Exception as e: idaapi.warning("ERROR: " + str(e))
def patch(self, fill_char=b'\x00', define=True): """ Patches the original encoded string with the decoded string. :param str fill_char: Character to use to fill left over space if decoded data is shorter than its encoded data. Set to None leaving the original data. :param bool define: Whether to define the string after patching. """ if not self.decoded_data or self.string_location is None: return decoded_data = self.decoded_data if fill_char: decoded_data += fill_char * (len(self.encoded_data) - len(decoded_data)) try: idaapi.patch_bytes(self.start_ea, decoded_data) if define: self.define() except TypeError: logger.debug( "String type for decoded string from location 0x{:08x}.".format( self.start_ea ) ) finally: return self
def add_stub_func(va, sc, nm): idaapi.patch_bytes(va, binascii.unhexlify(sc)) idc.create_insn(va) idc.add_func(va) mykutils.makename_safe(va, self._stubname(nm)) cmt = ('%s implementation generated by FLARE Code Grafter' % (nm)) idc.set_cmt(va, cmt, 1)
def __create_load_data_segment(data, seg_addr, seg_name): # This function creates a data segment located in a pre-specified address # and fills this new segment with data seglen = len(data) if seglen % 0x1000 != 0: seglen = seglen + (0x1000 - (seglen % 0x1000)) if not idc.AddSeg(seg_addr, seg_addr + seglen, 0, 1, 0, idaapi.scPub): logger.error('failed to add segment: 0x%x', seg_addr) return False if not idc.set_segm_name(seg_addr, seg_name): logger.warning('failed to rename segment: %s', seg_name) return False if not idc.set_segm_class(seg_addr, 'DATA'): logger.warning('failed to set segment class DATA: %s', seg_name) return False if not idc.set_segm_attr(seg_addr, idc.SEGATTR_ALIGN, idc.saRelPara): logger.warning('failed to align segment: %s', seg_name) return False if data: idaapi.patch_bytes(seg_addr, data) return True
def hook(self, hook_addr=0): """ Args: hook_addr(int): address for inline hook code, 0 indicates bpt hook. Returns: memory size in bytes used for inline hook. """ self.hook_addr = hook_addr self.func_addr = idc.get_name_ea_simple(self.name) if self.func_addr == 0: return 0 print("Hooking %s at 0x%x" % (self.name, self.func_addr)) if self.hook_addr == 0: idc.add_bpt(self.func_addr) idc.set_bpt_cond(self.func_addr, self.bpt_cond_hook_code) return 0 else: # assemble jmp code jmp_code = "jmp 0x%x" % self.hook_addr jmp_buf, _ = assemble(jmp_code, self.func_addr) # read function prologue according to jmp code length # NOTE: instructions like 'call $+5' in prologue will # cause problems. insn = idaapi.insn_t() move_length = 0 while move_length < len(jmp_buf): idaapi.decode_insn(insn, self.func_addr + move_length) move_length += insn.size prologue = idaapi.get_bytes(self.func_addr, move_length) # write jmp code idaapi.patch_bytes(self.func_addr, jmp_buf) # assmble hook code hook_buf, _ = assemble(self.inline_hook_code, self.hook_addr) hook_buf += prologue jmp_back_code = 'jmp 0x%x' % (self.func_addr + move_length) jmp_back_buf, _ = assemble(jmp_back_code, self.hook_addr + len(hook_buf)) hook_buf += jmp_back_buf # wirte hook code idaapi.patch_bytes(self.hook_addr, hook_buf) return len(hook_buf)
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 write_memory(start, data, destructive=False): if destructive: idaapi.put_bytes(start, data) else: idaapi.patch_bytes(start, data)
def activate(self, ctx): if self.action in ACTION_CONVERT: # convert t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t( ), idaapi.get_current_viewer() if idaapi.read_selection(view, t0, t1): start, end = t0.place(view).toea(), t1.place(view).toea() size = end - start elif idc.get_item_size(idc.get_screen_ea()) > 1: start = idc.get_screen_ea() size = idc.get_item_size(start) end = start + size else: return False data = idc.get_bytes(start, size) if isinstance(data, str): # python2 compatibility data = bytearray(data) name = idc.get_name(start, idc.GN_VISIBLE) if not name: name = "data" if data: print("\n[+] Dump 0x%X - 0x%X (%u bytes) :" % (start, end, size)) if self.action == ACTION_CONVERT[0]: # escaped string print('"%s"' % "".join("\\x%02X" % b for b in data)) elif self.action == ACTION_CONVERT[1]: # hex string print("".join("%02X" % b for b in data)) elif self.action == ACTION_CONVERT[2]: # C array output = "unsigned char %s[%d] = {" % (name, size) for i in range(size): if i % 16 == 0: output += "\n " output += "0x%02X, " % data[i] output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[3]: # C array word data += b"\x00" array_size = (size + 1) // 2 output = "unsigned short %s[%d] = {" % (name, array_size) for i in range(0, size, 2): if i % 16 == 0: output += "\n " output += "0x%04X, " % u16(data[i:i + 2]) output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[4]: # C array dword data += b"\x00" * 3 array_size = (size + 3) // 4 output = "unsigned int %s[%d] = {" % (name, array_size) for i in range(0, size, 4): if i % 32 == 0: output += "\n " output += "0x%08X, " % u32(data[i:i + 4]) output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[5]: # C array qword data += b"\x00" * 7 array_size = (size + 7) // 8 output = "unsigned long %s[%d] = {" % (name, array_size) for i in range(0, size, 8): if i % 32 == 0: output += "\n " output += "%#018X, " % u64(data[i:i + 8]) output = output[:-2] + "\n};" print(output.replace("0X", "0x")) elif self.action == ACTION_CONVERT[6]: # python list print("[%s]" % ", ".join("0x%02X" % b for b in data)) elif self.action == ACTION_CONVERT[7]: # python list word data += b"\x00" print("[%s]" % ", ".join("0x%04X" % u16(data[i:i + 2]) for i in range(0, size, 2))) elif self.action == ACTION_CONVERT[8]: # python list dword data += b"\x00" * 3 print("[%s]" % ", ".join("0x%08X" % u32(data[i:i + 4]) for i in range(0, size, 4))) elif self.action == ACTION_CONVERT[9]: # python list qword data += b"\x00" * 7 print("[%s]" % ", ".join( "%#018X" % u64(data[i:i + 8]) for i in range(0, size, 8)).replace("0X", "0x")) elif self.action == ACTION_XORDATA: t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t( ), idaapi.get_current_viewer() if idaapi.read_selection(view, t0, t1): start, end = t0.place(view).toea(), t1.place(view).toea() else: if idc.get_item_size(idc.get_screen_ea()) > 1: start = idc.get_screen_ea() end = start + idc.get_item_size(start) else: return False data = idc.get_bytes(start, end - start) if isinstance(data, str): # python2 compatibility data = bytearray(data) x = idaapi.ask_long(0, "Xor with...") if x: x &= 0xFF print("\n[+] Xor 0x%X - 0x%X (%u bytes) with 0x%02X:" % (start, end, end - start, x)) print(repr("".join(chr(b ^ x) for b in data))) elif self.action == ACTION_FILLNOP: t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t( ), idaapi.get_current_viewer() if idaapi.read_selection(view, t0, t1): start, end = t0.place(view).toea(), t1.place(view).toea() idaapi.patch_bytes(start, b"\x90" * (end - start)) print("\n[+] Fill 0x%X - 0x%X (%u bytes) with NOPs" % (start, end, end - start)) elif self.action == ACTION_SCANVUL: print("\n[+] Finding Format String Vulnerability...") found = [] for addr in idautils.Functions(): name = idc.get_func_name(addr) if "printf" in name and "v" not in name and idc.get_segm_name( addr) in (".text", ".plt", ".idata"): xrefs = idautils.CodeRefsTo(addr, False) for xref in xrefs: vul = self.check_fmt_function(name, xref) if vul: found.append(vul) if found: print("[!] Done! %d possible vulnerabilities found." % len(found)) ch = VulnChoose("Vulnerability", found, None, False) ch.Show() else: print("[-] No format string vulnerabilities found.") else: return 0 return 1
def activate(self, ctx): if self.action in ACTION_MENU_CONVERT: sel, start, end = lazy_read_selection() if not sel: idc.msg("[LazyIDA] Nothing to convert.") return False size = end - start data = idc.get_bytes(start, size) if isinstance(data, str): # python2 compatibility data = bytearray(data) assert size == len(data) name = idc.get_name(start, idc.GN_VISIBLE) if not name: name = "data" if data: output = None plg_print("Dump from 0x%X to 0x%X (%u bytes):" % (start, end - 1, size)) if self.action == ACTION_MENU_CONVERT[0]: # escaped string output = '"%s"' % "".join("\\x%02X" % b for b in data) elif self.action == ACTION_MENU_CONVERT[1]: # hex string, space output = " ".join("%02X" % b for b in data) elif self.action == ACTION_MENU_CONVERT[2]: # C array output = "unsigned char %s[%d] = {" % (name, size) for i in range(size): if i % 16 == 0: output += "\n " output += "0x%02X, " % data[i] output = output[:-2] + "\n};" elif self.action == ACTION_MENU_CONVERT[3]: # C array word data += b"\x00" array_size = (size + 1) // 2 output = "unsigned short %s[%d] = {" % (name, array_size) for i in range(0, size, 2): if i % 16 == 0: output += "\n " output += "0x%04X, " % u16(data[i:i+2]) output = output[:-2] + "\n};" elif self.action == ACTION_MENU_CONVERT[4]: # C array dword data += b"\x00" * 3 array_size = (size + 3) // 4 output = "unsigned int %s[%d] = {" % (name, array_size) for i in range(0, size, 4): if i % 32 == 0: output += "\n " output += "0x%08X, " % u32(data[i:i+4]) output = output[:-2] + "\n};" elif self.action == ACTION_MENU_CONVERT[5]: # C array qword data += b"\x00" * 7 array_size = (size + 7) // 8 output = "unsigned long %s[%d] = {" % (name, array_size) for i in range(0, size, 8): if i % 32 == 0: output += "\n " output += "%#018X, " % u64(data[i:i+8]) output = output[:-2] + "\n};" output = output.replace("0X", "0x") elif self.action == ACTION_MENU_CONVERT[6]: # python list output = "[%s]" % ", ".join("0x%02X" % b for b in data) elif self.action == ACTION_MENU_CONVERT[7]: # python list word data += b"\x00" output = "[%s]" % ", ".join("0x%04X" % u16(data[i:i+2]) for i in range(0, size, 2)) elif self.action == ACTION_MENU_CONVERT[8]: # python list dword data += b"\x00" * 3 output = "[%s]" % ", ".join("0x%08X" % u32(data[i:i+4]) for i in range(0, size, 4)) elif self.action == ACTION_MENU_CONVERT[9]: # python list qword data += b"\x00" * 7 output = "[%s]" % ", ".join("%#018X" % u64(data[i:i+8]) for i in range(0, size, 8)).replace("0X", "0x") elif self.action == ACTION_MENU_CONVERT[10]: # MASM byte array header = "%s db " % name output = header for i in range(size): if i and i % 16 == 0: output += "\n" output += " " * len(header) output += "0%02Xh, " % data[i] output = output[:-2] elif self.action == ACTION_MENU_CONVERT[11]: # GNU ASM byte array header = "%s: .byte " % name output = header for i in range(size): if i and i % 16 == 0: output += "\n" output += " " * len(header) output += "0x%02X, " % data[i] output = output[:-2] if output: print(output) copy_to_clip(output) output = None elif self.action == ACTION_MENU_COPY_DATA: # added by merc, modified by HTC sel, start, end = lazy_read_selection() if not sel: return 0 data = idaapi.get_bytes(start, end - start) if isinstance(data, str): data = bytearray(data) output = "".join("%02X" % b for b in data) copy_to_clip(output) plg_print("Hex string '%s' copied" % output) elif self.action == ACTION_MENU_DUMP_DATA: # add by HTC sel, start, end = lazy_read_selection() if not sel: return 0 size = end - start data = idaapi.get_bytes(start, size) assert len(data) == size if data and len(data) == size: dump_data_to_file("Dump_At_%X_Size_%d.dump" % (start, size), data) else: plg_print("0x%X: unable to get %d bytes" % (start, size)) elif self.action == ACTION_MENU_XOR_DATA: sel, start, end = lazy_read_selection() if not sel: return 0 size = end - start key = idaapi.ask_str("AA BB CC DD", 0, "Xor with hex values (or a string begin and end with\" or ')...") if not key: return 0 bytes_key = bytearray() if is_str(key): bytes_key = str_to_bytes(key) else: bytes_key = hex_to_bytes(key) if not bytes_key: return 0 data = idc.get_bytes(start, end - start) if isinstance(data, str): # python2 compatibility data = bytearray(data) output = xor_data(data, bytes_key) if not output: plg_print("Sorry, error occurred. My bug :( Please report.") return 0 assert size == len(output) plg_print("Xor result from 0x%X to 0x%X (%d bytes) with %s:" % (start, end, end - start, key)) process_data_result(start, output) elif self.action == ACTION_MENU_FILL_NOP: sel, start, end = lazy_read_selection() if not sel: return 0 idaapi.patch_bytes(start, b"\x90" * (end - start)) idc.create_insn(start) plg_print("Fill 0x%X to 0x%X (%u bytes) with NOPs" % (start, end, end - start)) elif self.action == ACTION_MENU_B64STD: base64_decode(True) elif self.action == ACTION_MENU_B64URL: base64_decode(False) elif self.action == ACTION_MENU_SCAN_VUL: plg_print("Finding Format String Vulnerability...") found = [] for addr in idautils.Functions(): name = idc.get_func_name(addr) if "printf" in name and "v" not in name and idc.get_segm_name(addr) in (".text", ".plt", ".idata"): xrefs = idautils.CodeRefsTo(addr, False) for xref in xrefs: vul = self.check_fmt_function(name, xref) if vul: found.append(vul) if found: plg_print("Done! %d possible vulnerabilities found." % len(found)) ch = VulnChoose("Vulnerability", found, None, False) ch.Show() else: plg_print("No format string vulnerabilities found.") else: return 0 return 1
def process_data_result(start, data): # 16 bytes on a line # one byte take 4 char: 2 hex char, a space and a char if isalnum # one line take 3 char addtion: two space and \n, and ea hex address BYTES_PER_LINE = 16 MAX_BYTES_HEX_DUMP = BYTES_PER_LINE * 64 # 64 lines printLen = len(data) if printLen > MAX_BYTES_HEX_DUMP: printLen = MAX_BYTES_HEX_DUMP plg_print("Only hexdump first %d bytes" % MAX_BYTES_HEX_DUMP) nLines = printLen // BYTES_PER_LINE # Number of lines nOdd = printLen % BYTES_PER_LINE # Number of bytes at last line isStr = True sHex = str() for i in range(printLen): if isStr and chr(data[i]) not in string.printable: isStr = False if i % BYTES_PER_LINE == 0: sHex += "%s: " % idaapi.ea2str(start + i) sHex += "%02X " % data[i] if (i % BYTES_PER_LINE == BYTES_PER_LINE - 1) or (i == printLen - 1): # add the end of data or end of a line if nLines: lineIdx = i // BYTES_PER_LINE # current line number low = lineIdx * BYTES_PER_LINE high = i + 1 else: low = 0 high = printLen sHex += " " # Padding last line if i == printLen - 1 and nLines and nOdd: sHex += " " * (BYTES_PER_LINE - nOdd) * 3 for j in range(low, high): ch = chr(data[j]) sHex += ch if ch.isalnum() else "." sHex += "\n" # Print out the hexdump string print(sHex) if isStr: txt = str(data) print("String result: '%s'" % txt) idaapi.set_cmt(start, txt, 1) if idaapi.ask_yn(idaapi.ASKBTN_NO, "Do you want to patch selected range with result data ?") == idaapi.ASKBTN_YES: idaapi.patch_bytes(start, bytes(data)) if idaapi.ask_yn(idaapi.ASKBTN_YES, "Do you want to dump result data to file ?") == idaapi.ASKBTN_YES: dump_data_to_file("Dump_At_0x%X_Size_%d.dump" % (start, len(data)), data)
def activate(self, ctx): if self.action in ACTION_CONVERT: sel, start, end = lazy_read_selection() if not sel: idc.msg("[LazyIDA] Nothing to convert.") return False size = end - start data = idc.get_bytes(start, size) if isinstance(data, str): # python2 compatibility data = bytearray(data) assert size == len(data) name = idc.get_name(start, idc.GN_VISIBLE) if not name: name = "data" if data: print("\n[+] Dump 0x%X - 0x%X (%u bytes) :" % (start, end, size)) if self.action == ACTION_CONVERT[0]: # escaped string print('"%s"' % "".join("\\x%02X" % b for b in data)) elif self.action == ACTION_CONVERT[1]: # hex string print("".join("%02X" % b for b in data)) elif self.action == ACTION_CONVERT[2]: # C array output = "unsigned char %s[%d] = {" % (name, size) for i in range(size): if i % 16 == 0: output += "\n " output += "0x%02X, " % data[i] output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[3]: # C array word data += b"\x00" array_size = (size + 1) // 2 output = "unsigned short %s[%d] = {" % (name, array_size) for i in range(0, size, 2): if i % 16 == 0: output += "\n " output += "0x%04X, " % u16(data[i:i+2]) output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[4]: # C array dword data += b"\x00" * 3 array_size = (size + 3) // 4 output = "unsigned int %s[%d] = {" % (name, array_size) for i in range(0, size, 4): if i % 32 == 0: output += "\n " output += "0x%08X, " % u32(data[i:i+4]) output = output[:-2] + "\n};" print(output) elif self.action == ACTION_CONVERT[5]: # C array qword data += b"\x00" * 7 array_size = (size + 7) // 8 output = "unsigned long %s[%d] = {" % (name, array_size) for i in range(0, size, 8): if i % 32 == 0: output += "\n " output += "%#018X, " % u64(data[i:i+8]) output = output[:-2] + "\n};" print(output.replace("0X", "0x")) elif self.action == ACTION_CONVERT[6]: # python list print("[%s]" % ", ".join("0x%02X" % b for b in data)) elif self.action == ACTION_CONVERT[7]: # python list word data += b"\x00" print("[%s]" % ", ".join("0x%04X" % u16(data[i:i+2]) for i in range(0, size, 2))) elif self.action == ACTION_CONVERT[8]: # python list dword data += b"\x00" * 3 print("[%s]" % ", ".join("0x%08X" % u32(data[i:i+4]) for i in range(0, size, 4))) elif self.action == ACTION_CONVERT[9]: # python list qword data += b"\x00" * 7 print("[%s]" % ", ".join("%#018X" % u64(data[i:i+8]) for i in range(0, size, 8)).replace("0X", "0x")) elif self.action == ACTION_COPYDATA: # added by merc, modfiy by HTC sel, start, end = lazy_read_selection() if not sel: return 0 data = idaapi.get_bytes(start, end - start) data = data.encode('hex') copy_to_clip(data) print("[LazyIDA] copied hex string '%s'" % data) elif self.action == ACTION_XORDATA: sel, start, end = lazy_read_selection() if not sel: return 0 data = idc.get_bytes(start, end - start) if isinstance(data, str): # python2 compatibility data = bytearray(data) x = idaapi.ask_long(0, "Xor with...") if x: x &= 0xFF print("\n[+] Xor 0x%X - 0x%X (%u bytes) with 0x%02X:" % (start, end, end - start, x)) print(repr("".join(chr(b ^ x) for b in data))) elif self.action == ACTION_FILLNOP: sel, start, end = lazy_read_selection() if not sel: return 0 idaapi.patch_bytes(start, b"\x90" * (end - start)) print("\n[+] Fill 0x%X - 0x%X (%u bytes) with NOPs" % (start, end, end - start)) elif self.action == ACTION_SCANVUL: print("\n[+] Finding Format String Vulnerability...") found = [] for addr in idautils.Functions(): name = idc.get_func_name(addr) if "printf" in name and "v" not in name and idc.get_segm_name(addr) in (".text", ".plt", ".idata"): xrefs = idautils.CodeRefsTo(addr, False) for xref in xrefs: vul = self.check_fmt_function(name, xref) if vul: found.append(vul) if found: print("[!] Done! %d possible vulnerabilities found." % len(found)) ch = VulnChoose("Vulnerability", found, None, False) ch.Show() else: print("[-] No format string vulnerabilities found.") elif self.action == ACTION_COPYNAME: copy_highlight_name() elif self.action == ACTION_PASTENAME: paste_highlight_name() else: return 0 return 1