diff options
Diffstat (limited to '')
-rwxr-xr-x | src/delf.py | 191 |
1 files changed, 68 insertions, 123 deletions
diff --git a/src/delf.py b/src/delf.py index c988098..f4b114b 100755 --- a/src/delf.py +++ b/src/delf.py @@ -19,10 +19,10 @@ # MA 02110-1301, USA.*/ # *****************************************************************************/ import argparse -import code import os import subprocess import sys +import typing from capstone import CS_ARCH_X86, CS_MODE_64, Cs @@ -30,6 +30,8 @@ from capstone import CS_ARCH_X86, CS_MODE_64, Cs class ELF_TYPE_SIZES: + """Const class that holds ELF type sizes in bytes""" + ELF32_HALF = 2 ELF64_HALF = 2 ELF32_WORD = 4 @@ -53,7 +55,7 @@ def SigHandler_SIGINT(signum, frame): sys.exit(0) -class CLIArgParser(object): +class CLIArgParser: def __init__(self): parser = argparse.ArgumentParser() parser.add_argument("--dbg", action="store_true", help="debug", default=False) @@ -194,6 +196,12 @@ class CLIArgParser(object): help="dump .got.plt section", default=False, ) + parser.add_argument( + "--nocolor", + action="store_true", + help="dont use color", + default=False, + ) self.args = parser.parse_args() if self.args.obj is None: raise Exception( @@ -273,16 +281,29 @@ class ELF_RELA: self.r_addend = r_addend -def ffs(offset, header_list, numbered, *args): +def ffs( + offset, + header_list, + numbered, + nocolor, + *args, +): # cn = Colors.green - ch = Colors.cyan - cd = Colors.blue - cb = Colors.BOLD - ci = Colors.red - ce = Colors.ENDC + if nocolor: + ch = "" + cd = "" + cb = "" + ci = "" + ce = "" + else: + ch = Colors.cyan + cd = Colors.blue + cb = Colors.BOLD + ci = Colors.red + ce = Colors.ENDC max_column_width = [] - lines = [] - numbers_f = [] + lines: typing.List[str] = [] + numbers_f: typing.List[int] = [] dummy = [] if numbered: @@ -1210,8 +1231,10 @@ class Symbol_Table_Entry64: self.st_type = st_type -class ELF(object): - def __init__(self, so): +class ELF: + """The ELF class that holds everything about the ELF file.""" + + def __init__(self, so, argparser): self.so = so self.so.seek(0, 0) self.elfhdr = ELFHDR(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) @@ -1240,6 +1263,7 @@ class ELF(object): self.plt_got_ents = [] self.got_ents = [] self.got_plt_ents = [] + self.argparser = argparser def init(self, size): self.size = size @@ -1420,7 +1444,7 @@ class ELF(object): header = ["d_tag", "d_un"] tag_list = [get_ph_dynamic_ent_tag_type(ph.d_tag) for ph in self.ph_dyn_ent] un_list = [ph.d_un for ph in self.ph_dyn_ent] - lines = ffs(2, header, True, tag_list, un_list) + lines = ffs(2, header, True, self.argparser.args.nocolor, tag_list, un_list) for line in lines: print(line) @@ -1473,7 +1497,7 @@ class ELF(object): self.dlpath = repr(obj) count = int() if dump: - strrep = [] + strrep: typing.List[str] = [] for byte in obj: if count % 16 == 0: for ch in strrep: @@ -1529,6 +1553,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocoor, name_list, size_list, value_list, @@ -1551,6 +1576,7 @@ class ELF(object): 2, header, True, + self.argparser.args.noclor, name_list, size_list, value_list, @@ -1609,6 +1635,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, mag_list, class_list, data_list, @@ -1661,6 +1688,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, type_list, flags_list, offset_list, @@ -1706,6 +1734,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, name_list, type_list, flag_list, @@ -1765,6 +1794,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, idx_list, name_list, value_list, @@ -1811,6 +1841,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, idx_list, name_list, value_list, @@ -1834,6 +1865,7 @@ class ELF(object): 2, header, True, + self.argparser.args.nocolor, tag_string_list, tag_list, value_list, @@ -1847,7 +1879,15 @@ class ELF(object): r_offset_list = [entry["r_offset"] for entry in to_dump] r_info_list = [entry["r_info"] for entry in to_dump] addend_list = [entry["r_addend"] for entry in to_dump] - lines = ffs(2, header, True, r_offset_list, r_info_list, addend_list) + lines = ffs( + 2, + header, + True, + self.argparser.args.nocolor, + r_offset_list, + r_info_list, + addend_list, + ) for line in lines: print(line) @@ -1855,7 +1895,9 @@ class ELF(object): header = ["r_offset", "r_info"] r_offset_list = [entry["r_offset"] for entry in to_dump] r_info_list = [entry["r_info"] for entry in to_dump] - lines = ffs(2, header, True, r_offset_list, r_info_list) + lines = ffs( + 2, header, True, self.argparser.args.nocolor, r_offset_list, r_info_list + ) for line in lines: print(line) @@ -2037,14 +2079,14 @@ class ELF(object): def dump_got(self): header = ["value"] value_list = [entry for entry in self.got_ents] - lines = ffs(2, header, True, value_list) + lines = ffs(2, header, True, self.argparser.args.nocolor, value_list) for line in lines: print(line) def dump_got_plt(self): header = ["value"] value_list = [entry for entry in self.got_plt_ents] - lines = ffs(2, header, True, value_list) + lines = ffs(2, header, True, self.argparser.args.nocolor, value_list) for line in lines: print(line) @@ -2074,109 +2116,11 @@ def ch_exe_to_so(path): so.close -def elf_init(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - - -def elf_get_func_names(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_symbol_string(ELF_ST_TYPE.STT_FUNC, False) - - -def elf_get_text_section(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_section(".text", False) - - -def elf_get_section(name): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_section(name, False) - - -def elf_get_rodata_section(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_section(".rodata", False) - - -# obj here means variables or what the C standard means by objects - - -def elf_get_obj_names(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_symbol_string(ELF_ST_TYPE.STT_OBJECT, False) - - -# obj here means variables or what the C standard means by objects - - -def elf_get_obj_sizes(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_obj_size(ELF_ST_TYPE.STT_OBJECT, False) - - -def elf_get_func_code(): - so = openSO_r(sys.argv[1]) - elf = ELF(so) - elf.init(64) - return elf.dump_funcs(False) - - -def elf_get_func_code_byname(): - so = openSO_r(sys.argv[1]) - arg = openSO_r(sys.argv[2]) - elf = ELF(so) - elf.init(64) - counter = 0 - # hit = False - for name in elf.dump_symbol_string(ELF_ST_TYPE.STT_FUNC, False): - if name == arg: - code = elf.dump_funcs(False)[counter] - # hit = True - counter += 1 - return code - - -class Call_Rewriter(object): - # def __init__(self, obj_code, arch, mode): - def __init__(self, obj_code): - self.obj_code = bytes(obj_code) - self.md = Cs(CS_ARCH_X86, CS_MODE_64) - # self.md = Cs(arch, mode) - - def dumpall(self): - for i in self.md.disasm(self.obj_code, 0x1): - print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str)) - - def run(self): - for i in self.md.disasm(self.obj_code, 0x1): - if i.mnemonic == "call": - print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str)) - print(i.bytes) - - -class Global_Rewriter(object): - def __init__(self): - pass - - -class Rewriter(object): - def __init__(self, path, new_name): +class Rewriter: + def __init__(self, path, new_name, argparser): so = openSO_r(path) - self.elf = ELF(so) + self.argparser = argparser + self.elf = ELF(so, argparser) self.elf.init(64) # shutil.copyfile(path, "/tmp/exe") self.magic_section_number = int() @@ -2223,9 +2167,10 @@ class Rewriter(object): def main() -> None: + """The entryp point.""" argparser = CLIArgParser() so = openSO_r(argparser.args.obj) - elf = ELF(so) + elf = ELF(so, argparser) elf.init(64) if argparser.args.header: elf.dump_header() @@ -2253,7 +2198,7 @@ def main() -> None: elif argparser.args.section: elf.dump_section(argparser.args.section, True) elif argparser.args.test2: - rewriter = Rewriter(argparser.args.obj, "new_exe") + rewriter = Rewriter(argparser.args.obj, "new_exe", argparser) new_text = bytes() rewriter.fix_section_offsets(".text", 1000, new_text) elif argparser.args.dumpfunc: @@ -2296,7 +2241,7 @@ def main() -> None: index = argparser.args.disassp # section not executable message if byte2int(elf.phdr[index].p_flags) & 0x1 != 1: - print("program header section is not " "executable but since you asked...") + print("program header section is not executable but since you asked...") header_offset = elf.phdr[index].p_offset header_size = elf.phdr[index].p_filesz elf.so.seek(byte2int(header_offset)) |