def load_dyn_sym(self): arch = self.elf.get_machine_arch() if arch == "ARM" or arch == "MIPS": for (rel, symtab) in self.__iter_reloc(): self.__resolve_symtab(rel, symtab, arch) return # x86/x64 # TODO: .plt can be renamed ? plt = self.elf.get_section_by_name(b".plt") if plt is None: warning(".plt section not found") return # TODO: .got.plt can be renamed or may be removed ? got_plt = self.elf.get_section_by_name(b".got.plt") addr_size = 8 if arch == "x64" else 4 if got_plt is None: warning(".got.plt section not found") return for (rel, symtab) in self.__iter_reloc(): self.__x86_resolve_reloc(rel, symtab, plt, got_plt, addr_size)
def load_dyn_sym(self): arch = self.elf.get_machine_arch() if arch == "ARM" or arch == "MIPS": for (rel, symtab) in self.__iter_reloc(): self.__resolve_symtab(rel, symtab) return # x86/x64 # TODO: .plt can be renamed ? plt = self.elf.get_section_by_name(b".plt") if plt is None: warning(".plt section not found") return # TODO: .got.plt can be renamed or may be removed ? got_plt = self.elf.get_section_by_name(b".got.plt") addr_size = 8 if arch == "x64" else 4 if got_plt is None: warning(".got.plt section not found") return for (rel, symtab) in self.__iter_reloc(): self.__x86_resolve_reloc(rel, symtab, plt, got_plt, addr_size)
def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size): # Save all got offsets with the corresponding symbol got_off = {} for r in rel.iter_relocations(): sym = symtab.get_symbol(r.entry.r_info_sym) name = sym.name.decode() ad = r.entry.r_offset if name and ad: ty = self.sym_type_lookup.get(sym.entry.st_info.type, MEM_UNK) got_off[ad] = [name + "@plt", ty] data = got_plt.data() unpack_str = "<" if self.elf.little_endian else ">" unpack_str += str(int(len(data) / addr_size)) unpack_str += "Q" if addr_size == 8 else "I" got_values = struct.unpack(unpack_str, data) plt_data = plt.data() wrong_jump_opcode = False off = got_plt.header.sh_addr # Read the .got.plt and for each address in the plt, substract 6 # to go at the begining of the plt entry. opcode_jmp = [b"\xff\x25", b"\xff\xa3"] for jump_in_plt in got_values: if off in got_off: plt_start = jump_in_plt - 6 plt_off = plt_start - plt.header.sh_addr # Check "jmp *(ADDR)" opcode. if plt_data[plt_off:plt_off+2] not in opcode_jmp: wrong_jump_opcode = True continue name, ty = got_off[off] if name in self.classbinary.symbols: continue self.classbinary.imports[plt_start] = True self.classbinary.reverse_symbols[plt_start] = name self.classbinary.symbols[name] = plt_start self.mem.add(plt_start, 1, ty) off += addr_size if wrong_jump_opcode: warning("I'm expecting to see a jmp *(ADDR) on each plt entry") warning("opcode \\xff\\x25 was not found, please report")
def load(self, filename): gc.disable() self.__init_vars() dirname = os.path.dirname(filename) self.path = dirname + "/" if dirname != "" else "" self.path += "." + os.path.basename(filename) + ".db" if os.path.exists(self.path): info("open database %s" % self.path) fd = open(self.path, "rb") data = self.__check_old_json_db(fd) if data is None: data = fd.read() if data.startswith(b"ZLIB"): data = zlib.decompress(data[4:]) data = msgpack.unpackb(data, encoding="utf-8") fd.close() self.__load_meta(data) self.__load_memory(data) self.__load_symbols(data) self.__load_jmptables(data) self.__load_comments(data) self.__load_functions(data) self.__load_history(data) self.__load_xrefs(data) self.__load_imports(data) if self.version <= 1.5: self.__load_labels(data) if self.version != VERSION: warning( "the database version is old, some information may be missing" ) self.loaded = True gc.enable()
def init_entry_addr(ctx): if ctx.calls_in_section is not None: s = ctx.dis.binary.get_section_by_name(ctx.calls_in_section) if s is None: error("section %s not found" % ctx.calls_in_section) if ctx.interactive: return False die() entry_addr = s.start elif ctx.entry == "EP": entry_addr = ctx.dis.binary.get_entry_point() else: try: entry_addr = ctx.dis.get_addr_from_string(ctx.entry, ctx.raw_type != None) # An exception is raised if the symbol was not found if ctx.entry is None: ctx.entry = "main" except ExcSymNotFound as e: error("symbol %s not found" % e.symname) if ctx.interactive: return False error("You can see all symbols with -s (if resolution is done).") error("Note: --dump need the option -x.") die() s = ctx.dis.binary.get_section(entry_addr) if s is None: error("the address 0x%x was not found" % entry_addr) if ctx.interactive: return False die() if not s.is_exec: warning("the address 0x%x is not in an executable section" % entry_addr) ctx.entry_addr = entry_addr return True
def init_entry_addr(ctx): if ctx.calls_in_section is not None: try: entry_addr = ctx.dis.binary.section_start(ctx.calls_in_section) except ExcSectionNotFound as e: error("section %s not found" % e.section) if ctx.interactive: return False die() elif ctx.entry == "EP": entry_addr = ctx.dis.binary.get_entry_point() else: try: entry_addr = ctx.dis.get_addr_from_string(ctx.entry, ctx.raw_type != None) # An exception is raised if the symbol was not found if ctx.entry is None: ctx.entry = "main" except ExcSymNotFound as e: error("symbol %s not found" % e.symname) if ctx.interactive: return False error("You can see all symbols with -s (if resolution is done).") error("Note: --dump need the option -x.") die() try: ctx.dis.check_addr(ctx, entry_addr) except ExcNotExec as e: warning("the address 0x%x is not in an executable section" % e.addr) except ExcNotAddr as e: error("the address 0x%x cannot be found" % e.addr) if ctx.interactive: return False die() ctx.entry_addr = entry_addr return True
def load(self, filename): gc.disable() self.__init_vars() dirname = os.path.dirname(filename) self.path = dirname + "/" if dirname != "" else "" self.path += "." + os.path.basename(filename) + ".db" if os.path.exists(self.path): info("open database %s" % self.path) fd = open(self.path, "rb") data = self.__check_old_json_db(fd) if data is None: data = fd.read() if data.startswith(b"ZLIB"): data = zlib.decompress(data[4:]) data = msgpack.unpackb(data, encoding="utf-8") fd.close() self.__load_meta(data) self.__load_memory(data) self.__load_symbols(data) self.__load_jmptables(data) self.__load_comments(data) self.__load_functions(data) self.__load_history(data) self.__load_xrefs(data) self.__load_imports(data) if self.version <= 1.5: self.__load_labels(data) if self.version != VERSION: warning("the database version is old, some information may be missing") self.loaded = True gc.enable()
def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size): # Save all got offsets with the corresponding symbol got_off = {} for r in rel.iter_relocations(): sym = symtab.get_symbol(r.entry.r_info_sym) got_off[r.entry.r_offset] = sym.name.decode() + "@plt" data = got_plt.data() unpack_str = "<" if self.elf.little_endian else ">" unpack_str += str(int(len(data) / addr_size)) unpack_str += "Q" if addr_size == 8 else "I" got_values = struct.unpack(unpack_str, data) plt_data = plt.data() wrong_jump_opcode = False off = got_plt.header.sh_addr # Read the .got.plt and for each address in the plt, substract 6 # to go at the begining of the plt entry. for jump_in_plt in got_values: if off in got_off: plt_start = jump_in_plt - 6 plt_off = plt_start - plt.header.sh_addr # Check "jmp *(ADDR)" opcode. if plt_data[plt_off:plt_off + 2] != b"\xff\x25": wrong_jump_opcode = True continue name = got_off[off] self.classbinary.reverse_symbols[plt_start] = name self.classbinary.symbols[name] = plt_start off += addr_size if wrong_jump_opcode: warning("I'm expecting to see a jmp *(ADDR) on each plt entry") warning("opcode \\xff\\x25 was not found, please report")
def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size): # Save all got offsets with the corresponding symbol got_off = {} for r in rel.iter_relocations(): sym = symtab.get_symbol(r.entry.r_info_sym) got_off[r.entry.r_offset] = sym.name.decode() + "@plt" data = got_plt.data() unpack_str = "<" if self.elf.little_endian else ">" unpack_str += str(int(len(data) / addr_size)) unpack_str += "Q" if addr_size == 8 else "I" got_values = struct.unpack(unpack_str, data) plt_data = plt.data() wrong_jump_opcode = False off = got_plt.header.sh_addr # Read the .got.plt and for each address in the plt, substract 6 # to go at the begining of the plt entry. for jump_in_plt in got_values: if off in got_off: plt_start = jump_in_plt - 6 plt_off = plt_start - plt.header.sh_addr # Check "jmp *(ADDR)" opcode. if plt_data[plt_off:plt_off+2] != b"\xff\x25": wrong_jump_opcode = True continue name = got_off[off] self.classbinary.reverse_symbols[plt_start] = name self.classbinary.symbols[name] = plt_start off += addr_size if wrong_jump_opcode: warning("I'm expecting to see a jmp *(ADDR) on each plt entry") warning("opcode \\xff\\x25 was not found, please report")
def __init__(self): self.__init_vars() if msgpack.version < (0, 4, 6): warning("your version of msgpack is less than 0.4.6")
import pefile from capstone.x86 import (X86_OP_INVALID, X86_OP_IMM, X86_OP_MEM, X86_REG_RIP, X86_REG_EIP) from ctypes import sizeof from lib.exceptions import ExcPEFail from lib.fileformat.pefile2 import PE2, SymbolEntry, PE_DT_FCN from lib.fileformat.binary import SectionAbs, SYM_UNK, SYM_FUNC from lib.utils import warning try: # This folder is not present in simonzack/pefile-py3k import ordlookup except: warning("you should use the most recent port of pefile") warning("https://github.com/mlaferrera/python3-pefile") pass class PE: def __init__(self, classbinary, filename): import capstone as CAPSTONE self.classbinary = classbinary self.pe = PE2(filename, fast_load=True) self.__data_sections = [] self.__data_sections_content = [] self.__exec_sections = [] self.arch_lookup = {
import pefile from capstone.x86 import (X86_OP_INVALID, X86_OP_IMM, X86_OP_MEM, X86_REG_RIP, X86_REG_EIP) from ctypes import sizeof from lib.exceptions import ExcPEFail from lib.fileformat.pefile2 import PE2, SymbolEntry, PE_DT_FCN from lib.fileformat.binary import SectionAbs from lib.utils import warning from lib.memory import MEM_FUNC, MEM_UNK try: # This folder is not present in simonzack/pefile-py3k import ordlookup except: warning("you should use the most recent port of pefile") warning("https://github.com/mlaferrera/python3-pefile") pass class PE: def __init__(self, mem, classbinary, filename): import capstone as CAPSTONE self.classbinary = classbinary self.mem = mem self.pe = PE2(filename, fast_load=True) self.__data_sections = [] self.__data_sections_content = [] self.__exec_sections = []