Remsec driver analysis

8 years ago 150
BOOK THIS SPACE FOR AD
ARTICLE AD
Remsec or Cremes malware already was perfectly described by Kaspersky in their report. Symantec also did a blog post about it. This sophisticated malware toolkit refers to so-called state-sponsored actor, which was named by KL as ProjectSauron or Strider by SYMC. There are some similarities between Remsec and other serious state-sponsored projects like EvilBunny (Animal Farm) or Flame (Equation Group). The toolkit contains a lot of modules for cyberespionage. As already declared by the Russian special service (FSB), the attackers have used unique malware files in case of each victim. This means that attacks were implemented in highly targeted manner.
One of the malware components was not described by KL or other AVers. This component is a driver and it works into kernel mode (Ring 0). Frankly speaking, the driver has compact size and is designed only for one purpose: execute Ring 3 code from kernel mode with SMEP bypass. Nothing special, but...The quality of written code confirms for us the fact that driver was written by skilled developers and intended to be hidden. These properties are ideally suited to the task the malware should perform.

Below are listed the facts about the driver (aswfilt.dll).
It has small size and fits in one memory page (4KB).It has the zeroed timestamp and one unnamed NONPAGED section.It has dynamic imports that is stored into special driver struct with ptr at DeviceObject->DeviceExtension.The code uses some sort of offsets obfuscation inside its body.The code is written in right way.
The driver is loaded into a system by the dropper that exploits vulnerability in Agnitum driver called Sandbox.sys. The dropper contains inside itself driver file, file of Agnitum Sandbox.sys and code for its exploitation. Below you can see part of the dropper that drops Sandbox.sys to disk.
After loading Agnitum Sandbox.sys, it sends to it a special IOCTL that forces it to load the rootkit driver.

The rootkit driver creates device with name \Device\rwx and the client uses path  \\.\GLOBALROOT\Device\rwx to communicate with it.
To disable SMEP, the client should sent to driver IOCTL with code 0x1173000C.
Note that unlike developers of Capcom.sys driver, authors of Remsec disables SMEP in right way.
Next structure describes DeviceContext that is used by rootkit as storage for run-time global data.

struct RootkitStruct {

PVOID  ExAllocatePool;
PVOID  ExFreePool;
PVOID  IoCompleteRequest;
PVOID  IoCreateDevice;
PVOID IoDeleteDevice;
PVOID KeAcquireSpinLock;
PVOID KeCancelTimer;
PVOID KeInitializeEvent;
PVOID KeInitializeSpinLock;
PVOID KeInitializeTimer;
PVOID KeQueryInterruptTime;
PVOID KeReleaseSpinLock;
PVOID KeSetEvent;
PVOID KeSetTimer;
PVOID KeWaitForMultipleObjects;
PVOID ObfReferenceObject;
PVOID ObDereferenceObject;
PVOID PsCreateSystemThread;
PVOID PsGetVersion;
PVOID PsTerminateSystemThread;
PVOID ZwClose;
PVOID ZwCreateKey;
PVOID ZwDeleteKey;
PVOID ZwEnumerateKey;
PVOID ZwOpenKey;
PVOID ZwSetValueKey;
PVOID ZwUnloadDriver;
PVOID KeQueryActiveProcessors;
PVOID KeSetSystemAffinityThread;
PVOID KeRevertToUserAffinityThread;
ULONG Flag;
KEVENT Event;
ULONG dwField1;
KTIMER Timer;
KSPIN_LOCK SpinLock;
ULONG dwField2;
LARGE_INTEGER IntervalTime;
UNICODE_STRING unDriverRegistryPath;
};

The driver supports an interesting method of unloading. It creates additional thread in DriverEntry and supports timer object for unloading from this thread. As there are two possible threads which can compete for the possession of the object, the driver supports special spinlock object. This object is captured each time when function wants to get access to timer. The timer interval can be set by client with special IOCTL code 0x117300CC. Timer guarantees the client that driver will unload as soon as possible.
Driver plays with spinlock in next manner. Before executing code in IRP_MJ_DEVICE_CONTROL handler, the rootkit cancels timer and set it again before exiting from it. 

KeAcquireSpinLock();
Flag1 = DeviceExtension->Flag1;
Flag2 = DeviceExtension->Flag2;
if( Flag1 & Flag2 ) {
   KeSetTimer();
}
KeRelaseSpinLock();

And

KeAcquireSpinLock();
Flag1 = DeviceExtension->Flag1;
Flag2 = DeviceExtension->Flag2;
if( Flag1 & Flag2 ) {
   KeCancelTimer();
}
KeRelaseSpinLock();

The thread waits on timer and executes cleanup after time has elapsed.



Driver also has function with name fnRemoveRegKeyTree that recursively removes registry key.

As it became clear from the analysis, the driver is intended for one purpose: execute function from user mode address space and next, unload as fast as possible. Driver's code uses spinlock and this is reason why authors are forced to use nonpaged section, that's untypical for such type of drivers.

UPDATE
I noticed interesting thing in procedure of driver unloading that looks like mistake for me. Let's look at this situation in more detail.

As I already mentioned above, the driver supports unloading procedure when some conditions were triggered. It is waiting for timer object in fnThreadStartFunction and when time elapses, the code calls fnCreateDriverRegKeyOrRemoveIt. Below you can see a chart of this process.
As you can see, when system thread has returned from ZwUnloadDriver, there is a high probability that page with driver's code is already invalid, because IopDeleteDriver calls MmUnloadSystemImage for mark virtual memory page which belong to driver as free for further using.
Read Entire Article