在最近的补丁星期二中,WalletService修复了权限提升漏洞,其中一个漏洞被分配为CVE-2020-1362。该漏洞利用了服务中的越界错误。在此我们分享利用该漏洞的技术。
我们对walletservice.dll中的以下函数进行了二进制分析:
SetGroup函数将用户控制的数据写入用户控制的偏移量的内存中。
signed __int64 __fastcall Wallet::WalletCustomProperty::SetGroup(__int64 this, int a2, int a3, int a4)
{
signed __int64 result; // rax
result = 0i64;
if ( a2 == 1 )
{
if ( a3 & 0xFFFFFFDF )
return 0x80070057i64;
}
else if ( a3 == 0x20 )
{
return 0x80070057i64;
}
if ( a4 == -1 )
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = 0;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = 0x7FFFFFFF;
}
else
{
*(_DWORD *)(this + 8i64 * a2 + 0x74) = a3;
*(_DWORD *)(this + 8i64 * a2 + 0x78) = a4;
}
return result;
}
我们可以注意到该函数没有检查用户可以控制的偏移量的范围。这就是漏洞所在。
我们现在可以进行越界内存写入。通过观察,我们发现同一个类中存在设置和获取BSTR的函数:
因此我们可以轻松地通过oobw修改指向BSTR的指针,从而获得任意地址的读写能力。
一旦我们拥有WWW(任意写入任意地址),我们就可以写入堆上Wallet::WalletCustomProperty对象的vtable以控制RIP。起初,我们尝试直接通过oobw修改,但发现oobw未对齐到8字节。因此我们必须利用竞争条件进行两次写入才能完成vtable劫持,但这可能使漏洞利用不稳定。还有一些其他方法可以绕过这个问题。但在我们的POC中,我们使用了另一个信息泄露漏洞(CVE-2020-1361)来泄露堆地址,并使用www直接写入vtable。顺便说一句,虽然CVE-2020-1361被标记为信息泄露漏洞,但实际上它可以用来实现权限提升。我们将在未来撰写相关分析文章。
我们在dxgi.dll中找到了ATL::CComObject<CDXGIAdapter>::`vector deleting destructor函数,它帮助我们实现从执行任意函数到任意代码执行。该函数调用loadlibraryEx函数,并将全局指针作为loadlibraryEx的第一个参数。然后我们可以通过加载自定义dll来实现任意代码执行。
在POC目录中提供了一个示例POC。
通过该漏洞,我们可以实现从中等权限提升到NT AUTHORITY\system。
在Windows 10.0.18363.815, x64下测试

秦浩然
彭志宁(@edwardzpeng),奇虎360
2020年4月10日: 报告漏洞
2020年4月21日: MSRC调查并确认漏洞
2020年7月14日: 发布补丁
2020年7月17日: 发布分析报告