CVE-2012-3569 VMware OVF Tool格式化字符串漏洞分析

VSole2021-09-14 17:58:18

漏洞信息

1、漏洞简述

  • 漏洞名称:VMware OVF Tool格式化字符串漏洞
  • 漏洞编号:CVE-2012-3569
  • 漏洞类型:格式化字符串漏洞
  • 漏洞影响:信息泄露
  • CVSS评分:9.3(High)
  • 利用难度:Medium
  • 基础权限:不需要

2、组件概述

开放虚拟机格式(Open Virtual Machine Format,OVF)是一种虚拟机分配格式,能够支持不同产品与组织之间共享虚拟机。

VMware OVF Tool是由VMware免费提供的一款支持虚拟的导入导出工具,支持以命令提示符的方式运行。

3、漏洞影响

VMware官网提供的影响版本。

4、解决方案

更新软件。

官方文档链接

(https://www.vmware.com/security/advisories/VMSA-2012-0015.html)

漏洞分析

1、基本信息

  • 漏洞文件:poc.ovf、exp.ovf(《漏洞战争》配套资料)
  • 漏洞函数:字符串打印函数std::basic_ostream
  • 漏洞对象:ovf文档

2、背景知识

(1) 格式化字符串漏洞

一段简单的代码:

#includeint main(){  char a[]="asdasd";  printf(a);  return 0;}

其输出为:

asdasd

上面的代码不会有什么问题,但是如果将字符串的输入权交给用户就会有问题了。看下面的代码:

#include int main(){  char a[100];  scanf("%s",str);  printf(str);  return 0;}

如果用户输入的字符串是"%x%x%x",则会输出以下结果:

6efe4c6effcc753eca20

可以看到程序打印了一堆断码,这其中的原因是什么呢,先要从栈的布局说起:

函数调用栈的简化布局如图所示(其实栈中还有一些其他无关紧要的数据,笔者在图中没有画出):

正常情况下输出函数的语句应该是(前提是a、b、c已经赋值):

printf(str,a,b,c)

这时栈中结构如下,程序在处理字符串时发现了三个%x,就会在栈中检索三个变量的位置:

如果没有输入这三个变量,程序同样会向下检索三个“变量”,栈中布局如下:

可以看到,我们竟然成功骗过程序,让其向下访问栈的地址空间,从而造成了内存泄漏。

理解基本原理后,我们看看其他格式化控制符:

%s :这个控制字符用于打印字符串,其原理是访问存放指向字符串的指针,进而从指针指向的位置打印“字符串”,直至打印到0x00这个截断符。

栈中的局部变量缓冲区存放字符串本身,而利用多个%s可以访问到局部变量缓冲区,如果输入的字符串是某个地址加上很多%s,当某一个%s访问到缓冲区字符串时,就会认为这个地址指向字符串,并打印这个地址空间的内容直至截断符,这样就做到了任意地址空间的访问。

%n 和 %hn :%n是一个很特殊的格式化控制符,其功能不是打印,而是将目前已打印的字符个数写入对应的变量,如果触发格式化字符串漏洞,%n会将栈中某个位置的数据修改为目前打印出来的字符的个数,%n是以DWORD的形式写入,%hn以WORD形式写入。通过控制输出字符的数量和%n在字符串中的位置,可以达到修改栈中的任意数据的效果,甚至是EBP,返回地址等关键数据。

(2)跳板技术

从汇编角度讲,在函数执行retn返回前,ESP刚好指向栈中存放返回地址的+0x4地址,若是发生栈溢出,将函数的返回地址覆盖为jmp/call esp的地址,剩下的部分覆盖为shellcode,程序就会在返回时自动跳转到shellcode地址,这种方法能够增加shellcode的写入空间,并且绕过ASLR。

3、详细分析

(1)基础分析

参考《漏洞战争》及其配套资料,安装VMware OVF Tool 2.1.0,将poc.ovf和exp.ovf放到安装路径中,命令行进入安装路径。

输入命令voftool poc.ovf:

可以看到终端先打印了一堆字符串后,系统报出内存访问错误,查看详细报告: 

报告中显示程序访问了错误的地址0x00000000。

在010 Editor中查看poc.ovf文件:

能够看到文件中存在一大段字符串,并且存在大量的格式控制符%08x,用于打印8位十六进制数(高位填充0)。

(2)静态分析

Ida分析

使用Ida打开ovftool,查看std::basic_ostream函数所在的源码:

v36 = v30[5];v20 = (int (__thiscall **)(_DWORD, _DWORD, _DWORD))(*(_DWORD *)v30[5] + 16);v21 = (*(int (__thiscall **)(int, int))(*(_DWORD *)v4 + 44))(v4, v19);v22 = (*v20)(v36, &v28, v21);v31 = 1;v23 = v22;v24 = sub_401A90(&dword_160C7D8, " - ");v25 = std::operator<<,std::allocator>(v24, v23);std::basic_ostream>::operator<<(v25, std::endl);   //此处没有对参数进行过滤,导致格式化字符串漏洞v31 = -1;std::basic_string,std::allocator>::~basic_string,std::allocator>(&v28);++v19;result = (*(int (__thiscall **)(_DWORD))(*(_DWORD *)v4 + 36))(v4)

可以看到std::basic_ostream函数没有对参数进行过滤,导致格式化字符串漏洞。

(3)动态分析

①分析poc.ovf

启动OD,设置调试-参数,输入poc.ovf,打开ovftool运行至结束,由于刚才的输入信息中包含Invalid value字符串,在反汇编窗口中右键-查找-所有参考文本字串:

找到“Invalid value”,双击转到引用字符串的命令,并在其附近设下断点:

可以看到附近的函数都是C++的std,继续F8运行数次后能够找到std::basic_ostream这个C++打印函数。

查看当前函数的EBP链:

 

可以看到整个函数调用栈的EBP链分别为:

0012FC1C - 0012FC74 - 0012FF50 - 0012FF7C - 0012FFC0 - 0012FFF0

单步步过这个函数后在查看EBP链:

 

0012FC1C - 0012FC74 - 0012FF50 - 00120345

可以明显看到0012FF50这个EBP指向的上一个栈的栈帧被修改为00120345,初步判断是由于格式化字符串造成的,打开101 Editor统计字符串。

"AAAAAAAAAAAAAAAAAAAAAAAAAA%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%hn"

通过统计得出字符串中共有26个'A',98个%08x和1个%hn,在%hn之前打印出的字符数量应为26 + 98*8 = 810,810的十六进制数刚好是0x345。通过%hn将EBP的第四位赋值为0345,使得EBP由0012FF7C被覆盖为00120345。

继续跟进知道EBP被赋值为00120345:

可以看到程序执行完00417AEF处的指令pop ebp后,EBP的值被覆盖为00120345,继续运行:

运行后ESP也被赋值为00120345,而此时00120345处的地址内容为00000000,在接下来的retn指令执行后,eip被修改为00000000,从而导致系统访问00000000这个无效地址,造成报错。

② 分析exp.ovf

与分析poc.ovf分析方式类似,将程序执行至std::basic_ostream这个函数,查看EBP链:

 

EBP链为:

0012FC1C - 0012FC74 - 0012FF50 - 0012FF7C - 0012FFC0 - 0012FFF0

步过函数后: 

 

可以看到EBP链被修改为:

0012FC1C - 0012FC74 - 0012FF50 - 00121000

EBP已经被修改为00121000,继续运行至ESP被修改为00121000:

继续运行pop ebp后,ESP值变为00121004,retn后eip被修改为00121004处的内容,查看00121004存放的地址7852753D对应的对应的反汇编:

反汇编为call esp,是一个跳板指令,能够将程序执行流劫持到00121008,在数据窗口中定位121008:

能够看到大量的字符串,将向上查找能够找到字符串的开始“znHt...”。

继续运行此处发现出现循环,并且内存中的字符串逐渐变为不可打印的字符: 

说明shellcode正在进行解码操作,继续跟进后寄存器窗口中出现相关函数及其参数,并跳出对话框。

缓解措施

更新软件。

漏洞字符串函数
本作品采用《CC 协议》,转载必须注明作者和本文链接
在我们学习c语言的时候我们就知道在输出或者输入的时候需要使用%s%d等等格式化字符,此处不过多介绍,详情可以去看看c语言的基础知识。
CTFer的周五之约, 蓝帽杯真题解析之四
开放虚拟机格式(Open Virtual Machine Format,OVF)是一种虚拟机分配格式,能够支持不同产品与组织之间共享虚拟机。 VMware OVF Tool是由VMware免费提供的一款支持虚拟的导入导出工具,支持以命令提示符的方式运行。
本篇针对该JS中的字符串混淆进行还原。字符串是如何混淆的解密方式想要对字符串反混淆就要先分析该样本是如何对字符串进行混淆的。而处于全局作用域的_0x1f1a68实际上也是对另一个函数的调用。
最近海康威视又一次因自身的漏洞被黑客利用而遭受攻击。
最近,研究人员发现了OriginLogger,这是一个基于Agent Tesla的恶意软件。OriginLogger的部分功能OriginLogger的全部功能此外,他们还展示了 Web 面板和恶意软件生成器。
mysql提权总结
2021-09-17 15:04:08
使用过MySQL的人都知道,MySQL有很多内置函数提供给使用者,包括字符串函数、数值函数、日期和时间函数等,给开发人员和使用者带来了很多方便。
二进制程序分析
2021-09-25 17:18:46
分析恶意软件的第一步是收集二进制程序在主机上执行的行为事件,研究人员根据这些行为大体形成一个思路来描述恶意软件的功能。 这包含应用释放或者从互联网下下载的文件,写入什么样的注册表、访问了什么网络地址,修改读写本地的什么文件等等。那么研究人员通过行为会确定恶意样本的类型。通常类型如下:
赛时有考虑过ret to dl_resolve的做法,在网上查了下也没发现有相关的文章,当时也没有详细研究,这次趁着期末考前有空,仔细琢磨了一下。
ftp程序,需要使用rxraclhm账号登录,提供了get、put、dir三个功能,分别读文件、上传文件、查看目录。
VSole
网络安全专家