# ret2csu

# 原理

  • 64 位程序中,函数的前 6 个参数是通过寄存器传递的,但是大多数时候我们很难找到每个寄存器对应的 gadges。这时候,我们可以利用 x64 下的__libc_csu_init 中的 gadgets。
  • 这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在。

# 下面借用别人在 IDA 摘出来的__libc_csu_init 函数的汇编指令

.text:00000000004011B0 ; void _libc_csu_init(void)
.text:00000000004011B0                 public __libc_csu_init
.text:00000000004011B0 __libc_csu_init proc near               ; DATA XREF: _start+16↑o
.text:00000000004011B0 ; __unwind {
.text:00000000004011B0                 push    r15
.text:00000000004011B2                 mov     r15, rdx
.text:00000000004011B5                 push    r14
.text:00000000004011B7                 mov     r14, rsi
.text:00000000004011BA                 push    r13
.text:00000000004011BC                 mov     r13d, edi
.text:00000000004011BF                 push    r12
.text:00000000004011C1                 lea     r12, __frame_dummy_init_array_entry
.text:00000000004011C8                 push    rbp
.text:00000000004011C9                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:00000000004011D0                 push    rbx
.text:00000000004011D1                 sub     rbp, r12
.text:00000000004011D4                 sub     rsp, 8
.text:00000000004011D8                 call    _init_proc
.text:00000000004011DD                 sar     rbp, 3
.text:00000000004011E1                 jz      short loc_4011FE
.text:00000000004011E3                 xor     ebx, ebx
.text:00000000004011E5                 nop     dword ptr [rax]
.text:00000000004011E8

gadgets2:

.text:00000000004011E8 loc_4011E8:                             ; CODE XREF: __libc_csu_init+4C↓j
.text:00000000004011E8                 mov     rdx, r15
.text:00000000004011EB                 mov     rsi, r14
.text:00000000004011EE                 mov     edi, r13d
.text:00000000004011F1                 call    qword ptr [r12+rbx*8]
.text:00000000004011F5                 add     rbx, 1
.text:00000000004011F9                 cmp     rbp, rbx
.text:00000000004011FC                 jnz     short loc_4011E8
.text:00000000004011FE

gadgets1:

.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
.text:000000000040120C ; } // starts at 4011B0
.text:000000000040120C __libc_csu_init endp

这里搬运之前在 CSDN 上发的文章(汇编代码执行顺序为先 gadgets2, 然后 gadgets1)

pop 命令 会把栈中的值存入相应的寄存器中,那么我们可以通过往栈中写对应的数据来存入寄存器里

cmp     rbx, rbp   //cpm后的不同的调整指令有着不同的作用,这里 jnz 比较结果相同不跳转,不相同就跳转
jnz     short loc_400580

最后第二次回到 gadget1 时,此时已经给寄存器赋值完毕只需要回到 ret,此处填充 56 个 padding 字符是因为在地址 0x4011FE 处有 add rsp , 8 这会把 rsp 栈提高 8,所以要填充 8 个字符来站这个位置,后面的 pop rbx ~ pop r15 共有 6 个寄存器,pop 了 6 次,所以总共是 (6+1)*8=56,所以填充 56 个字符即可到 ret 来控制程序执行

例题:https://vvwwvv.cn/2023/05/04/pwn/ 刷题 / 看雪社区 / 看雪社区 pwn8 (64 位构造通用 ROP,ret2csu)/

此文章已被阅读次数:正在加载...更新于