CISCN-BUU刷题记录3
1.ciscn_final_5:由于题目本身原因,chunkList中存放的堆地址是chunk_addr+idx,所以idx为16时就会导致存放的堆地址为chunk_addr+0x10。同时放入chunkList的顺序是按照申请顺序放入的,删除和修改的时候也是通过遍历查找的。那么如果先申请索引为16,1的chunk,chunkList中就会如下:
chunk16_addr+0x10,chunk1_addr
如果这时候释放索引为0的Chunk,就会误以为chunk16_addr+0x10为索引为0的chunk,如果事先伪造了chunk16_addr+0x10的size域,那么就能够将其释放,再申请回来,那么我们就能够制造堆块重叠,有了堆块重叠加上edit功能就很随意了。
1 | # -*- coding:UTF-8 -*- |
这里需要注意一点的是,我的做法不像其他人申请chunk到chunkList直接控制chunk块,从而修改堆块地址传入到被劫持为puts函数的free_got来泄露地址,而是直接申请到got表上,将got表作为堆地址传入被劫持为puts函数的free_got来泄露got表中的地址。
但是这里会遇到一个问题,就是选择哪一个函数的got表作为堆地址。这里两种解决办法:
(1)可以发送size为0,那么就不会修改到函数的got表,但是这个方法要求利用0x20的tcache的dup。
(2)如果size不为0,那么申请堆块的时候势必要发送数据,最少也是\x0a。那么发送数据也肯定会修改到该函数的真实地址,那么泄露出来的就是修改后的真实地址,而且如果该函数在程序运行过程中容易被调用,那么修改之后也势必会使得程序崩溃。这里有Libc文件还好,可以直接查找libc文件对于函数的最后一个字节来修复一下,但如果没有libc文件,那么就没招了。
这里假设没有libc文件,那么我们就需要找一个不太能用到函数来修改,这里刚好有个__stack_chk_fail_,只要不触发canary,这个函数就不会被调用,其got表是延迟绑定的,保存的不是真实地址,直接拿来用就行。同时还要注意的是由于是__stack_chk_fail_的got表作为堆地址,但是实际传入给puts函数的地址是__stack_chk_fail_got-0x10,所以泄露出来的是对应的puts函数的真实地址。
之后就正常利用0x20,0x30,0x40的tcache来任意申请修改了。
2.ciscn_2019_en_3:水题,利用格式化字符串泄露地址,打free_hook,唯一需要注意的一点是程序本身的提示信息,注意空格和DEBUG的使用。
1 | # -*- coding:UTF-8 -*- |
3.ciscn_2019_s_6:水到家的题,懒得看,两分钟改完脚本拉倒。
1 | # -*- coding:UTF-8 -*- |
4.ciscn_2019_sw_1:格式化字符串,改fini_array为main_addr,使得程序循环再来一次,劫持printf为system_plt,再输入binsh即可getshell。程序里的sys没啥用,用来迷惑人的,因为command无法被修改。
1 | # -*- coding:UTF-8 -*- |
5.ciscn_2019_s_1:差点被这道题搞崩溃。网上解法太多,感觉都挺麻烦的。其实直接一个技巧就搞定:house_of_einherjar。进行一定堆布局,申请chunk8-chunk10,将0x100的tcache填满,在chunk8中伪造chunk,满足2.27下的unlink要求,即size位和fd,bk位。(由于这里给了堆地址,所以可以直接用,恰好能够满足要求)之后触发0x100的off-by-null向上合并,将chunk9给overlap,之后申请到tcache结构体,就能随便玩了。(house_of_einherjar重点在于2.27下的unlink)
1 | # -*- coding:UTF-8 -*- |