CTF常用python庫PwnTools的使用學習

Ox9A82發表於2016-08-02

  之前主要是使用zio庫,對pwntools的瞭解僅限於DynELF,以為zio就可以取代pwntools。後來發現pwntools有很多的高階用法都不曾聽說過,這次學習一下用法,希望可以在以後的exp編寫中能提供效率。

  PwnTools的官網如下:http://pwntools.com/

  安裝方法是使用pip命令,pip install pwn。這樣就可以安裝上pwn庫了。使用時用from pwn import *來進行呼叫。

連線

本地process()、遠端remote()。對於remote函式可以接url並且指定埠。

IO模組

下面給出了PwnTools中的主要IO函式。這個比較容易跟zio搞混,記住zio是read、write,pwn是recv、send就可以了。

send(data) : 傳送資料
sendline(data) : 傳送一行資料,相當於在末尾加\n

recv(numb=4096, timeout=default) : 給出接收位元組數,timeout指定超時
recvuntil(delims, drop=False) : 接收到delims的pattern
(以下可以看作until的特例)
recvline(keepends=True) : 接收到\n,keepends指定保留\n
recvall() : 接收到EOF
recvrepeat(timeout=default) : 接收到EOF或timeout

interactive() : 與shell互動

ELF模組

ELF模組用於獲取ELF檔案的資訊,首先使用ELF()獲取這個檔案的控制程式碼,然後使用這個控制程式碼呼叫函式,和IO模組很相似。

下面演示了:獲取基地址、獲取函式地址(基於符號)、獲取函式got地址、獲取函式plt地址

>>> e = ELF('/bin/cat')
>>> print hex(e.address)  # 檔案裝載的基地址
0x400000
>>> print hex(e.symbols['write']) # 函式地址
0x401680
>>> print hex(e.got['write']) # GOT表的地址
0x60b070
>>> print hex(e.plt['write']) # PLT的地址
0x401680

資料處理

主要是對整數進行打包,就是轉換成二進位制的形式,比如轉換成地址。p32、p64是打包,u32、u64是解包。

DynELF

DynELF是leak資訊的神器。前提條件是要提供一個輸入地址,輸出此地址最少1byte數的函式。官網給出的說明是:Given a function which can leak data at an arbitrary address, any symbol in any loaded library can be resolved.

很叼啊,有木有。以下是官方例程

# 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

 

相關文章