Pwn 学习 question_5_plus_x64 ret2csu
1.源代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int dofunc(){
char b[8] = {
};
write(1,"input:",6);
read(0,b,0x200);
//printf(b);
write(1,"bye",3);
return 0;
}
int main(){
dofunc();
return 0;
}
2.源代码分析
- 没有后门函数
- 没有/bin/sh
- 第二个write只输出了三个字符
- 导致rdx会被修改成3
- 而且没有可控rdx的gadget
- 这个时候就要花式栈溢出!!!
- 在函数编译的时候都会生成一个 libc_csu_init 函数:如下图
- 这个函数的末尾调用了几乎所有的寄存器
- 我们可以控制程序来到csu来修改寄存器的值
- 但是这个方法需要溢出的量比较大
- 所以要清楚溢出的能否支撑布栈
3._libc_csu_init 分析
- 截取这个函数有用的部分来分析一下利用过程
.text:00000000004011E8 loc_4011E8: ; CODE XREF: __libc_csu_init+4C↓j
.text:00000000004011E8 mov rdx, r14
.text:00000000004011EB mov rsi, r13
.text:00000000004011EE mov edi, r12d
.text:00000000004011F1 call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
.text:00000000004011F5 add rbx, 1
.text:00000000004011F9 cmp rbp, rbx
.text:00000000004011FC jnz short loc_4011E8
.text:00000000004011FE
.text:00000000004011FE loc_4011FE: ; CODE XREF: __libc_csu_init+31↑j
.text:00000000004011FE add rsp, 8
.text:0000000000401202 pop rbx
.text:0000000000401203 pop rbp
.text:0000000000401204 pop r12
.text:0000000000401206 pop r13
.text:0000000000401208 pop r14
.text:000000000040120A pop r15
.text:000000000040120C retn
- 可以看到这个函数调用了很多寄存器
- 其中有我们要控制的rdx
- ret2csu适合控制3个参数的函数调用
.text:00000000004011E8 mov rdx, r14
- 从第一行看
r14 -> rdx
r13 -> rsi
r12d -> edi //r12d就是r12的底四位,这里不影响我们传参
然后call [r15 + rbx * 8] // 这里只要把rbx赋值成0就可以直接call [rbx]
然后 rbx = rbx + 1
将rbp和rbx作比较
如果不等于0就跳转到 0x4011E8 //控制rbp和rbx相等即可继续执行下面的ret了
下面:
pop rbx
pop rbp
pop r12
pop r13
pop r14
pop r15
就可以用来修改寄