-
-
[原创]看雪.TSRC 2017CTF秋季赛第四题WP
-
发表于: 2017-10-31 12:25 4090
-
这是此次比赛的第一个PWN题型。打开看了下,竟然似曾相识的感觉。下面先简单说下程序功能。
程序主功能流程在偏移为121A
的函数中:
先以seed
变量地址为种子初始化随机数,然后进入循环体通过switch表进行功能选择及操作。功能函数有6个,功能分别为:
大致看下就知道应该是堆方面的漏洞利用了。一共可以申请管理5个堆,编号1-5。与堆有关的全局变量(常量)共有4个,分别是:
功能函数不详细说了,只说主要点。
getbox申请堆时,先检查box_flag[i]
,未使用过才可申请。然后会根据前后已申请堆的大小来检查当前输入尺寸,检查原则是前小后大且差值不小于16字节。申请成功后,box_flag[i]
置位,当前堆大小写入box_size[i]
,堆地址写入box_addr[i]
,在释放时该堆时,box_flag[i]
、box_size[i]
box_addr[i]
保持不变。
destroybox释放堆时,会检查box_flag[]
和堆可释放标记destroy_flag[i]
,结合此常量值,可释放的堆编号只有2,3,5。并且堆释放后,并不对上面说的与堆相关的全局变量作清除工作。致使box_addr[i]
成悬空指针,
leavemessage和showmessage就是向堆中写数据和读数据了,写的时候会检查当前堆的尺寸,读是直接puts
。
randnum是猜测程序的下一个随机数,如果猜对则打印出seed
值,实际上就是其地址。
通过上面的程序功能说明,已然发现可以利用double free
方法,关于此方法可参看我的另一篇WP。
申请编号为2,3的堆,释放;再申请编号为4的堆,尺寸为2,3之和;向4号堆写数据,构造两个free状态的chunk;释放3号堆,造成double free,触发unlink,修改box_addr[3]
数值;申请1号堆,并通过堆写数据修改box_addr[3]
数据为free
函数的got.plt
地址,即box_addr[1]
指向got.plt
;通过showmessage
泄露libc函数地址;通过堆写数据修改box_addr[1]
数据为system
函数地址;修改3号堆数据为/bin/sh
并释放,getshell。
以上思路看似不错。但是当打开虚拟机,checksec一下会发现,PIE
开启,box_addr
地址不知,那就不能构造free状态的假chunk,一切成为空谈。这就说明还是按步就班的好。
仔细想想,程序中有一个功能函数可以泄露程序的基址,那就是看上去不起眼的猜随机数的功能函数,猜对随机数就能得到seed
地址,那一切又水到渠成了。
我们知道这个随机数是伪随机数,只要知道种子,就能知道随机数的出现序列。此程序的随机种子实际上是seed
地址的低4字节。seed偏移一定,程序基址4K对齐,那后12bit是已知的。那可以通过程序的第一个随机数暴出种子,得到下一个随机数,再通过程序功能得到seed
的完整地址。
在实现上,exp脚本先读取程序的第一个随机数,调用暴破用的C程序,得到下一个随机数提交给程序获得程序基址,再进行堆漏洞的利用。
代码如下:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)