导航菜单

t0187067c61ab79ddae

 

作者:bybye@知道创宇404实验室

漏洞背景

WalletServiC++e 服务是 windows 上用来持有钱包客户端所使用的对象的一个服务,只存在 windows 10 中。

CVE-2020-1362 是 WalletService 在处理 CustomProperty 对象的过程中出现了越界读写,此漏洞可以导致攻击者获得管理员权限,漏洞评级为高危。

微软在 2020 年 7 月更新对漏洞发布补丁。

 

环境搭建

  1. 复现环境:windows 10 专业版 1909 (内部版本号 18363.815)
  2. 设置 WalletService 服务启动类型为自动

t01b43774783a2a5f43

  1. 调试环境:windbg -psn WalletService 即可。

 

漏洞原理与分析

漏洞点是设置 CustomProperty 对象的 Group 的 get 方法和 set 方法没有检查边界。

  1. get 方法的 a2 参数没有检查边界导致可以泄露堆上的一些地址。 t012e1b9da9dbf588d3
  2. set 方法的 a2 参数没有检查边界,可以覆盖到对象的虚表指针,从而控制程序流。 t019971f8b116742891

 

漏洞利用过程

创建 CustomProperty 对象

WalletService 服务由 WalletService.dll 提供,WalletService.dll 实际上是一个动态链接库形式的 Com 组件,由 svchost.exe 加载。我们可以在自己写的程序(下面称为客户端)中使用 CoCreateInstance() 或者 CoGetClassObject() 等函数来创建对象,通过调用获得的对象的类方法来使用服务提供的功能。

如何创建出漏洞函数对应的对象呢?最简单的办法是下载 msdn 的符号表,然后看函数名。

我们想要创建出 CustomProperty 对象,IDA 搜索一下,发现有两个创建该对象的函数:Wallet::WalletItem::CreateCustomProperty() 和 Wallet::WalletXItem::CreateCustomProperty()。

t012bef9165e573e00e

所以我们创建一个 CustomProperty 需要一个 WalletXItem 对象或者 WalletItem 对象,那么使用哪个呢?继续用 ida 搜索 CreateWalletItem 或者 CreateWalletXItem,会发现只有 CreateWalletItem。

t01f32820bf26f139aa

那到这里我们需要一个 WalletX 对象,继续用 ida 搜索会发现找不到 CreateWalletX,但是如果搜索 WalletX,会发现有个 WalletXFactory::CreateInstance(),如果有过 Com 组件开发经验的同学就会知道,这个是个工厂类创建接口类的函数,上面提到的 CoCreateInstance() 函数会使 WalletService 调用这个函数来创建出接口类返回给客户端。

t017e1f453a86d8747c

那么如何调用 WalletXFactory::CreateInstance() 并创建出 WalletX 对象呢?我们需要在客户端使用 CoCreateInstance() 。

HRESULT CoCreateInstance(
REFCLSID rclsid, // CLSID,用于找到工厂类
LPUNKNOWN pUnkOuter, // 设置为 NULL 即可
DWORD dwClsContext, // 设置为 CLSCTX_LOCAL_SERVER,一个宏
REFIID riid, // IID, 提供给工程类,用于创建接口类实例
LPVOID *ppv // 接口类实例指针的地址
);

首先,我们需要 WalletXFactory 的 CLSID,可以使用 OLEViewDotNet 这个工具查看。

t0172475e94452dcb95

其次,我们需要一个 WalletX 的 IID,这个可以用 ida 直接看 WalletXFactory::CreateInstance() 这个函数。

t017d5a3bb85c6bbbaf

有了 WalletXFactory 的 CLSID 和 WalletX 的 IID,然后在客户端调用 CoCreateInstance(),WalletService 就会调用 CLSID 对应的工厂类 WalletXFactory 的 CreateInstance(), 创建出 IID 对应的 WalletX 对象,并返回对象给客户端。

然后按照上面的分析,使用 WalletX::CreateWalletItem() 创建出 WalletItem 对象,然后使用 WalletItem::CreateCustomProperty() 创建出 CustomProperty 对象。

对于上面的步骤有疑问的同学可以去学一学 Com 组件开发,尤其是进程外组件开发。

伪造虚表,覆盖附表指针

由于同一个动态库,在不同的进程,它的加载基址也是一样的,我们可以知道所有dll里面的函数的地址,所以可以获得伪造的虚表里面的函数地址。

那么把虚表放哪里呢?直接想到的是放堆上。

但如果我们继续分析,会发现,CustomProperty 类里面有一个 stRing 对象,并且可以使用 CustomProperty::SetLabel() 对 string 类进行修改,所以,我们可以通过修改 string 类里面的 beg 指针 和 end 指针,然后调用 CustomProperty::SetLabel() 做到任意地址写。

t01acf285f31d75b3d2

有了任意地址写,我们选择把虚表放在 WalletService.dll 的 .data 节区,以避免放在堆上可能破坏堆上的数据导致程序崩溃。

控制程序流到 LoadLibrary 函数

使用伪造 vtable 并覆盖虚表指针的办法,我们可以通过调用虚函数控制 WalletService 的程序流到任意地址了。

那么怎么提权呢?在 windows 服务提权中,通常的办法是把程序流控制到可以执行 LoadLibrary() 等函数来加载一个由我们自己编写的动态链接库,因为在加载 dll 的时候会执行 dll 里面的 DllMAIn(),这个方法是最强大的也是最实用的。

这里使用漏洞提交者的方法,把虚表的某个地址覆盖成 dxgi.dll 里面的 ATL::CComObject\<CDXGIAdAPTer>::`vector deleting destructor(),因为这个函数调用的 LoadLibraryExW() 会使用一个全局变量作为想要加载的 dll 的路径。

t018d2d5bd7e91af01c

我们可以通过上面的 SetLabel() 进行任意地址写,修改上图的全局变量 Src,使其指向我们自己实现的动态链接库的路径,然后调用对应的虚表函数,使程序流执行到 LoadLibrarExW() 即可。

实现一个动态链接库

在 DllMain() 里面写上我们希望以高权限执行代码,然后调用虚表里面对应的函数是 WalletService 的程序流运行到 LoadLibraryEx() 即可。

注意,因为 windows 服务运行在后台,所以需要在 DllMain() 里面使用命名管道或者 socket 等技术来进行回显或者交互,其次由于执行的是 LoadLibraryExW(),所以这里的 dll 路径要使用宽字符。

其它

在控制虚表函数程序流到 LoadLibraryExW() 时,需要绕过下面两个 check。

第一个是需要设置 this+0x80 这个地址的值,使得下面的 and 操作为 true。

t017f7fecb09b2b33b6

第二个是要调整 qword_C5E88 和 qword_C5E80 是下面的变量 v4 指向具有写权限的内存。

t013cb2824000a42450

 

漏洞利用结果

可以获得管理员权限

t01c99bbfe40422ca5e

 

补丁前后对比

可以看到,打了补丁之后,get 方法和 set 方法都对 a2 参数添加了边界检测。

t01110ba9920b0abee9

t013b9da0df8dc64d88

参考链接

[1] PoC链接[2] 微软更新公告[3] nvd漏洞评级

本文由知道创宇404实验室原创发布转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/212011

相关推荐

CVE-2020-0904:Hyper-V类型混淆任意地址解引用漏洞分析

译文声明 本文是翻译文章,文章原作者Daniel Fernandez Kuehr,文章来源:labs.bluefrostseC++urity.de 原文地址:https://labs.bluefrostsecurity.de/advisories/bfs-sa-2020-003/ 译文仅供参考,具体内容表达以...

JustSystems Ichitaro(一太郎)缓冲区溢出漏洞

  漏洞简介 IC++hitaro(一太郎)是日本JustSystems公司的一套文字处理软件。 JustSystems Ichitaro在处理JTD文档的过程中存在基于堆的缓冲区溢出漏洞,允许远程攻击者可利用该漏洞构建恶意文件,诱使用户解...