我遇到了这种技术,利用 Windows 调试工具的 gflags 中的 HPA 功能(堆页面分配器,称为 PageHeap)来查找堆分配的大小:
假设您在程序 X 上发现了一个 use-after-free,其中在某个时候它正在取消引用一个寄存器和一个偏移量。
你可以:
1)打开IDA查找创建对象的位置以查看分配的大小。
2) 使用页堆、windbg 并查看分配堆栈跟踪
3) Windbg !heap -p -a
或者...我今天使用的一个快速技巧,利用页面堆将对象放在页面末尾以捕获缓冲区溢出。
1:022:x86> ? 0x1000-(ebx&0x00000FFF) 求值表达式:88 = 00000058 <--- 块大小 1:022:x86>
Fermin J. Serna - @fjserna
为什么有效?
这是我的理解:
- 每页为 0x1000 字节 (4kb)。
- 每个小于 0x1000 的块将从页尾向后分配。
- 因此,通过获取页面大小并从中减去块大小,从块地址中检索我们使用 & 运算符获得的最后 3 位数字,您将得到它的实际大小。
这似乎有点巫术,因为:
为了使减法工作,检查的分配块地址必须与 1000 对齐。HPA 是否以某种方式对齐页面中的所有内容?我没有找到任何包含足够信息的资源。HPA 是否还有其他方法可以使此公式适用?
AND 运算符实际上如何使值仅返回最后 3 位数字?我不明白它的逻辑。
有没有好心人可以为我们解释一下这些事情?