pwn调整栈帧的技巧

调整栈帧的技巧

我们在存在栈溢出程序中,经常会碰到一些关于栈的问题,比如开启ASLR导致栈地址不可预测,所能溢出的字节数太少等等。对于这些问题,我们有时候可以通过gadgets来调整栈帧以完成攻击。比如我们所用到的常见手段,包括esp值的加减,利用部分溢出字节来修改ebp的值来进行stack pivoting等。

0x00 扩大栈空间

正常来说,当栈空间不够用时我们是写入bss段中的,那有什么办法不用写入bss就能在栈上进行呢?栈空间是否可以改变?那么,我们这里就试着是通过修改esp来扩大栈空间。
这里直接用了~/Alictf 2016-vss做例子。
首先查看程序的保护机制

adef@ubuntu:~/AliCTF vss$ checksec vss
[*] '/AliCTF vss/vss'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)


我们发现程序是64位的,只开启了NX,因为程序使用了strip命令剥离符号和静态编译,用IDA打开后发现程序乱糟糟的。



IDA载入后显示的是start代码块,这个结构是固定的,call的函数是**__libc_start_main**函数。进入main函数后,我们找到syscall,可以通过syscall的eax值、参数等确定几个函数的名字。

即这里的sys_alarm:(unsigned int seconds)

main函数里,sub_4374E0使用了调用号是0x25的syscall,而且F5的结果中该函数接收一个参数,应该就是alarm


sub_40880字符串单参数,且字符串被打印输出,可以猜测是puts。



我们继续寻找syscall调用函数
找到sub_437EA0调用 sub_437EBD,并使用了0调用号syscall,而且接收了三个参数,推测是read函数。


这时,我们的main函数变为:

我们命名的check函数内部比较复杂,先不尝试对其静态分析,先看上面的read,通过向程序注入大量字符发现程序存在溢出:
在这里插入图片描述

那么我们在read处下个断点,跟踪一下程序的输入走向:


我们步步跟进check函数,执行到call sub_400330一行并看执行结果,像是一个复制值操作,推测sub_400330是strncpy()函数。



继续往后执行,发现这里有两个判断,内容是判断输入的头两个字母是否为py,如果是则退出,否则就进入一个循环,这个循环会用一个值作为循环次数对输入开始的每一位进行异或0x66,这个只是[rbp+rax+dest]。由于这个值会被修改,也就是说循环次数会改变,而且变得过大,使得循环最后因为试图访问没有标志位R的内存页而崩溃。
在这里插入图片描述

从上面得到rbp+rax=0x7FFE6CD1A040,这个地址所在的内存页就无法访问。


那么我们就该尝试新思路了,我们试着在输入的开头加上’py’,这次出现了一个数据可控的栈溢出。



我们观察数据后发现,被修改的EIP是通过strcnpy复制到输入前面的0x50个字节的最后8个。这里由于没有libc,one_gadget RCE 也不能用,而且使用了strncpy,在payload里字符串又不能出现’\x00’,否则会被当做00截断从而使字节复制过程中无法复制满’0x50’个字节,就无法制造可控溢出了,这也就意味着任何地址都不能被写在前0x48个字节中,那么这种情况就用到了我们所提及的修改esp完成漏洞利用。

首先,虽然限制条件很多,但在main函数中我们看到read函数读取的字节大小’0x400’,而且read函数是可以读取’\x00’的:

这就说明我们可以用ROP链写入,放到0x50字节的后面,然后增加esp的值将栈顶抬高到ROP链上,我们看一下包含add esp的gadget都有哪些:

我们这里选用0x58那行,通过这个gadget,我们可以成功的将esp值增加到0x50之后。
接下来我们就可以使用我们熟悉的ROP技术来调用sys_read读取"/bin/sh\x00"字符串,最后调用sys_execve了。
下面就是所构建的ROP链和完整脚本:

#!/usr/bin/python
#coding:utf-8
from pwn import *

context.update(arch 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值