Simplify ctypes and ELF logic for choosing endianness / architecture

pull/162/head
Zach Riggle 9 years ago
parent 8110dacacb
commit 9d19daaea3

@ -13,48 +13,23 @@ from __future__ import print_function
from __future__ import unicode_literals
import ctypes
import struct
import six
import sys
import pwndbg.arch
import pwndbg.events
import pwndbg.memory
endian = {'big': '>', 'little': '<'}
def getattribute(self, attrname):
value = super(EndianAwareStructure, self).__getattribute__(attrname)
if pwndbg.arch.endian == pwndbg.arch.native_endian:
return value
if attrname == '_fields_':
return value
for field in self._fields_:
name = field[0]
typ = field[1]
if name != attrname:
continue
if isinstance(typ._type_, six.string_types):
fmt_orig = typ._type_
fmt_endian = endian[pwndbg.arch.endian] + fmt_orig
value = struct.pack(fmt_orig, value)
value = struct.unpack(fmt_endian, value)[0]
return value
module = sys.modules[__name__]
@pwndbg.events.start
@pwndbg.events.new_objfile
def update():
global module
class EndianAwareStructure(ctypes.Structure):
def __getattribute__(self, attrname):
return getattribute(self, attrname)
if pwndbg.arch.endian == 'little':
Structure = ctypes.LittleEndianStructure
else:
Structure = ctypes.BigEndianStructure
class EndianAwareUnion(ctypes.Union):
def __getattribute__(self, attrname):
return getattribute(self, attrname)
module.__dict__.update(locals())
Union = EndianAwareUnion
Structure = EndianAwareStructure
update()

@ -20,13 +20,13 @@ import tempfile
import gdb
import pwndbg.auxv
import pwndbg.elftypes as E
import pwndbg.events
import pwndbg.info
import pwndbg.memoize
import pwndbg.memory
import pwndbg.proc
import pwndbg.stack
from pwndbg.elftypes import *
# ELF constants
PF_X, PF_W, PF_R = 1,2,4
@ -128,8 +128,7 @@ def get_ehdr(pointer):
ei_class = pwndbg.memory.byte(base+4)
# Find out where the section headers start
EhdrType = { 1: Elf32_Ehdr, 2: Elf64_Ehdr }[ei_class]
Elfhdr = read(EhdrType, base)
Elfhdr = read(E.Ehdr, base)
return ei_class, Elfhdr
def get_phdrs(pointer):
@ -143,13 +142,11 @@ def get_phdrs(pointer):
if Elfhdr is None:
return (0, 0, None)
PhdrType = { 1: Elf32_Phdr, 2: Elf64_Phdr }[ei_class]
phnum = Elfhdr.e_phnum
phoff = Elfhdr.e_phoff
phentsize = Elfhdr.e_phentsize
x = (phnum, phentsize, read(PhdrType, Elfhdr.address + phoff))
x = (phnum, phentsize, read(E.Phdr, Elfhdr.address + phoff))
return x
def iter_phdrs(ehdr):

@ -35,6 +35,8 @@ from __future__ import print_function
from __future__ import unicode_literals
import ctypes
import six
import sys
import pwndbg.arch
import pwndbg.ctypes
@ -312,245 +314,22 @@ class Elf64_Phdr(pwndbg.ctypes.Structure):
("p_memsz", Elf64_Xword),
("p_align", Elf64_Xword),]
class Elf32_Shdr(pwndbg.ctypes.Structure):
_fields_ = [("sh_name", Elf32_Word),
("sh_type", Elf32_Word),
("sh_flags", Elf32_Word),
("sh_addr", Elf32_Addr),
("sh_offset", Elf32_Off),
("sh_size", Elf32_Word),
("sh_link", Elf32_Word),
("sh_info", Elf32_Word),
("sh_addralign", Elf32_Word),
("sh_entsize", Elf32_Word),]
module = sys.modules[__name__]
class Elf64_Shdr(pwndbg.ctypes.Structure):
_fields_ = [("sh_name", Elf64_Word),
("sh_type", Elf64_Word),
("sh_flags", Elf64_Xword),
("sh_addr", Elf64_Addr),
("sh_offset", Elf64_Off),
("sh_size", Elf64_Xword),
("sh_link", Elf64_Word),
("sh_info", Elf64_Word),
("sh_addralign", Elf64_Xword),
("sh_entsize", Elf64_Xword),]
@pwndbg.events.start
@pwndbg.events.new_objfile
def reload():
six.moves.reload_module(module)
module.update()
class _U__Elf32_Dyn(pwndbg.ctypes.Union):
_fields_ = [("d_val", Elf32_Sword),
("d_ptr", Elf32_Addr),]
def update():
if pwndbg.arch.ptrsize == 4:
Ehdr = Elf32_Ehdr
Phdr = Elf32_Phdr
else:
Ehdr = Elf64_Ehdr
Phdr = Elf64_Phdr
class Elf32_Dyn(pwndbg.ctypes.Structure):
_anonymous_ = ("d_un",)
_fields_ = [("d_tag", Elf32_Sword),
("d_un", _U__Elf32_Dyn),]
module.__dict__.update(locals())
class _U__Elf64_Dyn(pwndbg.ctypes.Union):
_fields_ = [("d_val", Elf64_Xword),
("d_ptr", Elf64_Addr),]
class Elf64_Dyn(pwndbg.ctypes.Structure):
_anonymous_ = ("d_un",)
_fields_ = [("d_tag", Elf64_Sxword),
("d_un", _U__Elf64_Dyn),]
class Elf32_Sym(pwndbg.ctypes.Structure):
_fields_ = [("st_name", Elf32_Word),
("st_value", Elf32_Addr),
("st_size", Elf32_Word),
("st_info", ctypes.c_ubyte),
("st_other", ctypes.c_ubyte),
("st_shndx", Elf32_Half),]
class Elf64_Sym(pwndbg.ctypes.Structure):
_fields_ = [("st_name", Elf64_Word),
("st_info", ctypes.c_ubyte),
("st_other", ctypes.c_ubyte),
("st_shndx", Elf64_Half),
("st_value", Elf64_Addr),
("st_size", Elf64_Xword),]
class Elf32_Link_Map(pwndbg.ctypes.Structure):
_fields_ = [("l_addr", Elf32_Addr),
("l_name", Elf32_Addr),
("l_ld", Elf32_Addr),
("l_next", Elf32_Addr),
("l_prev", Elf32_Addr),]
class Elf64_Link_Map(pwndbg.ctypes.Structure):
_fields_ = [("l_addr", Elf64_Addr),
("l_name", Elf64_Addr),
("l_ld", Elf64_Addr),
("l_next", Elf64_Addr),
("l_prev", Elf64_Addr),]
#
# Additions below here by Zach Riggle for pwntool
#
# See the routine elf_machine_runtime_setup for the relevant architecture
# for the layout of the GOT.
#
# https://chromium.googlesource.com/chromiumos/third_party/glibc/+/master/sysdeps/x86/dl-machine.h
# https://chromium.googlesource.com/chromiumos/third_party/glibc/+/master/sysdeps/x86_64/dl-machine.h
# https://fossies.org/dox/glibc-2.20/aarch64_2dl-machine_8h_source.html#l00074
# https://fossies.org/dox/glibc-2.20/powerpc32_2dl-machine_8c_source.html#l00203
#
# For now, these are defined for x86 and x64
#
char = ctypes.c_char
byte = ctypes.c_byte
class Elf_eident(pwndbg.ctypes.Structure):
_fields_ = [('EI_MAG',char*4),
('EI_CLASS',byte),
('EI_DATA',byte),
('EI_VERSION',byte),
('EI_OSABI',byte),
('EI_ABIVERSION',byte),
('EI_PAD', byte*(16-9))]
class Elf_i386_GOT(pwndbg.ctypes.Structure):
_fields_ = [("jmp", Elf32_Addr),
("linkmap", Elf32_Addr),
("dl_runtime_resolve", Elf32_Addr)]
class Elf_x86_64_GOT(pwndbg.ctypes.Structure):
_fields_ = [("jmp", Elf64_Addr),
("linkmap", Elf64_Addr),
("dl_runtime_resolve", Elf64_Addr)]
class Elf_HashTable(pwndbg.ctypes.Structure):
_fields_ = [('nbucket', Elf32_Word),
('nchain', Elf32_Word),]
# ('bucket', nbucket * Elf32_Word),
# ('chain', nchain * Elf32_Word)]
# Docs: http://dyncall.org/svn/dyncall/tags/r0.4/dyncall/dynload/dynload_syms_elf.c
class GNU_HASH(pwndbg.ctypes.Structure):
_fields_ = [('nbuckets', Elf32_Word),
('symndx', Elf32_Word),
('maskwords', Elf32_Word),
('shift2', Elf32_Word)]
class Elf32_r_debug(pwndbg.ctypes.Structure):
_fields_ = [('r_version', Elf32_Word),
('r_map', Elf32_Addr)]
class Elf64_r_debug(pwndbg.ctypes.Structure):
_fields_ = [('r_version', Elf32_Word),
('r_map', Elf64_Addr)]
constants.DT_GNU_HASH = 0x6ffffef5
constants.STN_UNDEF = 0
pid_t = ctypes.c_uint32
class elf_siginfo(pwndbg.ctypes.Structure):
_fields_ = [('si_signo', ctypes.c_int32),
('si_code', ctypes.c_int32),
('si_errno', ctypes.c_int32)]
class timeval32(pwndbg.ctypes.Structure):
_fields_ = [('tv_sec', ctypes.c_int32),
('tv_usec', ctypes.c_int32),]
class timeval64(pwndbg.ctypes.Structure):
_fields_ = [('tv_sec', ctypes.c_int64),
('tv_usec', ctypes.c_int64),]
# See linux/elfcore.h
def generate_prstatus_common(size, regtype):
c_long = ctypes.c_uint32 if size==32 else ctypes.c_uint64
timeval = timeval32 if size==32 else timeval64
return [('pr_info', elf_siginfo),
('pr_cursig', ctypes.c_int16),
('pr_sigpend', c_long),
('pr_sighold', c_long),
('pr_pid', pid_t),
('pr_ppid', pid_t),
('pr_pgrp', pid_t),
('pr_sid', pid_t),
('pr_utime', timeval),
('pr_stime', timeval),
('pr_cutime', timeval),
('pr_cstime', timeval),
('pr_reg', regtype),
('pr_fpvalid', ctypes.c_uint32)
]
# See i386-linux-gnu/sys/user.h
class user_regs_struct_i386(pwndbg.ctypes.Structure):
_fields_ = [(name, ctypes.c_uint32) for name in [
'ebx',
'ecx',
'edx',
'esi',
'edi',
'ebp',
'eax',
'xds',
'xes',
'xfs',
'xgs',
'orig_eax',
'eip',
'xcs',
'eflags',
'esp',
'xss',
]]
assert ctypes.sizeof(user_regs_struct_i386) == 0x44, ctypes.sizeof(user_regs_struct_i386)
# See i386-linux-gnu/sys/user.h
class user_regs_struct_amd64(pwndbg.ctypes.Structure):
_fields_ = [(name, ctypes.c_uint64) for name in [
'r15',
'r14',
'r13',
'r12',
'rbp',
'rbx',
'r11',
'r10',
'r9',
'r8',
'rax',
'rcx',
'rdx',
'rsi',
'rdi',
'orig_rax',
'rip',
'cs',
'eflags',
'rsp',
'ss',
'fs_base',
'gs_base',
'ds',
'es',
'fs',
'gs',
]]
assert ctypes.sizeof(user_regs_struct_amd64) == 0xd8
class elf_prstatus_i386(pwndbg.ctypes.Structure):
_fields_ = generate_prstatus_common(32, user_regs_struct_i386)
assert ctypes.sizeof(elf_prstatus_i386) == 0x90
class elf_prstatus_amd64(pwndbg.ctypes.Structure):
_fields_ = generate_prstatus_common(64, user_regs_struct_amd64)
assert ctypes.sizeof(elf_prstatus_amd64) == 0x150
class Elf32_auxv_t(pwndbg.ctypes.Structure):
_fields_ = [('a_type', ctypes.c_uint32),
('a_val', ctypes.c_uint32),]
class Elf64_auxv_t(pwndbg.ctypes.Structure):
_fields_ = [('a_type', ctypes.c_uint64),
('a_val', ctypes.c_uint64),]
update()

Loading…
Cancel
Save