/*
* Author: leng_que
* Date: 2015-03-19
* Description: 简单的演示了UAF漏洞的原理
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char* buf_use = (char*)malloc(32);
printf("buf_use's addr = [0x%08X]\n", buf_use);
strcpy(buf_use, "1");
printf("You have money %s$.\n", buf_use);
free(buf_use);
// free之后,buf_use指向的内存块已经被MMU(内存管理单元)标记为释放状态,即:这块内存是可以被其它地方再次分配到的。
printf("\n\n");
// 在这里,buf_new的地址有很大概率是与之前的buf_use是相同的。
// 因为这里要分配一个同样大小的内存块,MMU理所当然的应该把刚刚之前释放掉的那个内存块拿出来。
// 当然,这个在本质上是要取决于MMU的实现。
char* buf_new = (char*)malloc(32);
printf("buf_new's addr = [0x%08X]\n", buf_new);
strcpy(buf_new, "999"); // 修改其中的内容
printf("You have money %s$.\n", buf_use); // 在此处对于buf_use这个指针的使用,即:Use-After-Free(释放后重用)
getchar();
return 0;
}
我的编译运行环境:Windows7 64位 + Code::Blocks v13.12
结果输出:
buf_use's addr = [0x00032F98]
You have money 1$.
buf_new's addr = [0x00032F98]
You have money 999$.
说明:
可以看到,上面那个例子就是通过UAF漏洞把金钱数值给改了。通常在网页浏览器上这类漏洞特别多,例如:IE,这是因为浏览器涉及到各种描述语言或脚本语言的解析,这其中就会有很多对象的产生与销毁,即:内存的分配与释放,同时那么多的对象的产生、销毁与使用,这其中的关系是极其错综复杂的,你很难知道你所使用的内存块是否已经被释放后又重新分配并且被恶意篡改了的,因此出现了很多UAF漏洞。
这种漏洞在本质上就是控制内存中的某个或某些值,从而改变程序原本的逻辑。
其主要的利用步骤是:
1、显式的触发对某块内存的释放。2、申请分配到那块之前被释放了的内存,并视具体情况更改其中的内容。3、触发UAF部分。
当然,在真实的场景下,其利用过程是非常复杂的,这其中还涉及到要绕过各种保护机制等等内容,而且“申请分配到那块之前被释放了的内存”也不总是那么容易实现的,但总还是有各种技巧的,例如:HeapSpray(堆喷射技术)就是其中的一种。再者其中第2步中所更改的内容主要取决于第3步中是如何使用这块内存的,比如如果仅仅只是用来显示,那么你所更改的内容只是影响了显示而已,但如果是用来执行指令的话,那你就能控制程序的运行逻辑了。更多参考:
http://sebug.net/paper/books/vulncat/cpp/use_after_free.html
http://security.stackexchange.com/questions/20371/from-a-technical-standpoint-how-does-the-zero-day-internet-explorer-vulnerabili