CVE-2019-9729 冒险岛Online键盘保护驱动本地提权漏洞

前几天看到的一个漏洞,想来有趣,就翻译了一下,顺带跟着作者分析了一下这个漏洞

1. What is SdoKeyCrypt.sys?(什么是SdoKeyCrypt.sys)

SdoKeyCrypt.sys is a keyboard protection driver for a MMORPG, aka Massively-Multiplayer-Online-Role-Playing-Game, called MapleStory Online which is published by Shanda Group in China.

SdoKeyCrypt.sys是盛大冒险岛的一个键盘保护驱动

The game’s official website: http://mxd.sdo.com. (Language: Chinese)

官方站点:http://mxd.sdo.com

This driver will be downloaded and installed in C:\Windows\System32\ folder when the game runs first time. Because the game is very big, approximately 13.11 GB, here I made a backup SdoKeyCrypt.sys for anyone who wants to reproduce this exploit.

当冒险岛第一次运行的时候,这个驱动会安装在C:\Windows\System32\,因为游戏非常大,差不多13.11GB,所以我搞了一个备份文件方便大家复现这个漏洞

SdoKeyCrypt.sys is surely OFFICIAL and is NOT modified by anyone.

驱动SdoKeyCrypt.sys肯定是官方的而且没有被任何人修改过

You can see there’s a valid digest signature signed by Shanda Computer (Shanghai) Co., Ltd. which confirms SdoKeyCrypt.sys is indeed made by Shanda.

如图所示,它有盛大官方的数字签名,确定这个是盛大写的

IMAGE

2. What is the vulnerability caused by?(漏洞成因)

In IRP_MJ_DEVICE_CONTROL handle routine, when IOCTL code is (DWORD)(-0x7FFF3FFC + 0x18) = 0x8000c01c, the driver does not properly handle data passed from user space, which causes a size value can be negative so that a heap underflow will occur.

在该驱动的IRP_MJ_DEVICE_CONTROL里,当IOCTL Code为(DWORD)(-0x7FFF3FFC + 0x18) = 0x8000c01c的时候,没有正确处理好从用户空间传入的数据,导致可以指定这个值为一个负数,从而导致堆下溢

With the help of heap spraying, aka pool-Feng-Shui attack, one can disable SMEP and run any shellcode in kernel mode to make local privilege elevation.

攻击者可以使用堆风水绕过SMEP并且在内核执行shellcode,造成本地提权

IMAGE

IMAGE

3. How to use PoC code?

With x64 Microsoft Visual C++ compiler (which supports c++11)

$ cl poc.cpp /Fe:poc.exe /link /dynamicbase:no /fixed ntdll.lib

Tested on Visual Studio 2017 Community, the following is an example of output:

C:\Github\SdoKeyCrypt-sys-local-privilege-elevation>cl poc.cpp /Fe:poc.exe /link /dynamicbase:no /fixed ntdll.lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27027.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

poc.cpp
Microsoft (R) Incremental Linker Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:poc.exe
/dynamicbase:no
/fixed
ntdll.lib
poc.obj

Then make sure that SdoKeyCrypt.sys is loaded and run poc.exe directly. If nothing wrong, you should get a nt authority\system shell.

4. Screenshot

The PoC code has been tested and works fine on Win10 1709 and Win10 1803.

However it does not work on Win10 1809 which uses heap-backed pool that mitigates heap-spray attack. But it can cause BSOD, so there’s local Denial-of-Service vulnerability at least.

The following is a test video on Win10 1803 17134.619.

D9888CC4736FD461ECC616A080FC6CB0.gif

我尝试着在本地跟了一下,如下图所示,这里是DriverEntry,红色箭头所指的位置是IrpDeviceIoControl

IMAGE

跟入看到几个关键的变量

IMAGE

在case为0x18的地方,会调用函数sub_139E0,该函数第三个参数取传入的字符串偏移8字节位置的数据

IMAGE

这里的cbSize就是传入的第三个参数,这里分配内存,可以明显看到这里没有进行判断就直接使用了,如果我们传入的为-1cbSize+this->Length会大于0,通过此处的判断,下面for循环会直接跳过,在while循环里,Source[i++ + cbSize]会变成Source[-1],导致下溢

IMAGE

最近逆OLLVM后的APP,逆的头秃,看了下驱动这种不混淆的,突然感觉好开心!