ret2csu
__libc_csu_init
是 GNU C Library (glibc) 中的一个初始化函数,csu
通常指的是 “C Runtime Startup” 或 “C Startup”。这个函数主要用于 C 程序的启动过程,特别是在涉及到 C++ 构造函数和全局对象的初始化时。
下面的代码片段通常用于ret2csu
|
|
利用上面的gadget有下面的控制关系
-
rbp = rbx + 1 防止跳到<__libc_csu_init+64>,顺利执行到ret
-
r15 => func 若rbx为0,控制了r15就能指向指定内存区域
-
r12 => rdi 通过r12控制rdi,解决x64下第一个参数的传递问题
-
r13 => rsi 通过r13控制rsi,解决x64下第二个参数的传递问题
-
r14 => rdx 通过r14控制rdx,解决x64下第三个参数的传递问题
上面的寄存器都能控制的话就可以非常随意得调用三个及三个以下参数的函数
值得注意的是下面就有对各种寄存器的pop,只需要使用这些gadget在栈上构造payload
思路
首先布栈,调用pop
|
|
ret直接跳转到0x401270 <__libc_csu_init+64>,给传参的寄存器传值
|
|
调用函数
|
|
注意要让rbp = rbx + 1防止二次调用
|
|
布栈数据
- 0x40128a处获得pop指令,下面按顺序把值传入寄存器,这里是为了给函数传参
- 0x401270处是ret的返回地址,这里控制rip到0x401270执行函数传参和函数调用
- 调用完函数会根据rbp和rbx的值决定是否往上跳转,这里一定要有上面的等式关系不往上跳转
- add rsp,0x8给rsp加了8个字节,正好是一个地址的长度,这块地址随便填,也就是上面的0xdeadbeef
- 后面又pop各种寄存器,此时传什么参数不关心,因为已经调过函数了,只要有东西传即可,
- 上面执行完就走完了函数
__libc_csu_init
,返回地址就是下一个函数的地址,一般用exit
退出程序
不同版本的libc的__libc_csu_init反汇编出来的代码会有差异,具体要根据实际的汇编代码布栈
不同利用方式的比较
溢出函数 => __libc_csu_init => 溢出函数 => system
- 优点:溢出函数的payload比__libc_csu_init的少,适用于溢出空间较小的情况
- 缺点:溢出函数需要额外gadget给寄存器传参
溢出函数 => __libc_csu_init => __libc_csu_init => system
- 优点:__libc_csu_init有良好的传参环境,不需要额外的gadget
- 缺点:__libc_csu_init构造的payload比溢出函数的多,适用于溢出空间较大的情况
第一个 payload 都是泄露 libc 的基地址
例题
|
|