深圳北方裕盛代怀网

50多岁失独借卵 > 怀孕产子 > “震网”三代和二代漏洞技术分析报告

“震网”三代和二代漏洞技术分析报告

时间:2023-02-27 作者:admin 阅读:962
标签:

0x01概述

2017年6月份微软补丁发布了一个针对Windows系统处理LNK文件过程中发生的远程代码执行漏洞,通用漏洞编号CVE-2017-8464。当存在该漏洞的电脑被插上存在漏洞文件的U盘时,不需要任何额外操作,漏洞攻击程序就可以借此完全控制用户的电脑系统。同时,该漏洞也可借由用户访问网络共享、从互联网下载、拷贝文件等操作被触发和利用攻击。

与2015年的CVE-2015-0096上一代相比,CVE-2017-8464利用触发更早,更隐蔽。

早,指的是U盘插入后即触发,而前代需要在U盘插入后浏览到.lnk文件。

隐蔽,指的是本代.lnk文件可以藏在层层(非隐藏的)文件夹中,不需要暴露给受害人见到。

程序层面讲,CVE-2015-0096利用点是在explorer需要渲染.lnk文件图标时,而CVE-2017-8464利用点在于.lnk文件本身被预加载时显示名的解析过程中。

本文中,笔者将对这两个漏洞从漏洞的复现和反漏洞技术检测的防御角度进行剖析。本文是笔者在2017年6月份,没有任何PoC的情况下作的一个探索。

0x02CVE-2017-8464原理

CVE-2017-8464利用能够成功实现基于以下3点:

对控制面板对象的显示名解析未严格认证此对象是否为已注册的控制面板应用。

恶意构造的.lnk文件能够实现使explorer注册一个临时控制面板应用对象。

如上.lnk文件能够将步骤2中注册的临时对象的随机GUID值传输至步骤1所述之处进行解析。

本次利用原理就是由于在解码特殊文件夹时,能够有机会按上述3点完成触发。

细节见0x02节。

(显示名解析,参见IShellFolder::ParseDisplayName,以及shell对外的接口SHParseDisplayName。)

0x03还原

首先,猜下问题点出现在中。

通过diff比对分析,可以得知问题点有极大概率是存在于函数CControlPanelFolder::_GetPidlFromAppletId中的如下代码:

“震网”三代和二代漏洞技术分析报告

易知CControlPanelFolder::_GetPidlFromAppletId的上层函数是CControlPanelFolder::ParseDisplayName。

看名字大约理解为解析显示名,这很容易关联到shell提供的接口SHParseDisplayName,查MSDN可知此函数的功能是把shell名字空间对象的显示名(字符串)转换成PIDL(项目标识符列表的指针,我更喜欢称其为对象串烧)。

(那么PIDL大约长这样子:2-byteslength,(length-2)bytescontents,2-byteslength,(length-2)bytescontents,…,2-byteslength(=0)。实例:00410000)

中调用SHParseDisplayName的地方有很多,先验证下从SHParseDisplayName能否连通到目标CControlPanelFolder::ParseDisplayName。(另外shell32里还有个ParseDisplayNameChild效用也是差不多)

建立一个例子小程序工程,代码大概如下:

“震网”三代和二代漏洞技术分析报告

至于填充names的素材,网上可以搜索到很多,注册表里也容易找到不少:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions

这个地方似乎有不错的货源:

调试发现类似这样的名字可以满足要求:

L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\C:\\"

如第一张图片中,把想要加载的动态库路径传入到CPL_LoadCPLModule就成功了。但这里,虽然从SHParseDisplayName出发,就能把文件路径送到CControlPanelFolder::ParseDisplayName-CControlPanelFolder::_GetPidlFromAppletId。但CControlPanelFolder::_GetPidlFromAppletId之前还有CControlPanelFolder::_GetAppletPathForTemporaryAppId这一头拦路虎:

“震网”三代和二代漏洞技术分析报告

这段代码的大概意思是要检查一下传过来的名字是否在它的临时应用识别列表里面,若是则返个对应的路径名回来(显示名-实际路径)。

跟一下,发现它要对比的检查项,是一个GUID。

通过CControlPanelFolder::s_dsaTemporaryAppId这个标识符,容易得知,这个GUID是仅在CControlPanelFolder::_GetTemporaryAppIdForApplet中随机生成的:

“震网”三代和二代漏洞技术分析报告

这就尴尬了,也就是说,我们用SHParseDisplayName把动态库路径直接传到这里是不行的。我们需要先去触发CControlPanelFolder::_GetTemporaryAppIdForApplet函数,然后再把GUID替换掉动态库路径,再传过来。

就是说,如果我们先调用某个函数以参数L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\C:\\"触发CControlPanelFolder::_GetTemporaryAppIdForApplet,并从explorer内存中”偷”到那个随机GUID。再以L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\{{GUID}}"为参数调用SHParseDisplayName,就可以成功加载(如果C盘根目录真的有)了。

好吧,那么就来看看哪个函数可以先行触发CControlPanelFolder::_GetTemporaryAppIdForApplet来添加随机GUID。

容易得到它的上层函数是CControlPanelFolder::GetDetailsEx。

在之前的分析过程中,有个猜测:CRegFolder似乎是一系列CxxxFolder类的分发类,可以在CControlPanelFolder::GetDetailsEx和CRegFolder同名类函数上下断,搞几下就能得到一票撞过来的断点。

“震网”三代和二代漏洞技术分析报告

栈回溯中最惹眼的显然就是DisplayNameOfW了。

那么,现在如果能结合DisplayNameOfW和SHParseDisplayName,应该就能实现我们的目标,把.lnk中指定的.dll跑起来了。

不妨写个小程序验证一下是否属实:

“震网”三代和二代漏洞技术分析报告

其中ucIDList就是L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\C:\\"转换成PIDL的样子。

DisplayNameOfW参数0x8001表示返回目标路径,0x8000表示返回全路径。

跑起来有点小意外,stupid并没有被加载。

原因是加载之前有一段代码检测PSGetNameFromPropertyKey(PKEY_Software_AppId,ppszCanonicalName);是否成功。在explorer里这句是成功的,自己的小程序跑则失败。

好吧,这不是重点。那么把这段程序load到explorer里去跑下,果然成功了,被加载。或者在PSGetNameFromPropertyKey下断,把返回值改为0,也可以成功跑出stupid。

至此,我们知道,只要能来一发DisplayNameOfW+SHParseDisplayName连续技,就可以成功利用。

“震网”三代和二代漏洞技术分析报告

接着,在CPL_FindCPLInfo-CPL_ParseCommandLine-CPL_ParseToSeparator中我们又可以将上面使用过的大长文件名截断为短文件名,因为CPL_ParseToSeparator中除了使用”,”作为分割符,也是包含了空格符。

切成短名字,是为了过CPL_LoadCPLModule函数中的:

这里有返回值检查,超长的话就返回了。

我们的0x101长度名字,是不能在尾部附加一串”.manifest”的。

过了它,我们的短名dll(如果存在的话)就真的被加载起来了。

所以,这个利用需要用到一长名一短名双文件技巧。

长名文件任意内容,0字节都可以,只是被检测一下存在性。

比如:

3.dll3333333300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000

(注意dll后面有个空格)

短名文件(真正加载的就是它了):3.dll

.lnk里指定那个长名字就好了。

Hf,全文完!

最新推荐

相关文章

热门资讯

返回顶部