In two previous blog posts I've described 32-bit plugin that was mentioned by Kaspersky in their technical analysis. The plugin is called kgate and it has some interesting features, including, exploiting 32-bit Agnitum driver to run rootkit driver, run 32-bit or 64-bit kernel mode code by non-standart way. It's hard to say how stable this code works on live system, because authors use undocumented Windows kernel functions like ObCreateObject and ObInsertObject for creating new DriverObject.
There is one more 64-bit plugin that is called xkgate and it is used for compromising 64-bit Windows versions. Unlike kgate plugin, xkgate contains valid timestamp in PE header - 20 Aug 2014 (08:34:04). Both plugins contain code with identical functions in their .krwkr64 and .krdrv64 sections, but looks like xkgate plugin was written later than kgate. Although, kgate plugin has zeroed timestamp in PE-header, its file contains one timestamp inside - Oct 28 2013. This means that operators have switched from kgate plugin, which was developed to load Ring 0 code for both x32 and x64 platforms, to special edition for x64 that is called extended kgate.
Like kgate plugin, xkgate also contains timestamp inside its file - Aug 19 2014. This timestamp confirms for us that date of compilation in PE header of xkgate is valid, although they differ by one day. I think the reason for this difference is that timestamp inside file contains time data for debug purpose and was set by authors in manual mode. Screenshot below shows this fact.
The plugin also contains Ring 0 code in two separate sections named .krwkr64 and .krdrv64. Section .rdata stores whole AVAST! Virtualization Driver file aswsnx.sys, which is used by xkgate for loading own kernel mode. Section .avit contains code for communication with AVAST driver from "trusted" process.
Below you can see information about digital signatures of legitimate drivers Outpost and AVAST! that have been used by Remsec authors for loading Ring 0 code.
According to the language that has been used in debug comments for both plugins, authors were native English speakers. But it is not clear why they don't remove debug information from it. Below you can see strings, which are present into xkgate.
Load error: Access Denied
Load error: Unsupported OS
Load error: Invalid plugin image format!
Load error: Plugin entry point not found!
Load error: Failed to resolve kernel functions!
Load error: Out of memory!
Load error: Status unsuccessful!
Load error: Failed to run plugin (%#x)
Unsupported OS! Only Windows 2000 and later supported!
Unable to determine 32/64-bit OS!
Invalid plugin name: path not allowed, try using -n.
Invalid plugin name: suffix not allowed, try using -n.
Unable to load kernel plugin %s!
Unable to build argv!
Plugin successfully executed!
GateDriver is currently disabled on x64 systems due to driver signing restrictions!
In table below you can see characteristics of both plugins.
From the table above you can see that some IOCTLs functions are not used by attackers.
As I mentioned above, xkgate leverages Avast driver for executing Ring 0 code which doesn't drop to FS. There is function fnLoadAvast that is responsible for loading Avast driver in proper way. It also does some actions for reproducing correct environment for it. Unlike exploiting Agnitum driver, this situation is more hard for exploitation. Let's look more detailed.
First action that fnLoadAvast does, it tries to create mutex with name Global\yRg7d3x and checks a result of WaitForSingleObject to prevent doing same actions again.
Next, the code calls fnDropAvastDriverAndPrepareEnv function that does following actions:
There is one more 64-bit plugin that is called xkgate and it is used for compromising 64-bit Windows versions. Unlike kgate plugin, xkgate contains valid timestamp in PE header - 20 Aug 2014 (08:34:04). Both plugins contain code with identical functions in their .krwkr64 and .krdrv64 sections, but looks like xkgate plugin was written later than kgate. Although, kgate plugin has zeroed timestamp in PE-header, its file contains one timestamp inside - Oct 28 2013. This means that operators have switched from kgate plugin, which was developed to load Ring 0 code for both x32 and x64 platforms, to special edition for x64 that is called extended kgate.
Like kgate plugin, xkgate also contains timestamp inside its file - Aug 19 2014. This timestamp confirms for us that date of compilation in PE header of xkgate is valid, although they differ by one day. I think the reason for this difference is that timestamp inside file contains time data for debug purpose and was set by authors in manual mode. Screenshot below shows this fact.
The plugin also contains Ring 0 code in two separate sections named .krwkr64 and .krdrv64. Section .rdata stores whole AVAST! Virtualization Driver file aswsnx.sys, which is used by xkgate for loading own kernel mode. Section .avit contains code for communication with AVAST driver from "trusted" process.
Below you can see information about digital signatures of legitimate drivers Outpost and AVAST! that have been used by Remsec authors for loading Ring 0 code.
According to the language that has been used in debug comments for both plugins, authors were native English speakers. But it is not clear why they don't remove debug information from it. Below you can see strings, which are present into xkgate.
Load error: Access Denied
Load error: Unsupported OS
Load error: Invalid plugin image format!
Load error: Plugin entry point not found!
Load error: Failed to resolve kernel functions!
Load error: Out of memory!
Load error: Status unsuccessful!
Load error: Failed to run plugin (%#x)
Unsupported OS! Only Windows 2000 and later supported!
Unable to determine 32/64-bit OS!
Invalid plugin name: path not allowed, try using -n.
Invalid plugin name: suffix not allowed, try using -n.
Unable to load kernel plugin %s!
Unable to build argv!
Plugin successfully executed!
GateDriver is currently disabled on x64 systems due to driver signing restrictions!
In table below you can see characteristics of both plugins.
From the table above you can see that some IOCTLs functions are not used by attackers.
As I mentioned above, xkgate leverages Avast driver for executing Ring 0 code which doesn't drop to FS. There is function fnLoadAvast that is responsible for loading Avast driver in proper way. It also does some actions for reproducing correct environment for it. Unlike exploiting Agnitum driver, this situation is more hard for exploitation. Let's look more detailed.
First action that fnLoadAvast does, it tries to create mutex with name Global\yRg7d3x and checks a result of WaitForSingleObject to prevent doing same actions again.
Next, the code calls fnDropAvastDriverAndPrepareEnv function that does following actions:
- Creates directory \SystemRoot\Temp\aswSnx for dropping AVAST related files.
- Drops aswSnx.sys to FS.
- Drops snx_lconfig.xml to FS.
- Drops snx_gconfig.xml.
- Creates empty file snxhk.dll.
- Creates aswSnx.exe and writes to it content of notepad.exe.
Next, fnLoadAvast calls fnCreateAvastServiceAndLoadDriver for creating AVAST service key in registry.
- It creates key System\CurrentControlSet\Services\aswSnx.
- Creates parameter ImagePath with path to \SystemRoot\Temp\aswSnx\aswSnx.sys.
- Creates parameter Type.
- Creates subkey Parameters.
- Creates parameter DataFolder inside subkey with value \??\Global\GLOBALROOT\SystemRoot\Temp\aswSnx.
- Creates parameter ProgramFolder with value \??\Global\GLOBALROOT\SystemRoot\Temp\aswSnx.
- Creates key subkey Instances.
- Creates parameter DefaultInstance inside Instances key.
- Creates parameters Altitude and Flags.
- Loads aswSnx.sys with NtLoadDriver.
After aswSnx.sys was loaded, fnLoadAvast removes snxhk.dll and snxhk64.dll files from FS with help of NtSetInformationFile. Next step is creating process aswSnx.exe, which actually is notepad.exe. After that it opens handle on AVAST device \Device\aswSnx.
After creating aswSnx.exe (notepad) process in suspended state, it duplicates handle to \Device\aswSnx from current plugin process into new process aswSnx.exe. As you already guessed, next step is copying code for communicating with AVAST driver into aswSnx.exe. Copied code is located in special .avit section and performs DeviceIoControl that triggers code execution of Ring 0 rootkit code from AVAST driver.
Into loaded Ring 0 code, we can see already known to us function for dispatching FastDeviceControl request.
As you can see, both Agnitum and AVAST! drivers became exploitable for Remsec authors, because both don't use check of caller process based on digital signature properly. Although, notepad.exe is signed with Microsoft digital certificate that means AVAST! can check digital signature of caller process in IRP_MJ_CREATE handler, but doesn't check the name of signer.
As you can see, both Agnitum and AVAST! drivers became exploitable for Remsec authors, because both don't use check of caller process based on digital signature properly. Although, notepad.exe is signed with Microsoft digital certificate that means AVAST! can check digital signature of caller process in IRP_MJ_CREATE handler, but doesn't check the name of signer.