游乐游手机版
首页/网络安全/文章详情

手把手教你构造Office漏洞POC完整教程:以CVE-2012-0158漏洞为例

时间:2026-07-28 21:24
可以说,CVE-2012-0158作为经典的Office漏洞,凭借其稳定性和通用性,频繁出现在各类安全分析报告中。今天,我们将深入剖析这一漏洞,从原理到手动构造一个可触发的POC样本,全程逐步讲解。 漏洞原理 关于此漏洞的原理,网络上已有不少分析文章。通常的做法是获取一个真实样本,再定位二进制代码。

可以说,CVE-2012-0158作为经典的Office漏洞,凭借其稳定性和通用性,频繁出现在各类安全分析报告中。今天,我们将深入剖析这一漏洞,从原理到手动构造一个可触发的POC样本,全程逐步讲解。

漏洞原理

关于此漏洞的原理,网络上已有不少分析文章。通常的做法是获取一个真实样本,再定位二进制代码。我们这里不再重复这个流程,而是直接揭示漏洞的核心成因,但后续仍会简要演示调试过程。

该漏洞存在于Office的一个组件——MSCOMCTL.OCX中。多个版本的Office,该模块均存在相同问题。我们的测试环境以Windows XP + Office 2007为例。MSCOMCTL.OCX是Office解析ActiveX控件时调用的动态库。一旦文档中嵌入了按钮、列表、树形控件等ActiveX元素,Office打开文档时就会自动加载该库来解析和显示控件。

从漏洞类型来看,这属于经典的栈缓冲区溢出——准确地说,是栈内存拷贝溢出。当Office解析一个精心构造的控件(以ListView列表控件为例)时,就会发生栈内存的越界拷贝。下面的栈回溯图可以清晰展示整个触发过程:

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

可以看到,Excel在解析ListView控件时,读取并加载了控件的数据流。加载过程中会调用一个内部函数ReadBytesFromStreamPadded,该函数功能类似于memcpy,根据参数从指定内存拷贝指定大小的数据到目标缓冲区。不过,如果顺着调用链向上追溯就会发现,漏洞的真正元凶并不在这里,而是出在CObj::load函数中。我们来看看IDA反编译出的伪代码:

int __stdcall CObj__Load( int a1, void *lpMem)

{

int result; // eax@1

void *v3; // ebx@1

int v4; // esi@4

int v5; // [sp+Ch] [bp-14h]@1

SIZE_T dwBytes; // [sp+14h] [bp-Ch]@3

int v7; // [sp+18h] [bp-8h]@4

int v8; // [sp+1Ch] [bp-4h]@8

v3 = lpMem;

result = ReadBytesFromStreamPadded(&v5, lpMem, 0xCu ); //第一次正常拷贝,读取数据头

if ( result >= 0 )

{

if ( v5 == 'jboC' && dwBytes >= 8 ) //漏洞触发条件

{

v4 = ReadBytesFromStreamPadded(& v7, v3, dwBytes); //第二次拷贝,此处调用必然越界

if ( v4 >= 0 )

{

if ( ! v7 )

goto LABEL_8;

lpMem = 0;

v4 = ReadBstrFromStreamPadded(( UINT)&lpMem, (int )v3);

if ( v4 >= 0 )

{

CObj__SetKey((BSTR) lpMem);

SysFreeString((BSTR) lpMem);

LABEL_8:

if ( v8 )

v4 = ReadVariantFromStream(( struct tagVARIANT *)(a1 + 20) , (struct IStream *) v3);

return v4;

}

}

return v4;

}

result = 2147549183;

}

return result;

}

简而言之,CObj::Load用于加载CObj对象。它先从数据流中读取0x0c个字节到临时变量v5,然后检查v5前4个字节是否为“Cobj”以确认对象类型,同时检测dwBytes是否大于等于8。关键点在于:dwBytes这个值是在第一次读取那0x0c个字节时一并读入的。从IDA的变量注释可以看到,dwBytes在内存中正好位于v5之后,其值完全可以通过修改原始数据流来控制。

接下来,程序会再次从数据流中读取dwBytes个字节到临时变量v7。但v7的大小只有8个字节(从bp-0x08到bp-0x00)。而dwBytes本身大于8,这就意味着这次拷贝必然会覆盖到ebp,发生越界,从而形成栈溢出。

基于此分析可以推测,正常情况下,控件数据中读出的dwBytes不应大于8。如果大于8,栈拷贝就会异常,该漏洞早就被发现了。更值得注意的是,我在IDA中查看了这个函数的交叉引用,发现其作用很有限——只在加载特定几个控件时被调用。因此,我怀疑这未必是微软的一个“严重失误”,倒更像是故意留下的后门。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

构造触发漏洞的POC

原理已经厘清:Office解析ListView控件时,会调用漏洞函数CObj::Load,该函数在加载CObj对象时,会用我们可控的dwBytes值去拷贝数据到一个只有8字节的临时变量里——关键是,它连基本的校验都没有。为了验证这一分析,我们按图索骥,动手构造一个能触发漏洞的Excel文档。

首先,Excel文档中需要有一个ListView控件,这可以通过开发者工具添加。添加完成后,文档中就有了一个空的ListView对象。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

接下来,还需要往该控件中添加ListItems和ListItem子对象,这样才能让Excel程序调用CObj::Load。不过这里有一个难点:ListItem对象无法直接通过Excel界面操作添加——Excel只能通过ListView控件的属性添加列表标题,没有直接添加列表内容的入口。解决办法是使用VBA代码生成。但这样做又会引出另一个问题:如果文档包含宏代码,Excel默认会禁用宏,导致无法解析ListItem对象。

一个简单粗暴的应对方法是:先编写并运行代码,生成初始化好的ListView控件,然后将所有生成代码删除再保存。宏代码会被阻止执行,但已经生成的控件对象不会被阻止解析。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

完成这一步后,用十六进制编辑器打开保存好的文档,定位到CObj对象的数据区,将偏移量为8的dwBytes值改成一个大于8的数,理论上就能触发漏洞。不过只修改这一个值,你会发现它并未触发。原因是拷贝函数ReadBytesFromStreamPadded还会再做一次校验——它会从待拷贝的数据头部再读取一个dwBytes值,检查两个值是否相等。因此,我们只需要将对象数据中的那个同名字段也改成同样的大小,就能顺利绕过校验,触发漏洞。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

触发漏洞后,由于我们只是用随机数据覆盖了ebp和函数的返回地址,Excel最终会弹出一个经典的“程序错误”提示框——这正是我们想要的效果。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

漏洞利用

现在,我们手上有了一个可以稳定触发的栈溢出漏洞。接下来如何利用,就看各位的发挥了。这里我们还是老规矩——弹个计算器,抛砖引玉。

通过前面构造的POC,我们可以通过修改那两个dwBytes的值以及后面的数据,来控制运行栈的内存布局。为了更精准地编排数据,最好边调试边修改,最后将内存中排好的数据拷贝回文档的对应位置。调试阶段,第一目标自然是控制程序流程——拿到EIP的控制权。通常的做法是覆盖函数返回值或者SEH链指针。由于MSCOMCTRL.DLL没有开启GS保护,我们直接用最简单的覆盖函数返回值就能控制EIP。不过,为了让程序顺利走到返回地址,还需要调整数据,满足一些返回条件,引导程序流程绕过那些复杂的指令操作集,避免因栈被破坏而触发异常。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

一旦程序顺利抵达返回地址,剩下的就随意发挥了——可以是构造ROP链绕过DEP保护,也可以直接跳转到栈空间执行代码。对于懂漏洞利用的人来说,这些都是基本功。这里有一个额外要求:栈内存上的数据需要有足够的空间来容纳ROP链或者Shellcode。因此,需要将ListView控件的数据规模做大——方法很简单,在添加ListItem时把字符串写长一点即可。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

所有必要条件都凑齐后,代码就可以放进栈中执行了。这里使用一个通用的跳转地址,直接跳到栈内存代码上执行。由于XP + Office 2007默认不开启DEP保护,计算器顺利弹出。

手把手教你如何构造Office漏洞POC(以CVE-2012-0158为例)

至于如何编写ROP链来突破Office 2010及以上版本默认开启的DEP保护,以及更多高级利用技巧,我们会在后续的漏洞分析中继续展开。

总结

通过这一番分析,我们对该漏洞的原理和危害性有了透彻的了解。MSCOMCTL.OCX本身是一个基础动态库,影响面非常广——除了Office整套产品外,SQL Server以及其他第三方应用,只要依赖这个库,都可能被利用。而利用的思路与本文一致,万变不离其宗:构造的“畸形”数据必须能通过漏洞函数的检验流程,最终绕过程序本身的限制,夺取控制权。

来源:https://www.jb51.net/hack/497864.html
上一篇搜狐微博CSRF漏洞分析与修复方案 下一篇Nmap备忘单第一章从探索到漏洞利用
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
DDoS攻击的三大主要形式:原理、特征与防御重点
网络安全 · 2026-08-31

DDoS攻击的三大主要形式:原理、特征与防御重点

DDoS攻击主要分为基于流量(Volume)、基于应用层(Application)和基于协议(Protocol)三种形式。流量型攻击通过海量数据淹没带宽;应用层攻击利用Web漏洞耗尽服务器资源;协议层攻击则利用TCP握手缺陷导致系统挂起。了解这些原理是制定针对性防御策略的基础。

如何有效预防和缓解DDoS攻击:5大核心策略详解
网络安全 · 2026-08-31

如何有效预防和缓解DDoS攻击:5大核心策略详解

面对DDoS攻击,单纯增加带宽已非长久之计。本文详解5大核心防护策略:优化网络硬件配置、建立DNS冗余机制、部署透明缓解技术、引入负载平衡器及专用Anti-DDoS模块。通过合理组合这些技术手段,可有效抵御SYN泛洪、Slowloris等常见攻击,保障业务连续性与网站可用性。

DDoS防护四大误区:CDN、防火墙与黑名单的局限性解析
网络安全 · 2026-08-31

DDoS防护四大误区:CDN、防火墙与黑名单的局限性解析

许多企业误以为CDN、防火墙或黑名单能完全抵御DDoS攻击。本文深入解析四大常见误区:CDN仅提供部分缓解、静态黑名单易失效、防火墙算力有限且可能成为目标、阈值警报仅具滞后性。了解这些局限性,有助于构建更立体的防御体系,避免在攻击发生时措手不及。

常见DDoS攻击类型详解:原理、特征与防御策略
网络安全 · 2026-08-31

常见DDoS攻击类型详解:原理、特征与防御策略

本文详细解析四种常见DDoS攻击类型:SYN Flood利用TCP三次握手缺陷耗尽资源;UDP Flood通过海量数据包造成带宽拥塞;ICMP Flood利用Ping请求消耗系统算力;应用层Flood针对Web脚本进行高频请求。了解其原理是制定有效防御策略的基础。

如何有效抵御DDOS攻击:4种核心防护方案解析
网络安全 · 2026-08-31

如何有效抵御DDOS攻击:4种核心防护方案解析

面对DDOS攻击,企业需构建多层防护体系。本文详解四大核心策略:利用反向路由器查询进行流量清洗,通过GCDN智能分配节点隐藏源站IP,部署负载均衡硬件分担压力,以及接入高防机房抵御数百G恶意流量。掌握这些技术,可最大程度保障业务连续性。