pwnlib.dynelf
— 使用leak解析远程函数¶
这个模块主要用于解析ELF文件中加载的以及动态链接的符号。只要给一个可以泄漏任 何地址内容的函数,我们就可以解析加载的库中的任何地址。
例子
# Assume a process or remote connection
p = process('./pwnme')
# Declare a function that takes a single address, and
# leaks at least one byte at that address.
def leak(address):
data = p.read(address, 4)
log.debug("%#x => %s" % (address, (data or '').encode('hex')))
return data
# For the sake of this example, let's say that we
# have any of these pointers. One is a pointer into
# the target binary, the other two are pointers into libc
main = 0xfeedf4ce
libc = 0xdeadb000
system = 0xdeadbeef
# With our leaker, and a pointer into our target binary,
# we can resolve the address of anything.
#
# We do not actually need to have a copy of the target
# binary for this to work.
d = DynELF(leak, main)
assert d.lookup(None, 'libc') == libc
assert d.lookup('system', 'libc') == system
# However, if we *do* have a copy of the target binary,
# we can speed up some of the steps.
d = DynELF(leak, main, elf=ELF('./pwnme'))
assert d.lookup(None, 'libc') == libc
assert d.lookup('system', 'libc') == system
# Alternately, we can resolve symbols inside another library,
# given a pointer into it.
d = DynELF(leak, libc + 0x1234)
assert d.lookup('system') == system
DynELF
class pwnlib.dynelf.DynELF(leak,pointer,elf=None)
Dynelf 知道如何借助 pwnlib.memleak.MemLeak
. 通过 infoleak 或者 memleak 漏洞解
析远程程序中的符号地址。
应用细节
解析函数:
ELF文件(例如
libc.so
)一般会导出自己声明的符号,以便于其他库使用。这样,就会存在一系列的表格,它们会给出导出符号的名字,地址,以及这些导出符号的hash
值。通过将hash函数应用在期望符号上(例如printf
),我们就可以在hash表中找到对应的位置。其相应的索引提供了到string name table( strtab )和symbol address( symtab ) 的寻找的方式。假设我们有
libc.so
的基地址,解析printf
的地址的方式就是去定位symtab
,strtab
,hashtabe
。字符串"printf"
根据 hash 表的风格( YSV 或者 GNU )被hash,因此我们可以遍历hashtable来找到一个匹配的入口。我们可以通过检查 strtab 来验证一个匹配,然后从 symtab 中获取其在libc.so
中的偏移。解析库地址:
__init__(self, leak, pointer=None, elf=None)()
这是DynELF的一个实例化方法,通过它,如果我们给了
pwnlib.memleak.MemLeak
leaker, 以及一个binary文件中的指针,我们可以生成一个可以解析运行库中符号的实例对象。
- 参数:
- leak (MemLeak) - 泄漏内存的 pwnlib.memleak.MemLeak 的实例。
- pointer (int) - 已经被load的ELF文件中的一个指针。
- elf (str,ELF) - ELF文件对应的路径,或者说一个已经加载的
pwnlib.elf.ELF
。
bases()
解析所有已经被加载的二进制文件的基地址。
返回一个将库路径映射到它的基地址的字典。
static find_base(leak,ptr)()
给定一个
pwnlib.memleak.Memleak
对象,以及一个其二进制文件内部的binary,找到它的基地址。
heap()
通过 __curbrk 来查找当前堆的基地址,这个符号在链接器中已经被导出了,指向当前的brk。
lookup(symb=None,lib=None)-->int()
在lib中找到对应符号的地址。参数如下
- symb (str) - 要查找的名字。
- lib (str) - 用来匹配库文件名的子串。缺省情况下会搜索当前的库,如果设置为
libc
, ``libc.so``就会被查找。返回对应符号的地址,或者None。
stack()
通过 __envrion (这个符号是由libc导出的,指向环境变量部分)来寻找一个指向栈上的变量,
dynamic()
返回指向
.DYNAMIC
的指针。
elfclass(self)()
返回对应的二进制文件的类型。
libc(self)()
得到远程libc.so的build版本,下载对应的文件,并且使用正确的基地址加载
ELF
对象。返回一个ELF对象,或者什么也不返回。
link_map(self)()
返回指向运行时的link_map对象。
pwnlib.dynelf.gnu_hash(str)-->int
为字符串生成GNU格式的hash值。
pwnlib.dynelf.sysv_hash(str)-->int
为字符串生成SYSV格式的hash值。