通常找到function加载地址的方法是通过同一个libc中另一个function的offset计算出来,这需要远程的libc和我们的libc版本相同。或者我们也可以通过libcdb.com找到远程libc的方法,虽然这个方法有时候会失败。
DynELF
如果程序有办法leak memory我们就可以使用DynELF。正如文档介绍的那样,DynELF使用了两种技术:首先找到libc的base address,然后通过Symbol Table Section和the String Table Section遍历直到找出我们需要的function
下面我们就来看他是如何实现的
找到libc的Base Address
首先我们从进程中找出libc空间内的一个地址,我们可以从已经解析过的Global Offset Table中找到, Next we can parse through that address space using the leak with decrements of the memory page size (0x1000)直到我们找到\x7fELF
字符串常量,它代表了载入的base address. 代码如下所示:
# leak func returns n number of bytes from given address
def findLibcBase(ptr):
ptr &= 0xfffffffffffff000
while leak(ptr, 4) != "\x7fELF":
ptr -= 0x1000
return ptr
找到Program Header
program header包括了一系列的Elf32_Phdr/Elf64_Phdr
结构,每一个结构包含一个segments
通过0x1c for 32bit or 0x20 for 64bit的偏移,从ELF header中找到Program Header的位置,progrtam header的结构Elf32_Phdr
包含了如下元素
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
代码如下所示
# addr argument is the module's base address or rather the beginning of ELF Header
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
找到DYNAMIC Section
下一步我们要从Elf32_Phdr结构体中找到DYNAMIC Section,我们可以通过Elf32_Phdr->p_type == 2
来找到它,其中Elf32_Phdr->p_vaddr
就是DYNAMIC Section的地址
查找DYNAMIC Section的代码如下
def findDynamic(Elf32_Phdr, 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
对于PIE (Possition Independent Executable) ,p_vaddr是一个offset,对于non-PIE binaries,p_vaddr是一个虚拟绝对地址
DYNAMIC Section包含了许多个Elf32_Dyn/Elf64_Dyn结构,Each structure contains information about section tables participating in the dynamic linking process. Some of them include DT_GOTPLT, DT_HASH, DT_STRTAB, DT_SYMTAB, DT_DEBUG any many more.
对于这个dynamic section tables,我们感兴趣的是DT_SYMTAB 或者称作 Symbol Table 和 DT_STRTAB 或者称作 String Table.
找出DT_SYMTAB 和 DT_STRTAB
Symbol Table包含了许多Elf32_Sym/Elf64_Sym这个结构,function的地址可以从每个Elf32_Sym->st_value中找到