diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/delf.py | 2347 |
1 files changed, 2347 insertions, 0 deletions
diff --git a/src/delf.py b/src/delf.py new file mode 100755 index 0000000..c988098 --- /dev/null +++ b/src/delf.py @@ -0,0 +1,2347 @@ +#!/usr/bin/env python3 +# *****************************************************************************/ +# yet another elfdump in python +# Copyright (C) 2018 Farzad Sadeghi + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA.*/ +# *****************************************************************************/ +import argparse +import code +import os +import subprocess +import sys + +from capstone import CS_ARCH_X86, CS_MODE_64, Cs + +# from capstone.x86 import Cs + + +class ELF_TYPE_SIZES: + ELF32_HALF = 2 + ELF64_HALF = 2 + ELF32_WORD = 4 + ELF32_SWORD = 4 + ELF64_WORD = 4 + ELF64_SWORD = 4 + ELF32_XWORD = 8 + ELF32_SXWORD = 8 + ELF64_XWORD = 8 + ELF64_SXWORD = 8 + ELF32_ADDR = 4 + ELF64_ADDR = 8 + ELF32_OFF = 4 + ELF64_OFF = 8 + ELF32_SECTION = 2 + ELF64_SECTION = 2 + + +def SigHandler_SIGINT(signum, frame): + print() + sys.exit(0) + + +class CLIArgParser(object): + def __init__(self): + parser = argparse.ArgumentParser() + parser.add_argument("--dbg", action="store_true", help="debug", default=False) + parser.add_argument( + "--obj", + type=str, + help="path to the executbale, shared object " + "or object you want to load in bruiser", + ) + parser.add_argument( + "--header", action="store_true", help="dump headers", default=False + ) + parser.add_argument( + "--symboltable", + action="store_true", + help="dump symbol table", + default=False, + ) + parser.add_argument( + "--phdrs", + action="store_true", + help="dump program haeders", + default=False, + ) + parser.add_argument( + "--shdrs", + action="store_true", + help="dump section haeders", + default=False, + ) + parser.add_argument( + "--symbolindex", + action="store_true", + help="dump symbol index", + default=False, + ) + parser.add_argument( + "--stentries", + action="store_true", + help="dump section table entries", + default=False, + ) + parser.add_argument( + "--objcode", + action="store_true", + help="dump objects", + default=False, + ) + parser.add_argument( + "--test", action="store_true", help="test switch", default=False + ) + parser.add_argument( + "--test2", action="store_true", help="test switch 2", default=False + ) + parser.add_argument( + "--listdso", action="store_true", help="list DSOs", default=False + ) + parser.add_argument( + "--funcs", + action="store_true", + help="dump functions", + default=False, + ) + parser.add_argument( + "--objs", action="store_true", help="dump objects", default=False + ) + parser.add_argument( + "--dynsym", + action="store_true", + help="dump dynamic symbol table", + default=False, + ) + parser.add_argument( + "--dlpath", + action="store_true", + help="dump dynamic linker path", + default=False, + ) + parser.add_argument( + "--phdynent", + action="store_true", + help="dump ph PT_DYNAMIC entries", + default=False, + ) + parser.add_argument("--section", type=str, help="dump a section") + parser.add_argument( + "--dumpfunc", type=str, help="dump a functions machine code" + ) + parser.add_argument( + "--dumpfuncasm", type=str, help="dump a functions assembly code" + ) + parser.add_argument( + "--textasm", + action="store_true", + help="disassemble the text section", + default=False, + ) + parser.add_argument( + "--dynsecents", + action="store_true", + help="dynamic section entries", + default=False, + ) + parser.add_argument( + "--reladyn", + action="store_true", + help=".rela.dyn entries", + default=False, + ) + parser.add_argument( + "--relaplt", + action="store_true", + help=".rela.plt entries", + default=False, + ) + parser.add_argument( + "--rodata", action="store_true", help="dump .rodata", default=False + ) + parser.add_argument( + "--disass", + type=str, + help="disassembls a section by " "name in section headers", + ) + parser.add_argument( + "--disassp", + type=int, + help="disassembls a section " "by index in program headers", + ) + parser.add_argument( + "--got", + action="store_true", + help="dump .got section", + default=False, + ) + parser.add_argument( + "--gotplt", + action="store_true", + help="dump .got.plt section", + default=False, + ) + self.args = parser.parse_args() + if self.args.obj is None: + raise Exception( + "no object file provided. " "please specify an object with --obj." + ) + + +def byte2int(value, sign=False): + return int.from_bytes(value, byteorder="little", signed=sign) + + +def byte2hex(value): + return hex(int.from_bytes(value, byteorder="little", signed=False)) + + +def LEB128UnsignedDecode(bytelist): + result = 0 + shift = 0 + for byte in bytelist: + result |= (byte & 0x7F) << shift + if (byte & 0x80) == 0: + break + shift += 7 + return result + + +def LEB128SignedDecode(bytelist): + result = 0 + shift = 0 + for byte in bytelist: + result |= (byte & 0x7F) << shift + last_byte = byte + shift += 7 + if (byte & 0x80) == 0: + break + if last_byte & 0x40: + result |= -(1 << shift) + return result + + +def LEB128UnsignedEncode(int_val): + if int_val < 0: + raise Exception("value must not be negative") + if int_val == 0: + return bytes([0]) + byte_array = bytearray() + while int_val: + byte = int_val & 0x7F + byte_array.append(byte | 0x80) + int_val >>= 7 + byte_array[-1] ^= 0x80 + return byte_array + + +def LEB128SignedEncode(int_val): + byte_array = bytearray() + while True: + byte = int_val & 0x7F + byte_array.append(byte | 0x80) + int_val >>= 7 + if (int_val == 0 and byte & 0x40 == 0) or (int_val == -1 and byte & 0x40): + byte_array[-1] ^= 0x80 + break + return byte_array + + +class ELF_REL: + def __init__(self, r_offset, r_info): + self.r_offset = r_offset + self.r_info = r_info + + +class ELF_RELA: + def __init__(self, r_offset, r_info, r_addend): + self.r_offset = r_offset + self.r_info = r_info + self.r_addend = r_addend + + +def ffs(offset, header_list, numbered, *args): + # cn = Colors.green + ch = Colors.cyan + cd = Colors.blue + cb = Colors.BOLD + ci = Colors.red + ce = Colors.ENDC + max_column_width = [] + lines = [] + numbers_f = [] + dummy = [] + + if numbered: + numbers_f.extend(range(1, len(args[-1]) + 1)) + max_column_width.append( + max([len(repr(number)) for number in numbers_f]) if numbers_f else 6 + ) + header_list.insert(0, "idx") + + for arg in args: + max_column_width.append( + max([len(repr(argette)) for argette in arg]) if arg else 6 + ) + + index = range(0, len(header_list)) + for header, width, i in zip(header_list, max_column_width, index): + max_column_width[i] = max(len(header), width) + offset + + for i in index: + dummy.append(ch + cb + header_list[i].ljust(max_column_width[i]) + ce) + lines.append("".join(dummy)) + dummy.clear() + + index2 = range(0, len(args[-1])) + for i in index2: + if numbered: + dummy.append(ci + cb + repr(i).ljust(max_column_width[0]) + ce) + for arg, width in zip(args, max_column_width[1:]): + dummy.append(cd + repr(arg[i]).ljust(width) + ce) + else: + for arg, width in zip(args, max_column_width): + dummy.append(cd + repr(arg[i]).ljust(width) + ce) + lines.append("".join(dummy)) + dummy.clear() + return lines + + +def get_section_type_string(number): + if number == 0x0: + return "NULL" + if number == 0x1: + return "PROGBITS" + if number == 0x2: + return "SYMTAB" + if number == 0x3: + return "STRTAB" + if number == 0x4: + return "RELA" + if number == 0x5: + return "HASH" + if number == 0x6: + return "DYNAMIC" + if number == 0x7: + return "NOTE" + if number == 0x8: + return "NOBITS" + if number == 0x9: + return "REL" + if number == 0xA: + return "SHLIB" + if number == 0xB: + return "DYNSYM" + if number == 0xE: + return "INIT_ARRAY" + if number == 0xF: + return "FINI_ARRAY" + if number == 0x10: + return "PREINIT" + if number == 0x11: + return "GROUP" + if number == 0x12: + return "SYMTAB" + if number == 0x13: + return "NUM" + if number == 0x60000000: + return "LOOS" + if number == 0x6FFFFFF6: + return "GNU_HASH" + if number == 0x6FFFFFFF: + return "VERSYM" + if number == 0x6FFFFFFE: + return "VERNEED" + + +class sh_type_e: + SHT_NULL = 0x0 + SHT_PROGBITS = 0x1 + SHT_SYMTAB = 0x2 + SHT_STRTAB = 0x3 + SHT_RELA = 0x4 + SHT_HASH = 0x5 + SHT_DYNAMIC = 0x6 + SHT_NOTE = 0x7 + SHT_NOBITS = 0x8 + SHT_REL = 0x9 + SHT_SHLIB = 0xA + SHT_DYNSYM = 0xB + SHT_INIT_ARRAY = 0xE + SHT_FINI_ARRAY = 0xF + SHT_PREINIT = 0x10 + SHT_GROUP = 0x11 + SHT_SYMTAB_SHNDX = 0x12 + SHT_NUM = 0x13 + SHT_LOOS = 0x60000000 + GNU_HASH = 0x6FFFFFF6 + VERSYM = 0x6FFFFFFF + VERNEED = 0x6FFFFFFE + + +class sh_flags_e: + SHF_WRITE = 0x1 + SHF_ALLOC = 0x2 + SHF_EXECINSTR = 0x4 + SHF_MERGE = 0x10 + SHF_STRINGS = 0x20 + SHF_INFO_LINK = 0x40 + SHF_LINK_ORDER = 0x80 + SHF_OS_NONCONFORMING = 0x100 + SHF_GROUP = 0x200 + SHF_TLS = 0x400 + SHF_MASKOS = 0x0FF00000 + SHF_MASKPROC = 0xF0000000 + SHF_ORDERED = 0x4000000 + SHF_EXCLUDE = 0x8000000 + + +class p_type_e: + PT_NULL = 0x0 + PT_LOAD = 0x1 + PT_DYNAMIC = 0x2 + PT_INTERP = 0x3 + PT_NOTE = 0x4 + PT_SHLIB = 0x5 + PT_PHDR = 0x6 + PT_LOOS = 0x60000000 + PT_HIOS = 0x6FFFFFFF + PT_LOPROC = 0x70000000 + PT_HIPROC = 0x7FFFFFFF + GNU_EH_FRAME = 0x6474E550 + GNU_STACK = 0x6474E551 + GNU_RELRO = 0x6474E552 + + +def get_ph_type(value): + if value == p_type_e.PT_NULL: + return "NULL" + elif value == p_type_e.PT_LOAD: + return "LOAD" + elif value == p_type_e.PT_DYNAMIC: + return "DYNAMIC" + elif value == p_type_e.PT_INTERP: + return "INTERP" + elif value == p_type_e.PT_NOTE: + return "NOTE" + elif value == p_type_e.PT_SHLIB: + return "SHLIB" + elif value == p_type_e.PT_PHDR: + return "PHDR" + elif value == p_type_e.PT_LOOS: + return "LOOS" + elif value == p_type_e.PT_HIOS: + return "HIOS" + elif value == p_type_e.PT_LOPROC: + return "LOPROC" + elif value == p_type_e.PT_HIPROC: + return "HIPROC" + elif value == p_type_e.GNU_EH_FRAME: + return "GNU_EH_FRAME" + elif value == p_type_e.GNU_STACK: + return "GNU_STACK" + elif value == p_type_e.GNU_RELRO: + return "GNU_RELRO" + else: + return None + + +class ph_dynamic_entry: + def __init__(self, d_tag, d_un): + self.d_tag = d_tag + self.d_un = d_un + + +class elf_seg_flags: + PF_X = 0x1 + PF_W = 0x2 + PF_R = 0x4 + + +def get_elf_seg_flag(value): + ret = [] + if value & 0x01 == 1: + ret.append("X") + if (value & 0x02) >> 1 == 1: + ret.append("W") + if (value & 0x04) >> 2 == 1: + ret.append("R") + return "".join(ret) + + +class PH_DYN_TAG_TYPE: + DT_NULL = 0 + DT_NEEDED = 1 + DT_PLTRELSZ = 2 + DT_PLTGOT = 3 + DT_HASH = 4 + DT_STRTAB = 5 + DT_SYMTAB = 6 + DT_RELA = 7 + DT_RELASZ = 8 + DT_RELAENT = 9 + DT_STRSZ = 10 + DT_SYMENT = 11 + DT_INIT = 12 + DT_FINI = 13 + DT_SONAME = 14 + DT_RPATH = 15 + DT_SYMBOLIC = 16 + DT_REL = 17 + DT_RELSZ = 18 + DT_RELENT = 19 + DT_PLTREL = 20 + DT_DEBUG = 21 + DT_TEXTREL = 22 + DT_JMPREL = 23 + DT_LOPROC = 0x70000000 + DT_HIPROC = 0x7FFFFFFF + DT_BIND_NOW = 24 + DT_INIT_ARRAY = 25 + DT_FINI_ARRAY = 26 + DT_INIT_ARRAYSZ = 27 + DT_FINI_ARRAYSZ = 28 + DT_RUNPATH = 29 + DT_FLAGS = 30 + DT_ENCODING = 32 + DT_PREINIT_ARRAY = 32 + DT_PREINIT_ARRAYSZ = 33 + DT_NUM = 34 + DT_LOOS = 0x6000000D + DT_HIOS = 0x6FFFF000 + DT_PROC_NUM = 0x0 + DT_MIPS_NUM = 0x0 + DT_VALRNGLO = 0x6FFFFD00 + DT_GNU_PRELINKED = 0x6FFFFDF5 + DT_GNU_CONFLICTSZ = 0x6FFFFDF6 + DT_GNU_LIBLISTSZ = 0x6FFFFDF7 + DT_CHECKSUM = 0x6FFFFDF8 + DT_PLTPADSZ = 0x6FFFFDF9 + DT_MOVEENT = 0x6FFFFDFA + DT_MOVESZ = 0x6FFFFDFB + DT_FEATURE_1 = 0x6FFFFDFC + DT_POSFLAG_1 = 0x6FFFFDFD + DT_SYMINSZ = 0x6FFFFDFE + DT_SYMINENT = 0x6FFFFDFF + DT_VALRNGHI = 0x6FFFFDFF + DT_VALNUM = 12 + DT_ADDRRNGLO = 0x6FFFFE00 + DT_GNU_HASH = 0x6FFFFEF5 + DT_TLSDESC_PLT = 0x6FFFFEF6 + DT_TLSDESC_GOT = 0x6FFFFEF7 + DT_GNU_CONFLICT = 0x6FFFFEF8 + DT_GNU_LIBLIST = 0x6FFFFEF9 + DT_CONFIG = 0x6FFFFEFA + DT_DEPAUDIT = 0x6FFFFEFB + DT_AUDIT = 0x6FFFFEFC + DT_PLTPAD = 0x6FFFFEFD + DT_MOVETAB = 0x6FFFFEFE + DT_SYMINFO = 0x6FFFFEFF + DT_ADDRRNGHI = 0x6FFFFEFF + DT_ADDRNUM = 11 + DT_VERSYM = 0x6FFFFFF0 + DT_RELACOUNT = 0x6FFFFFF9 + DT_RELCOUNT = 0x6FFFFFFA + DT_FLAGS_1 = 0x6FFFFFFB + DT_VERDEF = 0x6FFFFFFC + DT_VERDEFNUM = 0x6FFFFFFD + DT_VERNEED = 0x6FFFFFFE + DT_VERNEEDNUM = 0x6FFFFFFF + DT_VERSIONTAGNUM = 16 + DT_AUXILIARY = 0x7FFFFFFD + DT_FILTER = 0x7FFFFFFF + DT_EXTRANUM = 3 + + +def get_ph_dynamic_ent_tag_type(value): + if value == PH_DYN_TAG_TYPE.DT_NULL: + return "DT_NULL" + elif value == PH_DYN_TAG_TYPE.DT_NEEDED: + return "DT_NEEDED" + elif value == PH_DYN_TAG_TYPE.DT_PLTRELSZ: + return "DT_PLTRELSZ" + elif value == PH_DYN_TAG_TYPE.DT_PLTGOT: + return "DT_PLTGOT" + elif value == PH_DYN_TAG_TYPE.DT_HASH: + return "DT_HASH" + elif value == PH_DYN_TAG_TYPE.DT_STRTAB: + return "DT_STRTAB" + elif value == PH_DYN_TAG_TYPE.DT_SYMTAB: + return "DT_SYMTAB" + elif value == PH_DYN_TAG_TYPE.DT_RELA: + return "DT_RELA" + elif value == PH_DYN_TAG_TYPE.DT_RELASZ: + return "DT_RELASZ" + elif value == PH_DYN_TAG_TYPE.DT_RELAENT: + return "DT_RELAENT" + elif value == PH_DYN_TAG_TYPE.DT_STRSZ: + return "DT_STRSZ" + elif value == PH_DYN_TAG_TYPE.DT_SYMENT: + return "DT_SYMENT" + elif value == PH_DYN_TAG_TYPE.DT_INIT: + return "DT_INIT" + elif value == PH_DYN_TAG_TYPE.DT_FINI: + return "DT_FINI" + elif value == PH_DYN_TAG_TYPE.DT_SONAME: + return "DT_SONAME" + elif value == PH_DYN_TAG_TYPE.DT_RPATH: + return "DT_RPATH" + elif value == PH_DYN_TAG_TYPE.DT_SYMBOLIC: + return "DT_SYMBOLIC" + elif value == PH_DYN_TAG_TYPE.DT_REL: + return "DT_REL" + elif value == PH_DYN_TAG_TYPE.DT_RELSZ: + return "DT_RELSZ" + elif value == PH_DYN_TAG_TYPE.DT_RELENT: + return "DT_RELENT" + elif value == PH_DYN_TAG_TYPE.DT_PLTREL: + return "DT_PLTREL" + elif value == PH_DYN_TAG_TYPE.DT_DEBUG: + return "DT_DEBUG" + elif value == PH_DYN_TAG_TYPE.DT_TEXTREL: + return "DT_TEXTREL" + elif value == PH_DYN_TAG_TYPE.DT_JMPREL: + return "DT_JMPREL" + elif value == PH_DYN_TAG_TYPE.DT_LOPROC: + return "DT_LOPROC" + elif value == PH_DYN_TAG_TYPE.DT_HIPROC: + return "DT_HIPROC" + elif value == PH_DYN_TAG_TYPE.DT_BIND_NOW: + return "DT_BIND_NOW" + elif value == PH_DYN_TAG_TYPE.DT_INIT_ARRAY: + return "DT_INIT_ARRAY" + elif value == PH_DYN_TAG_TYPE.DT_FINI_ARRAY: + return "DT_FINI_ARRAY" + elif value == PH_DYN_TAG_TYPE.DT_INIT_ARRAYSZ: + return "DT_INIT_ARRAYSZ" + elif value == PH_DYN_TAG_TYPE.DT_FINI_ARRAYSZ: + return "DT_FINI_ARRAYSZ" + elif value == PH_DYN_TAG_TYPE.DT_RUNPATH: + return "DT_RUNPATH" + elif value == PH_DYN_TAG_TYPE.DT_FLAGS: + return "DT_FLAGS" + elif value == PH_DYN_TAG_TYPE.DT_ENCODING: + return "DT_ENCODING" + elif value == PH_DYN_TAG_TYPE.DT_PREINIT_ARRAY: + return "DT_PREINIT_ARRAY" + elif value == PH_DYN_TAG_TYPE.DT_PREINIT_ARRAYSZ: + return "DT_PREINIT_ARRAYSZ" + elif value == PH_DYN_TAG_TYPE.DT_NUM: + return "DT_NUM" + elif value == PH_DYN_TAG_TYPE.DT_LOOS: + return "DT_LOOS" + elif value == PH_DYN_TAG_TYPE.DT_HIOS: + return "DT_HIOS" + # elif value == PH_DYN_TAG_TYPE.DT_PROC_NUM: return "DT_PROC_NUM" + # elif value == PH_DYN_TAG_TYPE.DT_MIPS_NUM: return "DT_MIPS_NUM" + elif value == PH_DYN_TAG_TYPE.DT_VALRNGLO: + return "DT_VALRNGLO" + elif value == PH_DYN_TAG_TYPE.DT_GNU_PRELINKED: + return "DT_GNU_PRELINKED" + elif value == PH_DYN_TAG_TYPE.DT_GNU_CONFLICTSZ: + return "DT_GNU_CONFLICTSZ" + elif value == PH_DYN_TAG_TYPE.DT_GNU_LIBLISTSZ: + return "DT_GNU_LIBLISTSZ" + elif value == PH_DYN_TAG_TYPE.DT_CHECKSUM: + return "DT_CHECKSUM" + elif value == PH_DYN_TAG_TYPE.DT_PLTPADSZ: + return "DT_PLTPADSZ" + elif value == PH_DYN_TAG_TYPE.DT_MOVEENT: + return "DT_MOVEENT" + elif value == PH_DYN_TAG_TYPE.DT_MOVESZ: + return "DT_MOVESZ" + elif value == PH_DYN_TAG_TYPE.DT_FEATURE_1: + return "DT_FEATURE_1" + elif value == PH_DYN_TAG_TYPE.DT_POSFLAG_1: + return "DT_POSFLAG_1" + elif value == PH_DYN_TAG_TYPE.DT_SYMINSZ: + return "DT_SYMINSZ" + elif value == PH_DYN_TAG_TYPE.DT_SYMINENT: + return "DT_SYMINENT" + elif value == PH_DYN_TAG_TYPE.DT_VALRNGHI: + return "DT_VALRNGHI" + # DT_VALNUM = 12 + elif value == PH_DYN_TAG_TYPE.DT_ADDRRNGLO: + return "DT_ADDRRNGLO" + elif value == PH_DYN_TAG_TYPE.DT_GNU_HASH: + return "DT_GNU_HASH" + elif value == PH_DYN_TAG_TYPE.DT_TLSDESC_PLT: + return "DT_TLSDESC_PLT" + elif value == PH_DYN_TAG_TYPE.DT_TLSDESC_GOT: + return "DT_TLSDESC_GOT" + elif value == PH_DYN_TAG_TYPE.DT_GNU_CONFLICT: + return "DT_GNU_CONFLICT" + elif value == PH_DYN_TAG_TYPE.DT_GNU_LIBLIST: + return "DT_GNU_LIBLIST" + elif value == PH_DYN_TAG_TYPE.DT_CONFIG: + return "DT_CONFIG" + elif value == PH_DYN_TAG_TYPE.DT_DEPAUDIT: + return "DT_DEPAUDIT" + elif value == PH_DYN_TAG_TYPE.DT_AUDIT: + return "DT_AUDIT" + elif value == PH_DYN_TAG_TYPE.DT_PLTPAD: + return "DT_PLTPAD" + elif value == PH_DYN_TAG_TYPE.DT_MOVETAB: + return "DT_MOVETAB" + elif value == PH_DYN_TAG_TYPE.DT_SYMINFO: + return "DT_SYMINFO" + elif value == PH_DYN_TAG_TYPE.DT_ADDRRNGHI: + return "DT_ADDRRNGHI" + # DT_ADDRNUM = 11 + elif value == PH_DYN_TAG_TYPE.DT_VERSYM: + return "DT_VERSYM" + elif value == PH_DYN_TAG_TYPE.DT_RELACOUNT: + return "DT_RELACOUNT" + elif value == PH_DYN_TAG_TYPE.DT_RELCOUNT: + return "DT_RELCOUNT" + elif value == PH_DYN_TAG_TYPE.DT_FLAGS_1: + return "DT_FLAGS_1" + elif value == PH_DYN_TAG_TYPE.DT_VERDEF: + return "DT_VERDEF" + elif value == PH_DYN_TAG_TYPE.DT_VERDEFNUM: + return "DT_VERDEFNUM" + elif value == PH_DYN_TAG_TYPE.DT_VERNEED: + return "DT_VERNEED" + elif value == PH_DYN_TAG_TYPE.DT_VERNEEDNUM: + return "DT_VERNEEDNUM" + elif value == PH_DYN_TAG_TYPE.DT_VERSIONTAGNUM: + return "DT_VERSIONTAGNUM" + elif value == PH_DYN_TAG_TYPE.DT_AUXILIARY: + return "DT_AUXILIARY" + elif value == PH_DYN_TAG_TYPE.DT_FILTER: + return "DT_FILTER" + # DT_EXTRANUM = 3 + else: + return str(value) + # else: return "UNKNOWN" + + +class X86_REL_TYPE: + R_386_NONE = 0 + R_386_32 = 1 + R_386_PC32 = 2 + R_386_GOT32 = 3 + R_386_PLT32 = 4 + R_386_COPY = 5 + R_386_GLOB_DAT = 6 + R_386_JMP_SLOT = 7 + R_386_RELATIVE = 8 + R_386_GOTOFF = 9 + R_386_GOTPC = 10 + R_386_32PLT = 11 + R_386_16 = 12 + R_386_PC16 = 13 + R_386_8 = 14 + R_386_PC8 = 15 + R_386_SIZE32 = 16 + + +def get_x86_rel_type(val): + if val == X86_REL_TYPE.R_386_NONE: + return "R_386_NONE" + elif val == X86_REL_TYPE.R_386_32: + return "R_386_32" + elif val == X86_REL_TYPE.R_386_PC32: + return "R_386_PC32" + elif val == X86_REL_TYPE.R_386_GOT32: + return "R_386_GOT32" + elif val == X86_REL_TYPE.R_386_PLT32: + return "R_386_PLT32" + elif val == X86_REL_TYPE.R_386_COPY: + return "R_386_COPY" + elif val == X86_REL_TYPE.R_386_GLOB_DAT: + return "R_386_GLOB_DAT" + elif val == X86_REL_TYPE.R_386_JMP_SLOT: + return "R_386_JMP_SLOT" + elif val == X86_REL_TYPE.R_386_RELATIVE: + return "R_386_RELATIVE" + elif val == X86_REL_TYPE.R_386_GOTOFF: + return "R_386_GOTOFF" + elif val == X86_REL_TYPE.R_386_GOTPC: + return "R_386_GOTPC" + elif val == X86_REL_TYPE.R_386_32PLT: + return "R_386_32PLT" + elif val == X86_REL_TYPE.R_386_16: + return "R_386_16" + elif val == X86_REL_TYPE.R_386_PC16: + return "R_386_PC16" + elif val == X86_REL_TYPE.R_386_8: + return "R_386_8" + elif val == X86_REL_TYPE.R_386_PC8: + return "R_386_PC8" + elif val == X86_REL_TYPE.R_386_SIZE32: + return "R_386_SIZE32" + else: + return "UNKNOWN" + + +class X86_64_REL_TYPE: + R_AMD64_NONE = 0 + R_AMD64_64 = 1 + R_AMD64_PC32 = 2 + R_AMD64_GOT32 = 3 + R_AMD64_PLT32 = 4 + R_AMD64_COPY = 5 + R_AMD64_GLOB_DAT = 6 + R_AMD64_JUMP_SLOT = 7 + R_AMD64_RELATIVE = 8 + R_AMD64_GOTPCREL = 9 + R_AMD64_32 = 10 + R_AMD64_32S = 11 + R_AMD64_16 = 12 + R_AMD64_PC16 = 13 + R_AMD64_8 = 14 + R_AMD64_PC8 = 15 + R_AMD64_PC64 = 24 + R_AMD64_GOTOFF64 = 25 + R_AMD64_GOTPC32 = 26 + R_AMD64_SIZE32 = 32 + R_AMD64_SIZE64 = 33 + + +class X86_64_REL_TYPE_2: + R_X86_64_NONE = 0 + R_X86_64_64 = 1 + R_X86_64_PC32 = 2 + R_X86_64_GOT32 = 3 + R_X86_64_PLT32 = 4 + R_X86_64_COPY = 5 + R_X86_64_GLOB_DAT = 6 + R_X86_64_JUMP_SLOT = 7 + R_X86_64_RELATIVE = 8 + R_X86_64_GOTPCREL = 9 + R_X86_64_32 = 10 + R_X86_64_32S = 11 + R_X86_64_16 = 12 + R_X86_64_PC16 = 13 + R_X86_64_64_8 = 14 + R_X86_64_PC8 = 15 + R_X86_64_DTPMOD64 = 16 + R_X86_64_DTPOFF64 = 17 + R_X86_64_TPOFF64 = 18 + R_X86_64_TLSGD = 19 + R_X86_64_TLSLD = 20 + R_X86_64_DTPOFF32 = 21 + R_X86_64_GOTTPOFF = 22 + R_X86_64_TPOFF32 = 23 + R_X86_64_PC64 = 24 + R_X86_64_GOTOFF64 = 25 + R_X86_64_GOTPC32 = 26 + R_X86_64_SIZE32 = 32 + R_X86_64_SIZE64 = 33 + R_X86_64_GOTPC32_TLDSEC = 34 + R_X86_64_TLDSEC_CALL = 35 + R_X86_64_TLDSEC = 36 + R_X86_64_IRELATIVE = 37 + + +def get_x86_64_rel_type(val): + if val == X86_64_REL_TYPE.R_AMD64_NONE: + return "R_386_NONE" + elif val == X86_64_REL_TYPE.R_AMD64_64: + return "R_AMD64_64" + elif val == X86_64_REL_TYPE.R_AMD64_PC32: + return "R_AMD64_PC32" + elif val == X86_64_REL_TYPE.R_AMD64_GOT32: + return "R_AMD64_GOT32" + elif val == X86_64_REL_TYPE.R_AMD64_PLT32: + return "R_AMD64_PLT32" + elif val == X86_64_REL_TYPE.R_AMD64_COPY: + return "R_AMD64_COPY" + elif val == X86_64_REL_TYPE.R_AMD64_GLOB_DAT: + return "R_AMD64_GLOB_DAT" + elif val == X86_64_REL_TYPE.R_AMD64_JUMP_SLOT: + return "R_AMD64_JUMP_SLOT" + elif val == X86_64_REL_TYPE.R_AMD64_RELATIVE: + return "R_AMD64_RELATIVE" + elif val == X86_64_REL_TYPE.R_AMD64_GOTPCREL: + return "R_AMD64_GOTPCREL" + elif val == X86_64_REL_TYPE.R_AMD64_32: + return "R_AMD64_32" + elif val == X86_64_REL_TYPE.R_AMD64_32S: + return "R_AMD64_32S" + elif val == X86_64_REL_TYPE.R_AMD64_16: + return "R_AMD64_16" + elif val == X86_64_REL_TYPE.R_AMD64_PC16: + return "R_AMD64_PC16" + elif val == X86_64_REL_TYPE.R_AMD64_8: + return "R_AMD64_8" + elif val == X86_64_REL_TYPE.R_AMD64_PC8: + return "R_AMD64_PC8" + elif val == X86_64_REL_TYPE.R_AMD64_PC64: + return "R_AMD64_PC64" + elif val == X86_64_REL_TYPE.R_AMD64_GOTOFF64: + return "R_AMD64_GOTOFF64" + elif val == X86_64_REL_TYPE.R_AMD64_GOTPC32: + return "R_AMD64_GOTPC32" + elif val == X86_64_REL_TYPE.R_AMD64_SIZE32: + return "R_AMD64_SIZE32" + elif val == X86_64_REL_TYPE.R_AMD64_SIZE64: + return "R_AMD64_SIZE64" + else: + return "UNKNOWN" + + +def get_x86_64_rel_type_2(val): + if val == X86_64_REL_TYPE_2.R_X86_64_NONE: + return "R_X86_64_NONE" + elif val == X86_64_REL_TYPE_2.R_X86_64_64: + return "R_X86_64_64" + elif val == X86_64_REL_TYPE_2.R_X86_64_PC32: + return "R_X86_64_PC32" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOT32: + return "R_X86_64_GOT32" + elif val == X86_64_REL_TYPE_2.R_X86_64_PLT32: + return "R_X86_64_PLT32" + elif val == X86_64_REL_TYPE_2.R_X86_64_COPY: + return "R_X86_64_COPY" + elif val == X86_64_REL_TYPE_2.R_X86_64_GLOB_DAT: + return "R_X86_64_GLOB_DAT" + elif val == X86_64_REL_TYPE_2.R_X86_64_JUMP_SLOT: + return "R_X86_64_JUMP_SLOT" + elif val == X86_64_REL_TYPE_2.R_X86_64_RELATIVE: + return "R_X86_64_RELATIVE" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOTPCREL: + return "R_X86_64_GOTPCREL" + elif val == X86_64_REL_TYPE_2.R_X86_64_32: + return "R_X86_64_32" + elif val == X86_64_REL_TYPE_2.R_X86_64_32S: + return "R_X86_64_32S" + elif val == X86_64_REL_TYPE_2.R_X86_64_16: + return "R_X86_64_16" + elif val == X86_64_REL_TYPE_2.R_X86_64_PC16: + return "R_X86_64_PC16" + elif val == X86_64_REL_TYPE_2.R_X86_64_64_8: + return "R_X86_64_64_8" + elif val == X86_64_REL_TYPE_2.R_X86_64_PC8: + return "R_X86_64_PC8" + elif val == X86_64_REL_TYPE_2.R_X86_64_DTPMOD64: + return "R_X86_64_DTPMOD64" + elif val == X86_64_REL_TYPE_2.R_X86_64_DTPOFF64: + return "R_X86_64_DTPOFF64" + elif val == X86_64_REL_TYPE_2.R_X86_64_TPOFF64: + return "R_X86_64_TPOFF64" + elif val == X86_64_REL_TYPE_2.R_X86_64_TLSGD: + return "R_X86_64_TLSGD" + elif val == X86_64_REL_TYPE_2.R_X86_64_TLSLD: + return "R_X86_64_TLSLD" + elif val == X86_64_REL_TYPE_2.R_X86_64_DTPOFF32: + return "R_X86_64_DTPOFF32" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOTTPOFF: + return "R_X86_64_GOTTPOFF" + elif val == X86_64_REL_TYPE_2.R_X86_64_TPOFF32: + return "R_X86_64_TPOFF32" + elif val == X86_64_REL_TYPE_2.R_X86_64_PC64: + return "R_X86_64_PC64" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOTOFF64: + return "R_X86_64_GOTOFF64" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOTPC32: + return "R_X86_64_GOTPC32" + elif val == X86_64_REL_TYPE_2.R_X86_64_SIZE32: + return "R_X86_64_SIZE32" + elif val == X86_64_REL_TYPE_2.R_X86_64_SIZE64: + return "R_X86_64_SIZE64" + elif val == X86_64_REL_TYPE_2.R_X86_64_GOTPC32_TLDSEC: + return "R_X86_64_GOTPC32_TLDSEC" + elif val == X86_64_REL_TYPE_2.R_X86_64_TLDSEC_CALL: + return "R_X86_64_TLDSEC_CALL" + elif val == X86_64_REL_TYPE_2.R_X86_64_TLDSEC: + return "R_X86_64_TLDSEC" + elif val == X86_64_REL_TYPE_2.R_X86_64_IRELATIVE: + return "R_X86_64_IRELATIVE" + else: + return "UNKNOWN" + + +class ELF_ST_BIND: + STB_LOCAL = 0 + STB_GLOBAL = 1 + STB_WEAK = 2 + STB_LOOS = 10 + STB_HIOS = 12 + STB_LOPROC = 13 + STB_HIPROC = 15 + + +def get_elf_st_bind_string(value): + if value == ELF_ST_BIND.STB_LOCAL: + return "STB_LOCAL" + elif value == ELF_ST_BIND.STB_GLOBAL: + return "STB_GLOBAL" + elif value == ELF_ST_BIND.STB_WEAK: + return "STB_WEAK" + elif value == ELF_ST_BIND.STB_LOOS: + return "STB_LOOS" + elif value == ELF_ST_BIND.STB_HIOS: + return "STB_HIOS" + elif value == ELF_ST_BIND.STB_LOPROC: + return "STB_LOPROC" + elif value == ELF_ST_BIND.STB_LOPROC: + return "STB_HIPROC" + else: + return None + + +class ELF_ST_TYPE: + STT_NOTYPE = 0 + STT_OBJECT = 1 + STT_FUNC = 2 + STT_SECTION = 3 + STT_FILE = 4 + STT_COMMON = 5 + STT_TLS = 6 + STT_LOOS = 10 + STT_HIOS = 12 + STT_LOPROC = 13 + STT_SPARC_REGISTER = 13 + STT_HIPROC = 15 + + +def get_elf_st_type_string(value): + if value == ELF_ST_TYPE.STT_NOTYPE: + return "STT_NOTYPE" + elif value == ELF_ST_TYPE.STT_OBJECT: + return "STT_OBJECT" + elif value == ELF_ST_TYPE.STT_FUNC: + return "STT_FUNC" + elif value == ELF_ST_TYPE.STT_SECTION: + return "STT_SECTION" + elif value == ELF_ST_TYPE.STT_FILE: + return "STT_FILE" + elif value == ELF_ST_TYPE.STT_COMMON: + return "STT_COMMON" + elif value == ELF_ST_TYPE.STT_TLS: + return "STT_TLS" + elif value == ELF_ST_TYPE.STT_LOOS: + return "STT_LOOS" + elif value == ELF_ST_TYPE.STT_HIOS: + return "STT_HIOS" + elif value == ELF_ST_TYPE.STT_LOPROC: + return "STT_LOPROC" + elif value == ELF_ST_TYPE.STT_SPARC_REGISTER: + return "STT_SPARC_REGISTER" + elif value == ELF_ST_TYPE.STT_HIPROC: + return "STT_HIPROC" + else: + return None + + +class ELF_VIS: + STV_DEFAULT = 0 + STV_INTERNAL = 1 + STV_HIDDEN = 2 + STV_PROTECTED = 3 + STV_EXPORTED = 4 + STV_SINGLETON = 5 + STV_ELIMINATE = 6 + + +def get_elf_vis_string(value): + if value == ELF_VIS.STV_DEFAULT: + return "STV_DEFAULT" + elif value == ELF_VIS.STV_INTERNAL: + return "STV_INTERNAL" + elif value == ELF_VIS.STV_HIDDEN: + return "STV_HIDDEN" + elif value == ELF_VIS.STV_PROTECTED: + return "STV_PROTECTED" + elif value == ELF_VIS.STV_EXPORTED: + return "STV_EXPORTED" + elif value == ELF_VIS.STV_SINGLETON: + return "STV_SINGLETON" + elif value == ELF_VIS.STV_ELIMINATE: + return "STV_ELIMINATE" + else: + return None + + +class Colors: + purple = "\033[95m" + blue = "\033[94m" + green = "\033[92m" + yellow = "\033[93m" + red = "\033[91m" + grey = "\033[1;37m" + darkgrey = "\033[1;30m" + cyan = "\033[1;36m" + ENDC = "\033[0m" + BOLD = "\033[1m" + UNDERLINE = "\033[4m" + + +def openSO_r(path): + so = open(path, "rb") + return so + + +def openSO_w(path): + so = open(path, "wb") + return so + + +class ELFHDR: + def __init__( + self, + ei_mag, + ei_class, + ei_data, + ei_version, + ei_osabi, + ei_abiversion, + ei_pad, + e_type, + e_machine, + e_version, + e_entry, + e_phoff, + e_shoff, + e_flags, + e_ehsize, + e_phentsize, + e_phnum, + e_shentsize, + e_shnum, + e_shstrndx, + ): + self.ei_mag = ei_mag + self.ei_class = ei_class + self.ei_data = ei_data + self.ei_version = ei_version + self.ei_osabi = ei_osabi + self.ei_abiversion = ei_abiversion + self.ei_pad = ei_pad + self.e_type = e_type + self.e_machine = e_machine + self.e_version = e_version + self.e_entry = e_entry + self.e_phoff = e_phoff + self.e_shoff = e_shoff + self.e_flags = e_flags + self.e_ehsize = e_ehsize + self.e_phentsize = e_phentsize + self.e_phnum = e_phnum + self.e_shentsize = e_shentsize + self.e_shnum = e_shnum + self.e_shstrndx = e_shstrndx + + +class PHDR: + def __init__( + self, + p_type, + p_flags, + p_offset, + p_vaddr, + p_paddr, + p_filesz, + p_memsz, + p_flags2, + p_align, + ): + self.p_type = p_type + self.p_flags = p_flags + self.p_offset = p_offset + self.p_vaddr = p_vaddr + self.p_paddr = p_paddr + self.p_filesz = p_filesz + self.p_memsz = p_memsz + self.p_flags2 = p_flags2 + self.p_align = p_align + + +class SHDR: + def __init__( + self, + sh_name, + sh_type, + sh_flags, + sh_addr, + sh_offset, + sh_size, + sh_link, + sh_info, + sh_addralign, + sh_entsize, + ): + self.sh_name = sh_name + self.sh_type = sh_type + self.sh_flags = sh_flags + self.sh_addr = sh_addr + self.sh_offset = sh_offset + self.sh_size = sh_size + self.sh_link = sh_link + self.sh_info = sh_info + self.sh_addralign = sh_addralign + self.sh_entsize = sh_entsize + + +class Symbol_Table_Entry64: + def __init__( + self, + st_name, + st_info, + st_other, + st_shndx, + st_value, + st_size, + st_bind, + st_type, + ): + self.st_name = st_name + self.st_info = st_info + self.st_other = st_other + self.st_shndx = st_shndx + self.st_value = st_value + self.st_size = st_size + self.st_bind = st_bind + self.st_type = st_type + + +class ELF(object): + def __init__(self, so): + 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) + self.phdr = [] + self.shhdr = [] + self.size = int() + self.string_tb_e = [] + self.string_tb_e_dyn = [] + self.symbol_table_e = [] + self.data_section = [] + self.text_section = [] + self.dlpath = str() + self.ph_dyn_ent = [] + self.dyn_section = [] + self.dyn_section_ents = [] + self.rela_dyn = [] + self.rela_dyn_ents = [] + self.rela_plt = [] + self.rela_plt_ents = [] + self.rodata = [] + self.plt = [] + self.got = [] + self.got_plt = [] + self.plt_got = [] + self.plt_ents = [] + self.plt_got_ents = [] + self.got_ents = [] + self.got_plt_ents = [] + + def init(self, size): + self.size = size + self.read_ELF_H(size) + self.so.seek(byte2int(self.elfhdr.e_phoff)) + phnum = byte2int(self.elfhdr.e_phnum) + for i in range(0, phnum): + self.read_PHDR(size) + self.so.seek(byte2int(self.elfhdr.e_shoff)) + shnum = byte2int(self.elfhdr.e_shnum) + for i in range(0, shnum): + self.read_SHDR(size) + for i in range(0, shnum): + type = byte2int(self.shhdr[i].sh_type) + if type == sh_type_e.SHT_SYMTAB: + self.so.seek(byte2int(self.shhdr[i].sh_offset), 0) + symbol_tb = self.so.read(byte2int(self.shhdr[i].sh_size)) + offset = 0 + num = int(byte2int(self.shhdr[i].sh_size) / 24) + for j in range(0, num): + self.read_st_entry( + symbol_tb[offset : offset + 24], self.string_tb_e + ) + offset += 24 + if type == sh_type_e.SHT_DYNSYM: + self.so.seek(byte2int(self.shhdr[i].sh_offset), 0) + symbol_tb = self.so.read(byte2int(self.shhdr[i].sh_size)) + offset = 0 + num = int(byte2int(self.shhdr[i].sh_size) / 24) + for j in range(0, num): + self.read_st_entry( + symbol_tb[offset : offset + 24], self.string_tb_e_dyn + ) + offset += 24 + self.pop_data_section() + self.pop_text_section() + self.get_ph_dyn_entries() + self.pop_dynamic_entries(".dynamic", self.dyn_section_ents) + self.pop_rela(".rela.plt", self.rela_plt, self.rela_plt_ents) + self.pop_rela(".rela.dyn", self.rela_dyn, self.rela_dyn_ents) + # self.pop_rel() + + def read_ELF_H(self, size): + self.elfhdr.ei_mag = self.so.read(4) + self.elfhdr.ei_class = self.so.read(1) + self.elfhdr.ei_data = self.so.read(1) + self.elfhdr.ei_version = self.so.read(1) + self.elfhdr.ei_osabi = self.so.read(1) + self.elfhdr.ei_abiversion = self.so.read(1) + self.elfhdr.ei_pad = self.so.read(7) + self.elfhdr.e_type = self.so.read(2) + self.elfhdr.e_machine = self.so.read(2) + self.elfhdr.e_version = self.so.read(4) + if size == 32: + self.elfhdr.e_entry = self.so.read(4) + elif size == 64: + self.elfhdr.e_entry = self.so.read(8) + if size == 32: + self.elfhdr.e_phoff = self.so.read(4) + elif size == 64: + self.elfhdr.e_phoff = self.so.read(8) + if size == 32: + self.elfhdr.e_shoff = self.so.read(4) + elif size == 64: + self.elfhdr.e_shoff = self.so.read(8) + self.elfhdr.e_flags = self.so.read(4) + self.elfhdr.e_ehsize = self.so.read(2) + self.elfhdr.e_phentsize = self.so.read(2) + self.elfhdr.e_phnum = self.so.read(2) + self.elfhdr.e_shentsize = self.so.read(2) + self.elfhdr.e_shnum = self.so.read(2) + self.elfhdr.e_shstrndx = self.so.read(2) + + def read_PHDR(self, size): + dummy = PHDR(0, 0, 0, 0, 0, 0, 0, 0, 0) + dummy.p_type = self.so.read(4) + if size == 64: + dummy.p_flags = self.so.read(4) + if size == 32: + dummy.p_offset = self.so.read(4) + elif size == 64: + dummy.p_offset = self.so.read(8) + if size == 32: + dummy.p_vaddr = self.so.read(4) + elif size == 64: + dummy.p_vaddr = self.so.read(8) + if size == 32: + dummy.p_paddr = self.so.read(4) + elif size == 64: + dummy.p_paddr = self.so.read(8) + if size == 32: + dummy.p_filesz = self.so.read(4) + elif size == 64: + dummy.p_filesz = self.so.read(8) + if size == 32: + dummy.p_memsz = self.so.read(4) + elif size == 64: + dummy.p_memsz = self.so.read(8) + if size == 32: + dummy.p_flags2 = self.so.read(4) + elif size == 64: + pass + if size == 32: + dummy.p_align = self.so.read(4) + elif size == 64: + dummy.p_align = self.so.read(8) + self.phdr.append(dummy) + + def read_SHDR(self, size): + dummy = SHDR(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + dummy.sh_name = self.so.read(4) + dummy.sh_type = self.so.read(4) + if size == 32: + dummy.sh_flags = self.so.read(4) + elif size == 64: + dummy.sh_flags = self.so.read(8) + if size == 32: + dummy.sh_addr = self.so.read(4) + elif size == 64: + dummy.sh_addr = self.so.read(8) + if size == 32: + dummy.sh_offset = self.so.read(4) + elif size == 64: + dummy.sh_offset = self.so.read(8) + if size == 32: + dummy.sh_size = self.so.read(4) + elif size == 64: + dummy.sh_size = self.so.read(8) + dummy.sh_link = self.so.read(4) + dummy.sh_info = self.so.read(4) + if size == 32: + dummy.sh_addralign = self.so.read(4) + elif size == 64: + dummy.sh_addralign = self.so.read(8) + if size == 32: + dummy.sh_entsize = self.so.read(4) + elif size == 64: + dummy.sh_entsize = self.so.read(8) + self.shhdr.append(dummy) + + def read_st_entry(self, st, entry_list): + dummy = Symbol_Table_Entry64(0, 0, 0, 0, 0, 0, 0, 0) + dummy.st_name = st[0:4] + dummy.st_info = st[4:5] + dummy.st_other = st[5:6] + dummy.st_shndx = st[6:8] + dummy.st_value = st[8:16] + dummy.st_size = st[16:24] + dummy.st_bind = byte2int(dummy.st_info) >> 4 + dummy.st_type = byte2int(dummy.st_info) & 0x0F + entry_list.append(dummy) + + def read_section_name(self, index): + shstrtab_index = byte2int(self.elfhdr.e_shstrndx) + name = [] + self.so.seek(byte2int(self.shhdr[shstrtab_index].sh_offset), 0) + strings = self.so.read(byte2int(self.shhdr[shstrtab_index].sh_size)) + char = strings[index] + while chr(char) != "\0": + index += 1 + name.append(chr(char)) + char = strings[index] + return "".join(name) + + def get_ph_dyn_entries(self): + size = 0 + for phdr in self.phdr: + if byte2int(phdr.p_type) == p_type_e.PT_DYNAMIC: + self.so.seek(byte2int(phdr.p_offset), 0) + size = byte2int(phdr.p_filesz) + ph_dyn = self.so.read(size) + for i in range(int(size / 8)): + d_tag = byte2int(ph_dyn[8 * i : 8 * i + 4]) + d_un = byte2int(ph_dyn[8 * i + 4 : 8 * i + 8]) + self.ph_dyn_ent.append(ph_dynamic_entry(d_tag, d_un)) + + def dump_ph_dyn_entries(self): + 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) + for line in lines: + print(line) + + def dump_funcs(self, dump_b): + ret_list = [] + dummy = [] + ret_list_int = [] + for iter in self.string_tb_e: + if iter.st_type == ELF_ST_TYPE.STT_FUNC: + self.so.seek(int.from_bytes(iter.st_value, byteorder="little")) + obj = self.so.read(int.from_bytes(iter.st_size, byteorder="little")) + ret_list.append(obj) + for byte in obj: + dummy.append(int(byte)) + ret_list_int.append(dummy) + dummy = [] + if dump_b: + for obj in ret_list_int: + for byte in obj: + print(format(byte, "02x") + " ", end="") + print("\n") + + return ret_list_int + + def dump_symbol_string(self, stt_type, dump_b): + ret_list = [] + for entry in self.string_tb_e: + if entry.st_type == stt_type: + ret_list.append( + "".join( + self.get_st_entry_symbol_string( + byte2int(entry.st_name), ".strtab" + ) + ) + ) + if dump_b: + for name in ret_list: + print(name) + return ret_list + + def dump_section(self, section_name, dump): + hit = False + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == section_name: + hit = True + self.so.seek(byte2int(section.sh_offset)) + obj = self.so.read(byte2int(section.sh_size)) + if section_name == ".interp": + self.dlpath = repr(obj) + count = int() + if dump: + strrep = [] + for byte in obj: + if count % 16 == 0: + for ch in strrep: + if ord(ch) > 32 and ord(ch) < 127: + print(ch, end="") + else: + print(" ", end="") + print() + strrep = [] + print(format(count, "06x"), ": ", end="") + strrep.append(str(chr(byte))) + print(format(byte, "02x") + " ", end="") + else: + strrep += str(chr(byte)) + print(format(byte, "02x") + " ", end="") + count += 1 + for i in range(0, 16 - count % 16): + print(" ", end="") + for ch in strrep: + if ord(ch) > 32 and ord(ch) < 127: + print(ch, end="") + else: + print(" ", end="") + print() + + ret_dummy = [] + for i in range(0, len(obj)): + ret_dummy.append(obj[i]) + # print(ret_dummy) + return ret_dummy + if not hit: + print(Colors.red + Colors.BOLD + "section is not present" + Colors.ENDC) + + def dump_obj_size(self, stt_type, dump_b): + ret_list = [] + for entry in self.string_tb_e: + if entry.st_type == stt_type: + ret_list.append(byte2int(entry.st_size)) + if dump_b: + for name in ret_list: + print(name) + return ret_list + + def dump_symbol_idx(self): + header = ["name", "size", "value", "info", "other", "shndx"] + name_list = [byte2int(st.st_name) for st in self.string_tb_e] + size_list = [byte2int(st.st_size) for st in self.string_tb_e] + value_list = [byte2int(st.st_value) for st in self.string_tb_e] + info_list = [byte2int(st.st_info) for st in self.string_tb_e] + other_list = [byte2int(st.st_other) for st in self.string_tb_e] + shndx_list = [byte2int(st.st_shndx) for st in self.string_tb_e] + lines = ffs( + 2, + header, + True, + name_list, + size_list, + value_list, + info_list, + other_list, + shndx_list, + ) + print(Colors.green + Colors.BOLD + "symbol:" + Colors.ENDC) + for line in lines: + print(line) + print(Colors.green + Colors.BOLD + "dyn symbol:" + Colors.ENDC) + header = ["name", "size", "value", "info", "other", "shndx"] + name_list = [byte2int(st.st_name) for st in self.string_tb_e_dyn] + size_list = [byte2int(st.st_size) for st in self.string_tb_e_dyn] + value_list = [byte2int(st.st_value) for st in self.string_tb_e_dyn] + info_list = [byte2int(st.st_info) for st in self.string_tb_e_dyn] + other_list = [byte2int(st.st_other) for st in self.string_tb_e_dyn] + shndx_list = [byte2int(st.st_shndx) for st in self.string_tb_e_dyn] + lines = ffs( + 2, + header, + True, + name_list, + size_list, + value_list, + info_list, + other_list, + shndx_list, + ) + for line in lines: + print(line) + + def dump_header(self): + header = [ + "ei_mag", + "ei_class", + "ei_data", + "ei_version", + "ei_osabi", + "ei_abiversion", + "ei_pad", + "e_type", + "e_machine", + "e_version", + "e_version", + "e_entry", + "e_phoff", + "e_shoff", + "e_flags", + "e_entsize", + "e_phentsize", + "e_phnum", + "e_shentsize", + "e_shnum", + "e_shstrndx", + ] + mag_list = [self.elfhdr.ei_mag] + class_list = [byte2int(self.elfhdr.ei_class)] + data_list = [byte2int(self.elfhdr.ei_data)] + version_list = [byte2int(self.elfhdr.ei_version)] + osabi_list = [byte2int(self.elfhdr.ei_osabi)] + abiversion_list = [byte2int(self.elfhdr.ei_abiversion)] + pad_list = [byte2int(self.elfhdr.ei_pad)] + type_list = [byte2int(self.elfhdr.e_type)] + machine_list = [byte2int(self.elfhdr.e_machine)] + # e_version_list = [byte2int(self.elfhdr.e_version)] + entry_list = [byte2int(self.elfhdr.e_entry)] + phoff_list = [byte2int(self.elfhdr.e_phoff)] + shoff_list = [byte2int(self.elfhdr.e_shoff)] + flags_list = [byte2int(self.elfhdr.e_flags)] + ehsize_list = [byte2int(self.elfhdr.e_ehsize)] + phentsize_list = [byte2int(self.elfhdr.e_phentsize)] + phnum_list = [byte2int(self.elfhdr.e_phnum)] + shentsize_list = [byte2int(self.elfhdr.e_shentsize)] + shnum_list = [byte2int(self.elfhdr.e_shnum)] + shstrndx_list = [byte2int(self.elfhdr.e_shstrndx)] + lines = ffs( + 2, + header, + True, + mag_list, + class_list, + data_list, + version_list, + osabi_list, + abiversion_list, + pad_list, + type_list, + machine_list, + version_list, + entry_list, + phoff_list, + shoff_list, + flags_list, + ehsize_list, + phentsize_list, + phnum_list, + shentsize_list, + phnum_list, + shentsize_list, + shnum_list, + shstrndx_list, + ) + for line in lines: + print(line) + + def dump_phdrs(self): + header = [ + "p_type", + "p_flags", + "p_offset", + "p_vaddr", + "p_paddr", + "p_filesz", + "p_memsz", + "p_flags2", + "p_align", + ] + type_list = [get_ph_type(byte2int(phdr.p_type)) for phdr in self.phdr] + flags_list = [get_elf_seg_flag(byte2int(phdr.p_type)) for phdr in self.phdr] + offset_list = [byte2int(phdr.p_offset) for phdr in self.phdr] + vaddr_list = [byte2int(phdr.p_vaddr) for phdr in self.phdr] + paddr_list = [byte2int(phdr.p_paddr) for phdr in self.phdr] + filesz_list = [byte2int(phdr.p_filesz) for phdr in self.phdr] + memsz_list = [byte2int(phdr.p_memsz) for phdr in self.phdr] + flags2_list = [phdr.p_flags2 for phdr in self.phdr] + align_list = [byte2hex(phdr.p_align) for phdr in self.phdr] + + lines = ffs( + 2, + header, + True, + type_list, + flags_list, + offset_list, + vaddr_list, + paddr_list, + filesz_list, + memsz_list, + flags2_list, + align_list, + ) + for line in lines: + print(line) + + def dump_shdrs(self): + header = [ + "sh_name", + "sh_type", + "sh_flags", + "sh_addr", + "sh_offset", + "sh_size", + "sh_link", + "sh_info", + "sh_addralign", + "sh_entsize", + ] + name_list = [ + self.read_section_name(byte2int(shhdr.sh_name)) for shhdr in self.shhdr + ] + type_list = [ + get_section_type_string(byte2int(shhdr.sh_type)) for shhdr in self.shhdr + ] + flag_list = [byte2int(shhdr.sh_flags) for shhdr in self.shhdr] + addr_list = [byte2int(shhdr.sh_addr) for shhdr in self.shhdr] + offset_list = [byte2int(shhdr.sh_offset) for shhdr in self.shhdr] + size_list = [byte2int(shhdr.sh_size) for shhdr in self.shhdr] + link_list = [byte2int(shhdr.sh_link) for shhdr in self.shhdr] + info_list = [byte2int(shhdr.sh_info) for shhdr in self.shhdr] + allign_list = [byte2int(shhdr.sh_addralign) for shhdr in self.shhdr] + entsize_list = [byte2int(shhdr.sh_entsize) for shhdr in self.shhdr] + + lines = ffs( + 2, + header, + True, + name_list, + type_list, + flag_list, + addr_list, + offset_list, + size_list, + link_list, + info_list, + allign_list, + entsize_list, + ) + for line in lines: + print(line) + + def dump_symbol_tb(self, name, type): + for i in range(0, byte2int(self.elfhdr.e_shnum)): + if byte2int(self.shhdr[i].sh_type) == type: + if name == self.read_section_name(byte2int(self.shhdr[i].sh_name)): + print(Colors.BOLD + Colors.yellow + "STRING TABLE:" + Colors.ENDC) + self.so.seek(byte2int(self.shhdr[i].sh_offset), 0) + symbol_tb = self.so.read(byte2int(self.shhdr[i].sh_size)) + for byte in symbol_tb: + print(chr(byte), end="") + if chr(byte) == "\0": + print() + + def dump_st_entries(self): + header = [ + "name_index", + "name", + "value", + "size", + "info", + "other", + "shndx", + "bind", + "type", + ] + idx_list = [byte2int(entry.st_name) for entry in self.string_tb_e] + name_list = [ + "".join(self.get_st_entry_symbol_string(byte2int(entry.st_name), ".strtab")) + for entry in self.string_tb_e + ] + value_list = [byte2int(entry.st_value) for entry in self.string_tb_e] + size_list = [byte2int(entry.st_size) for entry in self.string_tb_e] + info_list = [byte2int(entry.st_info) for entry in self.string_tb_e] + other_list = [byte2int(entry.st_other) for entry in self.string_tb_e] + shndx_list = [byte2int(entry.st_shndx) for entry in self.string_tb_e] + bind_list = [ + get_elf_st_bind_string(entry.st_bind) for entry in self.string_tb_e + ] + type_list = [ + get_elf_st_type_string(entry.st_type) for entry in self.string_tb_e + ] + + lines = ffs( + 2, + header, + True, + idx_list, + name_list, + value_list, + size_list, + info_list, + other_list, + shndx_list, + bind_list, + type_list, + ) + for line in lines: + print(line) + + def dump_st_entries_dyn(self): + header = [ + "name_index", + "name", + "value", + "size", + "info", + "other", + "shndx", + "bind", + "type", + ] + idx_list = [byte2int(entry.st_name) for entry in self.string_tb_e_dyn] + name_list = [ + "".join(self.get_st_entry_symbol_string(byte2int(entry.st_name), ".dynstr")) + for entry in self.string_tb_e_dyn + ] + value_list = [byte2int(entry.st_value) for entry in self.string_tb_e_dyn] + size_list = [byte2int(entry.st_size) for entry in self.string_tb_e_dyn] + info_list = [byte2int(entry.st_info) for entry in self.string_tb_e_dyn] + other_list = [byte2int(entry.st_other) for entry in self.string_tb_e_dyn] + shndx_list = [byte2int(entry.st_shndx) for entry in self.string_tb_e_dyn] + bind_list = [ + get_elf_st_bind_string(entry.st_bind) for entry in self.string_tb_e_dyn + ] + type_list = [ + get_elf_st_type_string(entry.st_type) for entry in self.string_tb_e_dyn + ] + + lines = ffs( + 2, + header, + True, + idx_list, + name_list, + value_list, + size_list, + info_list, + other_list, + shndx_list, + bind_list, + type_list, + ) + for line in lines: + print(line) + + def dump_dyn_sec_ents(self, who): + header = ["type_string", "tag", "value", "value(hex)"] + tag_string_list = [entry["type_string"] for entry in who] + tag_list = [entry["tag"] for entry in who] + value_list = [entry["value"] for entry in who] + value_list_hex = [hex(entry["value"]) for entry in who] + lines = ffs( + 2, + header, + True, + tag_string_list, + tag_list, + value_list, + value_list_hex, + ) + for line in lines: + print(line) + + def dump_rela(self, to_dump): + header = ["r_offset", "r_info", "r_addend"] + 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) + for line in lines: + print(line) + + def dump_rel(self, to_dump): + 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) + for line in lines: + print(line) + + def get_st_entry_symbol_string(self, index, section_name): + symbol = [] + for i in range(0, byte2int(self.elfhdr.e_shnum)): + name = self.read_section_name(byte2int(self.shhdr[i].sh_name)) + if ( + byte2int(self.shhdr[i].sh_type) == sh_type_e.SHT_STRTAB + and name == section_name + ): + self.so.seek(byte2int(self.shhdr[i].sh_offset) + index, 0) + byte = self.so.read(1) + while chr(byte[0]) != "\0": + if chr(byte[0]) != "\0": + symbol.append(chr(byte[0])) + byte = self.so.read(1) + return symbol + + def get_symbol_string_table(self, offset): + symbol = [] + for i in range( + 0, + int.from_bytes(self.elfhdr.e_shnum, byteorder="little", signed=False), + ): + if ( + int.from_bytes(self.shhdr[i].sh_type, byteorder="little", signed=False) + == sh_type_e.SHT_STRTAB + ): + self.so.seek( + int.from_bytes( + self.shhdr[i].sh_offset, + byteorder="little", + signed=False, + ) + + offset + - 0, + 0, + ) + byte = self.so.read(1) + while chr(byte[0]) != "\0": + if chr(byte[0]) != "\0": + symbol.append(chr(byte[0])) + byte = self.so.read(1) + return symbol + + def dump_inst_sections(self): + indices = [] + for section in self.shhdr: + if ( + int.from_bytes(section.sh_flags, byteorder="little", signed=False) + & sh_flags_e.SHF_EXECINSTR + == sh_flags_e.SHF_EXECINSTR + ): + indices.append(int.from_bytes(section.sh_name, byteorder="little")) + return indices + + def pop_data_section(self): + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == ".data": + self.so.seek(byte2int(section.sh_offset)) + self.data_section = self.so.read(byte2int(section.sh_size)) + + def pop_text_section(self): + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == ".text": + self.so.seek(byte2int(section.sh_offset)) + self.text_section = self.so.read(byte2int(section.sh_size)) + + def pop_dynamic_entries(self, section_name, struct_to_pop): + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == section_name: + self.so.seek(byte2int(section.sh_offset)) + self.dyn_section = self.so.read(byte2int(section.sh_size)) + length = int(len(self.dyn_section)) + dummy = {} + if self.size == 64: + jmp_val = 8 + elif self.size == 32: + jmp_val = 4 + else: + jmp_val = 8 + print("self.size is not set for class " "elf.going with 8 as a default.") + for offset in range(0, length, jmp_val * 2): + tag_type = byte2int(self.dyn_section[offset : offset + jmp_val]) + dummy["tag"] = tag_type + value = byte2int( + self.dyn_section[offset + jmp_val : offset + (jmp_val * 2)] + ) + dummy["value"] = value + type_string = get_ph_dynamic_ent_tag_type(tag_type) + dummy["type_string"] = type_string + type_string = str() + struct_to_pop.append(dummy) + dummy = {} + + def pop_rela(self, section_name, section_whole, to_pop): + size = int() + entsize = int() + dummy = {} + step = int() + if self.size == 64: + step = 8 + if self.size == 32: + step = 4 + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == section_name: + self.so.seek(byte2int(section.sh_offset)) + section_whole = self.so.read(byte2int(section.sh_size)) + size = byte2int(section.sh_size) + entsize = byte2int(section.sh_entsize) + if entsize != 0: + for i in range(0, int(size / entsize)): + dummy["r_offset"] = byte2int( + section_whole[i * entsize : i * entsize + step] + ) + dummy["r_info"] = byte2int( + section_whole[i * entsize + step : i * entsize + (step * 2)] + ) + dummy["r_addend"] = byte2int( + section_whole[i * entsize + (step * 2) : i * entsize + (step * 3)], + sign=True, + ) + to_pop.append(dummy) + dummy = {} + + def pop_rel(self, section_name, section_whole, to_pop): + size = int() + entsize = int() + dummy = {} + step = int() + if self.size == 64: + step = 8 + if self.size == 32: + step = 4 + for section in self.shhdr: + name = self.read_section_name(byte2int(section.sh_name)) + if name == section_name: + self.so.seek(byte2int(section.sh_offset)) + section_whole = self.so.read(byte2int(section.sh_size)) + size = byte2int(section.sh_size) + entsize = byte2int(section.sh_entsize) + for i in range(0, int(size / entsize)): + dummy["r_offset"] = byte2int( + section_whole[i * entsize : i * entsize + step] + ) + dummy["r_info"] = byte2int( + section_whole[i * entsize + step : i * entsize + (step * 2)] + ) + to_pop.append(dummy) + dummy = {} + + # FIXME-ELF64 only + def pop_got(self): + for shhdr in self.shhdr: + name = self.read_section_name(byte2int(shhdr.sh_name)) + if name == ".got": + self.so.seek(byte2int(shhdr.sh_offset)) + self.got = self.so.read(byte2int(shhdr.sh_size)) + self.so.seek(byte2int(shhdr.sh_offset)) + for i in range(0, int(byte2int(shhdr.sh_size) / 8)): + self.got_ents.append(byte2int(self.so.read(8))) + + # FIXME-ELF64 only + def pop_got_plt(self): + for shhdr in self.shhdr: + name = self.read_section_name(byte2int(shhdr.sh_name)) + if name == ".got.plt": + self.so.seek(byte2int(shhdr.sh_offset)) + self.got_plt = self.so.read(byte2int(shhdr.sh_size)) + self.so.seek(byte2int(shhdr.sh_offset)) + for i in range(0, int(byte2int(shhdr.sh_size) / 8)): + self.got_plt_ents.append(byte2int(self.so.read(8))) + + def dump_got(self): + header = ["value"] + value_list = [entry for entry in self.got_ents] + lines = ffs(2, header, True, 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) + for line in lines: + print(line) + + +class obj_loader: + def __init__(self, bytes): + self.memory = bytes() + + def load(self, obj): + for byte in obj: + self.memory.append(byte) + + +def ch_so_to_exe(path): + so = open(path, "r+b") + so.seek(16) + so.write(bytes([2])) + print(Colors.purple + "changed so to exe" + Colors.ENDC) + so.close + + +def ch_exe_to_so(path): + so = open(path, "r+b") + so.seek(16) + so.write(bytes([3])) + print(Colors.purple + "changed exe to so" + Colors.ENDC) + 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): + so = openSO_r(path) + self.elf = ELF(so) + self.elf.init(64) + # shutil.copyfile(path, "/tmp/exe") + self.magic_section_number = int() + self.new_name = new_name + self.shdr_new_size = [] + self.shdr_new_offset = [] + + def fix_section_offsets(self, section_name, new_size: int, new_section: bytes): + # file_w = open(self.new_name, "wb") + # magic_number = int() + for i in range(0, byte2int(self.elf.elfhdr.e_shnum)): + name = self.elf.read_section_name(byte2int(self.elf.shhdr[i].sh_name)) + if section_name == name: + self.magic_section_number = i + print(self.magic_section_number) + + # copy the sections before magic_number + # write in the new section + # fix section headers + + end = int() + for i in range(0, byte2int(self.elf.elfhdr.e_shnum)): + if i > self.magic_section_number: + extra_chunk = end % byte2int(self.elf.shhdr[i].sh_addralign) + missing_chunk = byte2int(self.elf.shhdr[i].sh_addralign) - extra_chunk + assert missing_chunk > 0, "missing chunk is negative" + self.shdr_new_size.append(byte2int(self.elf.shhdr[i].sh_size)) + self.shdr_new_offset.append( + end + missing_chunk % byte2int(self.elf.shhdr[i].sh_addralign) + ) + end = self.shdr_new_offset[-1] + self.shdr_new_size[-1] + + elif i < self.magic_section_number: + self.shdr_new_size.append(byte2int(self.elf.shhdr[i].sh_size)) + self.shdr_new_offset.append(byte2int(self.elf.shhdr[i].sh_offset)) + elif i == self.magic_section_number: + self.shdr_new_size.append(new_size) + self.shdr_new_offset.append(byte2int(self.elf.shhdr[i].sh_offset)) + end = byte2int(self.elf.shhdr[i].sh_offset) + new_size + for size in self.shdr_new_size: + print(repr(i) + " new size is " + repr(size)) + for offset in self.shdr_new_offset: + print(repr(i) + " new offset is " + repr(offset)) + + +def main() -> None: + argparser = CLIArgParser() + so = openSO_r(argparser.args.obj) + elf = ELF(so) + elf.init(64) + if argparser.args.header: + elf.dump_header() + elif argparser.args.symboltable: + elf.dump_symbol_tb(".strtab", sh_type_e.SHT_STRTAB) + elf.dump_symbol_tb(".dynstr", sh_type_e.SHT_STRTAB) + elif argparser.args.phdrs: + elf.dump_phdrs() + elif argparser.args.shdrs: + elf.dump_shdrs() + elif argparser.args.symbolindex: + elf.dump_symbol_idx() + elif argparser.args.stentries: + elf.dump_st_entries() + elif argparser.args.objcode: + elf.dump_funcs(True) + elif argparser.args.funcs: + elf.dump_symbol_string(ELF_ST_TYPE.STT_FUNC, True) + elif argparser.args.objs: + elf.dump_symbol_string(ELF_ST_TYPE.STT_OBJECT, True) + elif argparser.args.dynsym: + elf.dump_st_entries_dyn() + elif argparser.args.dlpath: + elf.dump_section(".interp", True) + elif argparser.args.section: + elf.dump_section(argparser.args.section, True) + elif argparser.args.test2: + rewriter = Rewriter(argparser.args.obj, "new_exe") + new_text = bytes() + rewriter.fix_section_offsets(".text", 1000, new_text) + elif argparser.args.dumpfunc: + counter = 0 + for name in elf.dump_symbol_string(ELF_ST_TYPE.STT_FUNC, False): + if name == argparser.args.dumpfunc: + print(Colors.red + Colors.BOLD + name + Colors.ENDC) + code = elf.dump_funcs(False)[counter] + print(code) + counter += 1 + elif argparser.args.dumpfuncasm: + counter = 0 + hit = False + for name in elf.dump_symbol_string(ELF_ST_TYPE.STT_FUNC, False): + if name == argparser.args.dumpfuncasm: + code = elf.dump_funcs(False)[counter] + hit = True + counter += 1 + if hit: + md = Cs(CS_ARCH_X86, CS_MODE_64) + for i in md.disasm(bytes(code), 0x0): + print(hex(i.address).ljust(7), i.mnemonic.ljust(7), i.op_str) + elif argparser.args.phdynent: + elf.dump_ph_dyn_entries() + elif argparser.args.disass: + for section in elf.shhdr: + name = elf.read_section_name(byte2int(section.sh_name)) + if name == argparser.args.disass: + if byte2int(section.sh_flags) & 0x4 != 0x04: + print( + "section is not executable...but, " + "since you asked, here you go..." + ) + elf.so.seek(byte2int(section.sh_offset)) + code = elf.so.read(byte2int(section.sh_size)) + md = Cs(CS_ARCH_X86, CS_MODE_64) + for i in md.disasm(bytes(code), 0x0): + print(hex(i.address).ljust(7), i.mnemonic.ljust(7), i.op_str) + elif argparser.args.disassp is not 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...") + header_offset = elf.phdr[index].p_offset + header_size = elf.phdr[index].p_filesz + elf.so.seek(byte2int(header_offset)) + code = elf.so.read(byte2int(header_size)) + md = Cs(CS_ARCH_X86, CS_MODE_64) + for i in md.disasm(bytes(code), 0x0): + print(hex(i.address).ljust(7), i.mnemonic.ljust(7), i.op_str) + elif argparser.args.textasm: + md = Cs(CS_ARCH_X86, CS_MODE_64) + for i in md.disasm(bytes(elf.text_section), 0x0): + print(hex(i.address).ljust(7), i.mnemonic.ljust(7), i.op_str) + elif argparser.args.dynsecents: + elf.dump_dyn_sec_ents(elf.dyn_section_ents) + elif argparser.args.reladyn: + elf.dump_rela(elf.rela_dyn_ents) + elif argparser.args.relaplt: + elf.dump_rela(elf.rela_plt_ents) + elif argparser.args.got: + elf.pop_got() + elf.dump_got() + elif argparser.args.gotplt: + elf.pop_got_plt() + elf.dump_got_plt() + elif argparser.args.listdso: + os.environ["LD_TRACE_LOADED_OBJECTS"] = "1" + os.environ["LD_WARN"] = "yes" + os.environ["LD_BIND_NOW"] = "yes" + # os.environ["LD_VERBOSE"] = "yes" + # os.environ["LD_DEBUG"] = "all" + rtldlist = [ + "/usr/lib/ld-linux.so.2", + "/usr/lib64/ld-linux-x86-64.so.2", + "/usr/libx32/ld-linux-x32.so.2", + ] + for rtld in rtldlist: + if os.path.exists(rtld): + result = subprocess.run( + [rtld, argparser.args.obj], + capture_output=True, + ) + print(result.stdout.decode("utf-8")) + break + else: + print("why even bother if you were not gonna type anythng decent in?") + + +if __name__ == "__main__": + main() |