ZCTF note3:一种新解法

最近在学习unlink做到了这道题 , 网上有两种做法:一种是利用edit功能读入id时整数溢出使索引为-1 , 一种是设置块大小为0使得写入时利用整数溢出漏洞可以将数据溢出到下一个块中 。我采取了另一种思路:程序在分配id=7块时虽然提示块已满 , 但没有采取措施 , 依然分配了一个块 , 并将块地址放在了存放块0 size的位置 , 使得可以往块0写入足够多的数据溢出到下一个块中 。
我先分析我的解法 , 然后再简单叙述一下另外两种解法的原理 。
程序分析一般步骤查看程序保护措施 。

ZCTF note3:一种新解法

文章插图
该程序有4个功能:
  • New note
  • Show note(假的 , 只打印一个字符串)
  • Edit note
  • Delete note
New功能添加note函数如下图 , 主要流程已通过注释标注 。值得注意的是当i=7时 , 虽然提示note已满 , 添加失败 , 但没有return语句 , 后面依然为它分配块并将地址保存在&ptr+7处 。(注意:i=0时块的size保存在qword_6020C0[0+8]处)
ZCTF note3:一种新解法

文章插图
需要关注的是qword_6020C0和ptr的关系 , 其内存关系如下所示
.bss:00000000006020C0 ; __int64 qword_6020C0[].bss:00000000006020C0 qword_6020C0    dq ?                    ; DATA XREF: sub_400A30+D1↑w.bss:00000000006020C0                                         ; sub_400A30+E6↑w ....bss:00000000006020C8 ; void *ptr.bss:00000000006020C8 ptr             dq ?                    ; DATA XREF: sub_400A30+16↑r.bss:00000000006020C8                                         ; sub_400A30+BC↑w ....bss:00000000006020D0                 dq ?.bss:00000000006020D8                 dq ?.bss:00000000006020E0                 dq ?.bss:00000000006020E8                 dq ?.bss:00000000006020F0                 dq ?.bss:00000000006020F8                 dq ?.bss:0000000000602100                 dq ?.bss:0000000000602108                 dq ?可以看到ptr所在位置等同于qword_6020C0[1]所在位置 , 所以当i=7时分配的块地址保存在&ptr+7等同于保存在qword_6020C0[8]处 , 即表示i=0块的大小 。通过分配i=7块可实现i=0块大小被新分配块地址覆写 , 而块地址所代表的大小足够我们溢出到后面的块内 。

经验总结扩展阅读