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