攻防世界进阶题Recho——知识点缝合怪
文章目录
引入
好久没有做pwn题了,手生的厉害,做道简单题练练手好了
这道题其实难度不高,属于那种开门见山把漏洞点抛出任君采撷的题,但是由于涉及的知识点较多,在ROP链构造时需要有清晰的思路,对于我这样的小白来说自然是再好不过的练习题。
初分析
1、checksec
题目拿到手上,第一件事还是checksec
发现只有NX(栈不可执行)打开了
2、主函数结构
ida反汇编伪代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
char nptr[16]; // [rsp+0h] [rbp-40h] BYREF
char buf[40]; // [rsp+10h] [rbp-30h] BYREF
int v6; // [rsp+38h] [rbp-8h] var_8
int v7; // [rsp+3Ch] [rbp-4h] var_4
Init();
write(1, "Welcome to Recho server!\n", 0x19uLL);
while ( read(0, nptr, 0x10uLL) > 0 )
{
v7 = atoi(nptr); // 输入希望读入的字符长度
if ( v7 <= 15 )
v7 = 16; // 至少读入16个字符
v6 = read(0, buf, v7); // 读入缓冲区,v6记录读入长度
buf[v6] = 0; // 加入截断
printf("%s", buf);
}
return 0;
}
显而易见的栈溢出
3、栈结构
buf距离return地址0x38字节
4、特殊字符串
data段的小提示
解题过程
其实解题思路已经很明显了,整个栈空间都在控制内,又给出了提示“flag”文件名,故整体思路如下
- 挟持GOT,调用open函数打开flag
- 用read函数把flag文件中的内容读入bss段缓存区(可读可写)
- 用printf函数把缓存区中的内容输出
1、gadget搜集
由于涉及到ROP对函数调用,又是x86-64架构的系统,函数参数主要通过寄存器传递,所以需要找到控制相应寄存器的gadget
并且为了更改GOT表项的值,还需要一个可以改变特定地址值的地址
已知函数参数主要通过寄存器传递,前三个参数分别放在rdi,rsi,rdx寄存器中,幸运的是,这三条指令都存在(0x4008a3、0x4008a1, 0x4006fe),这样我们就不需要用到One_gadget去硬凑了(有关万能One_gadget的相关知识)。同时,我们也顺利的找到了所需的改值gadget(0x40070d)
2、GOT表详情
需要更改GOT表项以获得open函数,所以看看plt表中有哪些函数(关于GOT,PLT和延迟绑定机制)
因为alarm函数不需要用到,所以计划将alarm函数的got表项改为system_call这个系统调用接口函数,这个函数在使用时只需改变保存在eax中的系统调用号即可调用系统函数。
3、函数参数说明
- <