Buffer Overflow
ret2text
ret2text 即控制程序执行程序本身已有的的代码。
先找到可调用的函数地址,再用系列一技巧中的方法可以轻松算出覆盖24个a即可覆盖到返回地址,部分脚本如下。
1 | bash = 0x0400607(此为调用系统shell的地址) |
ret2shellcode
与ret2text类似,只不过没有可直接调用的函数。于是需要自己填充shellcode,但需要填充的区域(一般为bss)有可执行权限。
可用checksec插件进行检测,如下图。
于是可以利用pwn库自带的asm(shellcraft.sh())
生成shellcode进行插入,由于shellcode长度未知,可用shellcode.ljust(112, 'A') + p32(shellcode)
来进行对齐插入。
ret2syscall
ret2syscall即控制程序执行系统调用来获取shell。
系统调用:Linux的系统调用通过int 80h实现,用系统调用号来区分入口函数
应用程序调用系统调用的过程是:
- 把系统调用的编号存入EAX
- 把函数参数存入其它通用寄存器
- 触发0×80号中断(int 0x80)
接下来就是选取系统调用号然后构造参数,可使用ROPgadget
来查找,命令如下
1 | ROPgadget --binary rop --only 'pop|ret' | grep 'eax' |
例如构造execve
(0Xb为其对应的系统调用号,可通过 此网站 查询),例如下列两种,只要逻辑正确均可:
1 | pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh |
若为64位机则需置RAX为0x3b RDI为bin_sh_addr RDX为0 RCX为0。
在发送payload时可用flat
函数将字符串和地址结合并且转为字节模式,如下:
1 | payload = flat(['A' * 112, pop_eax_ret, 0xb, pop_ecbx_ret, 0, binsh, pop_edx_ret, 0, int_0x80]) |
ret2libc
有RELRO,且NX保护是开启的,于是利用流程如下:
- 测试偏移,控制跳转地址
- 泄露libc中某函数的地址
- 使用puts,printf等函数将GOT表中的函数地址打印出来
- ×86-64位上使用寄存器传递参数rdi rsi rdx rcx(传参方法如上ret2syscall)
在需要泄露libc中某些函数地址(如puts、write、gets等)来确定libc版本,然后根据版本和相对偏移计算system等函数地址时,可以使用LibcSearcher
,示例如下:
1 | from LibcSearcher import * |
(详情见)。