MY BLOG: 0gur1.cc
这题据说是远程没有启用assert,导致文件没有close。但我当时没看出来,现在平台关闭了也试不了了TAT,就看了些大佬(Ne0 和dcua )的wp,了解这个漏洞是怎么用的。duca的wp更细一点,两者结合更容易理解。
关于assert
DESCRIPTION If the macro NDEBUG was defined at the moment <assert.h> was last included, the macro assert() generates no code, and hence does nothing at all. Otherwise, the macro assert() prints an error message to standard error and terminates the program by calling abort(3) if expression is false (i.e., compares equal to zero).
如果assert.h中包含了宏NDEBUG,assert将不生成代码,不执行任何操作;否则当assert中的条件不满足时,assert会输出错误并终止程序。
也就是说,如果远程assert.h中有NDEBUG,那么在read_lyrics中的关闭文件操作就不会执行:
memmove通过数组的前移实现删除,因此当读到的内容包含“DrgnS”时,只会在数组中删除元素,但文件仍处于打开状态,即fd的数量没有减少。
关于setrlimit
程序进行了一些限制,其中就包含能够打开文件描述符的最大值:
打开的文件个数超过32个时,再通过open打开文件就会失败。观察open_lyrics的检查顺序,有两个用到open的操作位于flag之前,因此可以通过这一操作绕过flag的读取。
另外,程序中限制输入的band或者song中不能包含“../”,但是可以输入“..”绕过。
参考Ne0大佬 的思路。
这题用到了一个奇怪的点:abs(0x80000000)==0x80000000。从开始看大佬的wp到自己捋顺一共花了两天时间ORZ。
add,print和edit功能。
add函数输入name、size和value,并对size和value地址做简单的处理后一起存放。题目中实现了一个类似于哈希表的简单结构:对name进行哈希作为索引,出现碰撞后用next字段链接起来。
其种insert_item函数是对name作一些运算并进行插入操作。我用的IDA6.8版本的就看不出来用了abs函数(当然即使看出来也不觉得有问题),据说7.0的可以直接显示。
通过insert_idx函数了解到哈希链表结点的结构。
set_hash_bits函数用位运算记录h2和h3的结果:
print和edit都是通过name定位到结点,输出或修改value的值。
find_by_name函数中同样用到了h1,h2,h3函数,并在遍历链表前先对bits[idx]进行检查,查看bits[idx]是否有对应的几个bit。
大佬们究竟是怎么想到的??
abs(0x80000000)==0x80000000。验证一下:
输出结果:
如果h1(name)为0x80000000,idx = abs(0x80000000)%62=-2,在insert_idx时进行entry[idx] = node_addr时,实际上是对entry之前的数据进行操作。查看bss结构,entry[-2]即为bits[60]。
当输入特定的name时,会在entry[-2]即bits[60]写入堆地址,而在find_by_name中的check会对bits[60]进行检查,确定是否有某一bit,检查失败会返回"No such entry! ",利用这一点可以对bits[60]中的堆地址进行逐位泄露,方法是暴力破解。
另外,在新增结点时,bit[idx]|=1<<a2|1<<a3,通过操作a2和a3能够修改bit[idx]中的内容,即如果能够修改bit[60]中的堆地址,就相当于修改了entry[-2]的首个结点地址,控制这个堆地址中存放满足条件的name,就能泄露或者修改指定的value值。
脚本我是参考EmpireCTF队伍的wp ,这里就只附上暴破的简单脚本:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-10-12 22:57
被oguri编辑
,原因:
上传的附件: