#!/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()