Skip to content

Instantly share code, notes, and snippets.

@techvoltage
Created April 14, 2017 12:45
Show Gist options
  • Save techvoltage/f5f61564b8b95b6ecad1cf6cdf6351ee to your computer and use it in GitHub Desktop.
Save techvoltage/f5f61564b8b95b6ecad1cf6cdf6351ee to your computer and use it in GitHub Desktop.
Finds the Function's Load Address
#!/usr/bin/env python
#Taken from http://uaf.io/exploitation/misc/2016/04/02/Finding-Functions.html
from pwn import *
import sys, os
wordSz = 4
hwordSz = 2
bits = 32
PIE = 0
def leak(address, size):
with open('/proc/%s/mem' % pid) as mem:
mem.seek(address)
return mem.read(size)
def findModuleBase(pid, mem):
name = os.readlink('/proc/%s/exe' % pid)
with open('/proc/%s/maps' % pid) as maps:
for line in maps:
if name in line:
addr = int(line.split('-')[0], 16)
mem.seek(addr)
if mem.read(4) == "\x7fELF":
bitFormat = u8(leak(addr + 4, 1))
if bitFormat == 2:
global wordSz
global hwordSz
global bits
wordSz = 8
hwordSz = 4
bits = 64
return addr
log.failure("Module's base address not found.")
sys.exit(1)
def findIfPIE(addr):
e_type = u8(leak(addr + 0x10, 1))
if e_type == 3:
return addr
else:
return 0
def findPhdr(addr):
if bits == 32:
e_phoff = u32(leak(addr + 0x1c, wordSz).ljust(4, '\0'))
else:
e_phoff = u64(leak(addr + 0x20, wordSz).ljust(8, '\0'))
return e_phoff + addr
def findDynamic(Elf32_Phdr, moduleBase, bitSz):
if bitSz == 32:
i = -32
p_type = 0
while p_type != 2:
i += 32
p_type = u32(leak(Elf32_Phdr + i, wordSz).ljust(4, '\0'))
return u32(leak(Elf32_Phdr + i + 8, wordSz).ljust(4, '\0')) + PIE
else:
i = -56
p_type = 0
while p_type != 2:
i += 56
p_type = u64(leak(Elf32_Phdr + i, hwordSz).ljust(8, '\0'))
return u64(leak(Elf32_Phdr + i + 16, wordSz).ljust(8, '\0')) + PIE
def findDynTable(Elf32_Dyn, table, bitSz):
p_val = 0
if bitSz == 32:
i = -8
while p_val != table:
i += 8
p_val = u32(leak(Elf32_Dyn + i, wordSz).ljust(4, '\0'))
return u32(leak(Elf32_Dyn + i + 4, wordSz).ljust(4, '\0'))
else:
i = -16
while p_val != table:
i += 16
p_val = u64(leak(Elf32_Dyn + i, wordSz).ljust(8, '\0'))
return u64(leak(Elf32_Dyn + i + 8, wordSz).ljust(8, '\0'))
def getPtr(addr, bitSz):
with open('/proc/%s/maps' % sys.argv[1]) as maps:
for line in maps:
if 'libc-' in line and 'r-x' in line:
libc = line.split(' ')[0].split('-')
i = 3
while True:
if bitSz == 32:
gotPtr = u32(leak(addr + i*4, wordSz).ljust(4, '\0'))
else:
gotPtr = u64(leak(addr + i*8, wordSz).ljust(8, '\0'))
if (gotPtr > int(libc[0], 16)) and (gotPtr < int(libc[1], 16)):
return gotPtr
else:
i += 1
continue
def findLibcBase(ptr):
ptr &= 0xfffffffffffff000
while leak(ptr, 4) != "\x7fELF":
ptr -= 0x1000
return ptr
def findSymbol(strtab, symtab, symbol, bitSz):
if bitSz == 32:
i = -16
while True:
i += 16
st_name = u32(leak(symtab + i, 2).ljust(4, '\0'))
if leak( strtab + st_name, len(symbol)+1 ).lower() == (symbol.lower() + '\0'):
return u32(leak(symtab + i + 4, 4).ljust(4, '\0'))
else:
i = -24
while True:
i += 24
st_name = u64(leak(symtab + i, 4).ljust(8, '\0'))
if leak( strtab + st_name, len(symbol)).lower() == (symbol.lower()):
return u64(leak(symtab + i + 8, 8).ljust(8, '\0'))
def lookup(pid, symbol):
with open('/proc/%s/mem' % pid) as mem:
moduleBase = findModuleBase(pid, mem)
log.info("Module's base address:................. " + hex(moduleBase))
global PIE
PIE = findIfPIE(moduleBase)
if PIE:
log.info("Binary is PIE enabled.")
else:
log.info("Binary is not PIE enabled.")
modulePhdr = findPhdr(moduleBase)
log.info("Module's Program Header:............... " + hex(modulePhdr))
moduleDynamic = findDynamic(modulePhdr, moduleBase, bits)
log.info("Module's _DYNAMIC Section:............. " + hex(moduleDynamic))
moduleGot = findDynTable(moduleDynamic, 3, bits)
log.info("Module's GOT:.......................... " + hex(moduleGot))
libcPtr = getPtr(moduleGot, bits)
log.info("Pointer from GOT to a function in libc: " + hex(libcPtr))
libcBase = findLibcBase(libcPtr)
log.info("Libc's base address:................... " + hex(libcBase))
libcPhdr = findPhdr(libcBase)
log.info("Libc's Program Header:................. " + hex(libcPhdr))
PIE = findIfPIE(libcBase)
libcDynamic = findDynamic(libcPhdr, libcBase, bits)
log.info("Libc's _DYNAMIC Section:............... " + hex(libcDynamic))
libcStrtab = findDynTable(libcDynamic, 5, bits)
log.info("Libc's DT_STRTAB Table:................ " + hex(libcStrtab))
libcSymtab = findDynTable(libcDynamic, 6, bits)
log.info("Libc's DT_SYMTAB Table:................ " + hex(libcSymtab))
symbolAddr = findSymbol(libcStrtab, libcSymtab, symbol, bits)
log.success("%s loaded at address:.............. %s" % (symbol, hex(symbolAddr + libcBase)))
if __name__ == "__main__":
log.info("Manual usage of pwnlib.dynelf")
if len(sys.argv) == 3:
pid = sys.argv[1]
symbol = sys.argv[2]
lookup(pid, symbol)
else:
log.failure("Usage: %s PID SYMBOL" % sys.argv[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment