ret2csu 说明
复制本地路径 | 在线编辑
之所以叫 csu,本质是利用 __libc_csu_init 里现成的两段代码,构造出 ROP 链。
注意点:不需要知道 libc 地址
__libc_csu_init 不是在 libc 里面,而是编译进 你这个可执行文件 里的代码。也就是在 主程序 ELF 的 .text 段。
所以 ret2csu 不需要知道 libc 基地址!
具体细节
用的 __libc_csu_init 这个函数,里面有两个片段可以用:
片段一:
pop rbx
pop rbp
pop r12
pop r13
pop r14
pop r15
ret
片段二:
mov rdx, r15
mov rsi, r14
mov edi, r13d
call [r12 + rbx*8]
可以看到第二片段里面有个 call 指令,里面用到的寄存器 r12 和 rbx 我们可以在第一个片段中控制,所以两个片段会组合使用,达到 func(arg1, arg2, arg3) 的效果:
padding
csu_pop_addr ← 片段 A
rbx = 0
rbp = 1
r12 = func_got
r13 = arg1
r14 = arg2
r15 = arg3
csu_call_addr ← 片段 B
junk ← 对齐 / 占位
常用方式
常见的做法有 write(1, puts@got, 8); 泄露 libc 地址,read(0, bss, 0x400); 达到写入内存目的。
通常有如下的组合:
ret2csu → write 泄露
ret2csu → read 写第二阶段
ret2libc → system
好处
- ELF 基本都有
__libc_csu_init - 不依赖 libc
- 能一次性设置 3 个参数
- ASLR 开启也能用(只要程序不是 PIE)(回忆:ASLR 是 heap 之类的结构随机化,主程序不随机)