From 143898301ae86e2cca2ade4088fe63a9b7d84331 Mon Sep 17 00:00:00 2001 From: terminaldweller Date: Wed, 8 Nov 2023 20:16:43 -0500 Subject: added to pypi --- README.md | 6 + delf.py | 27 - load.py | 2448 -------------------------------------------------------- poetry.lock | 543 +++++++++++++ pyproject.toml | 23 +- src/delf.py | 2347 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 2916 insertions(+), 2478 deletions(-) delete mode 100755 delf.py delete mode 100755 load.py create mode 100644 poetry.lock create mode 100755 src/delf.py diff --git a/README.md b/README.md index 9364cbf..691a796 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ # delf delf is an ELF dump tool.
+## Installation +You will also need to have `libcapstone` installed. +```sh +pip install delf +``` + ## Requirements You need python3 and `capstone`. If you don't have capstone you can get it by:
```bash diff --git a/delf.py b/delf.py deleted file mode 100755 index 27b574f..0000000 --- a/delf.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python3 - -import code -import signal -from load import premain, CLIArgParser, SigHandler_SIGINT - - -def main(): - argparser = CLIArgParser() - if argparser.args.dbg: - try: - premain(argparser) - except Exception as e: - print(e.__doc__) - if e.message: - print(e.message) - signal.signal(signal.SIGINT, SigHandler_SIGINT) - variables = globals().copy() - variables.update(locals()) - shell = code.InteractiveConsole(variables) - shell.interact(banner="DELF REPL") - else: - premain(argparser) - - -if __name__ == "__main__": - main() diff --git a/load.py b/load.py deleted file mode 100755 index 091926d..0000000 --- a/load.py +++ /dev/null @@ -1,2448 +0,0 @@ -#!/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 signal -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 ExceptionHandler(object): - def __init__(self, globals, locals): - self.variables = globals().copy() - self.variables.update(locals()) - self.shell = code.InteractiveConsole() - - -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") - elif 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 premain(argparser): - 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?") - - -def main(): - argparser = CLIArgParser() - if argparser.args.dbg: - try: - premain(argparser) - except Exception as e: - print(e.__doc__) - if e.message: - print(e.message) - signal.signal(signal.SIGINT, SigHandler_SIGINT) - variables = globals().copy() - variables.update(locals()) - shell = code.InteractiveConsole(variables) - shell.interact(banner="DELF REPL") - else: - premain(argparser) - - -if __name__ == "__main__": - main() diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..e00611d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,543 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "astroid" +version = "3.0.1" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "astroid-3.0.1-py3-none-any.whl", hash = "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca"}, + {file = "astroid-3.0.1.tar.gz", hash = "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "bandit" +version = "1.7.5" +description = "Security oriented static analyser for python code." +optional = false +python-versions = ">=3.7" +files = [ + {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, + {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +rich = "*" +stevedore = ">=1.20.0" + +[package.extras] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0)"] +yaml = ["PyYAML"] + +[[package]] +name = "black" +version = "23.11.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"}, + {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"}, + {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"}, + {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"}, + {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"}, + {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"}, + {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"}, + {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"}, + {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"}, + {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"}, + {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"}, + {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"}, + {file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"}, + {file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"}, + {file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"}, + {file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"}, + {file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"}, + {file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "capstone" +version = "4.0.2" +description = "Capstone disassembly engine" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "capstone-4.0.2-py2.py3-none-manylinux1_i686.whl", hash = "sha256:da442f979414cf27e4621e70e835880878c858ea438c4f0e957e132593579e37"}, + {file = "capstone-4.0.2-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:9d1a9096c5f875b11290317722ed44bb6e7c52e50cc79d791f142bce968c49aa"}, + {file = "capstone-4.0.2-py2.py3-none-win32.whl", hash = "sha256:c3d9b443d1adb40ee2d9a4e7341169b76476ddcf3a54c03793b16cdc7cd35c5a"}, + {file = "capstone-4.0.2-py2.py3-none-win_amd64.whl", hash = "sha256:0d65ffe8620920976ceadedc769f22318f6f150a592368d8a735612367ac8a1a"}, + {file = "capstone-4.0.2.tar.gz", hash = "sha256:2842913092c9b69fd903744bc1b87488e1451625460baac173056e1808ec1c66"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.3.7" +description = "serialize all of Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] + +[[package]] +name = "gitdb" +version = "4.0.11" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, + {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.40" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, + {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "pbr" +version = "6.0.0" +description = "Python Build Reasonableness" +optional = false +python-versions = ">=2.6" +files = [ + {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"}, + {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"}, +] + +[[package]] +name = "platformdirs" +version = "3.11.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pylint" +version = "3.0.2" +description = "python code static checker" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "pylint-3.0.2-py3-none-any.whl", hash = "sha256:60ed5f3a9ff8b61839ff0348b3624ceeb9e6c2a92c514d81c9cc273da3b6bcda"}, + {file = "pylint-3.0.2.tar.gz", hash = "sha256:0d4c286ef6d2f66c8bfb527a7f8a629009e42c99707dec821a03e1b51a4c1496"}, +] + +[package.dependencies] +astroid = ">=3.0.1,<=3.1.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, +] +isort = ">=4.2.5,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "rich" +version = "13.6.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.6.0-py3-none-any.whl", hash = "sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245"}, + {file = "rich-13.6.0.tar.gz", hash = "sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "ruff" +version = "0.1.5" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.5-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:32d47fc69261c21a4c48916f16ca272bf2f273eb635d91c65d5cd548bf1f3d96"}, + {file = "ruff-0.1.5-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:171276c1df6c07fa0597fb946139ced1c2978f4f0b8254f201281729981f3c17"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ef33cd0bb7316ca65649fc748acc1406dfa4da96a3d0cde6d52f2e866c7b39"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2c205827b3f8c13b4a432e9585750b93fd907986fe1aec62b2a02cf4401eee6"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb408e3a2ad8f6881d0f2e7ad70cddb3ed9f200eb3517a91a245bbe27101d379"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f20dc5e5905ddb407060ca27267c7174f532375c08076d1a953cf7bb016f5a24"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aafb9d2b671ed934998e881e2c0f5845a4295e84e719359c71c39a5363cccc91"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4894dddb476597a0ba4473d72a23151b8b3b0b5f958f2cf4d3f1c572cdb7af7"}, + {file = "ruff-0.1.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00a7ec893f665ed60008c70fe9eeb58d210e6b4d83ec6654a9904871f982a2a"}, + {file = "ruff-0.1.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8c11206b47f283cbda399a654fd0178d7a389e631f19f51da15cbe631480c5b"}, + {file = "ruff-0.1.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fa29e67b3284b9a79b1a85ee66e293a94ac6b7bb068b307a8a373c3d343aa8ec"}, + {file = "ruff-0.1.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9b97fd6da44d6cceb188147b68db69a5741fbc736465b5cea3928fdac0bc1aeb"}, + {file = "ruff-0.1.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:721f4b9d3b4161df8dc9f09aa8562e39d14e55a4dbaa451a8e55bdc9590e20f4"}, + {file = "ruff-0.1.5-py3-none-win32.whl", hash = "sha256:f80c73bba6bc69e4fdc73b3991db0b546ce641bdcd5b07210b8ad6f64c79f1ab"}, + {file = "ruff-0.1.5-py3-none-win_amd64.whl", hash = "sha256:c21fe20ee7d76206d290a76271c1af7a5096bc4c73ab9383ed2ad35f852a0087"}, + {file = "ruff-0.1.5-py3-none-win_arm64.whl", hash = "sha256:82bfcb9927e88c1ed50f49ac6c9728dab3ea451212693fe40d08d314663e412f"}, + {file = "ruff-0.1.5.tar.gz", hash = "sha256:5cbec0ef2ae1748fb194f420fb03fb2c25c3258c86129af7172ff8f198f125ab"}, +] + +[[package]] +name = "smmap" +version = "5.0.1" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +files = [ + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, +] + +[[package]] +name = "stevedore" +version = "5.1.0" +description = "Manage dynamic plugins for Python applications" +optional = false +python-versions = ">=3.8" +files = [ + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, +] + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tomlkit" +version = "0.12.2" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.12.2-py3-none-any.whl", hash = "sha256:eeea7ac7563faeab0a1ed8fe12c2e5a51c61f933f2502f7e9db0241a65163ad0"}, + {file = "tomlkit-0.12.2.tar.gz", hash = "sha256:df32fab589a81f0d7dc525a4267b6d7a64ee99619cbd1eeb0fae32c1dd426977"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "971a384728657803a76d6ad6fe551d3541259df1d3ea8adb9dc19daa825c8222" diff --git a/pyproject.toml b/pyproject.toml index 9b8f034..e71a89e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,33 @@ [tool.poetry] name = "delf" -version = "0.1.0" -description = "" -authors = ["terminaldweller "] +version = "0.1.2" +description = "yet another elf dump tool" +authors = ["terminaldweller "] license = "GPL-3.0" +keywords = ["elf", "capstone"] +classifiers = [ + "Environment :: Console", +] +include = [ + "LICENSE", +] [tool.poetry.dependencies] python = "^3.8" capstone = "^4.0.2" +[tool.poetry.scripts] +delf = "delf:main" + [tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +mypy = "^1.6.1" +pylint = "^3.0.2" +bandit = "^1.7.5" +ruff = "^0.1.1" +black = "^23.10.0" + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" 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() -- cgit v1.2.3