Remsec driver analysis – Part 2

In previous blog post I’ve described 32-bit driver that has been used by attackers who are behind Strider cybergroup. I also pointed that from my point of view the driver was developed by skilled guys, but it contains two flaws. Firstly, authors forget to turn on SMEP again, after executing user mode code and they disable it each time when client tries to call 0x1173000C IOCTL code. Secondly, they try to unload driver dynamically in separate system thread that can lead to code execution from invalid memory (fnThreadStartFunction).

The dropper also contains one more driver (and its x64 clone) that is also interesting for research. I should make one clarification about information I posted before. The dropper itself doesn’t contain rootkit driver as whole file inside, instead it stores only its PE-sections. This means that rootkit PE-file is generated by dropper on-the-fly. So, aswfilt.dll and 32-bit code of another driver as well as its 64-bit clone are stored only as PE-sections. And this is answer on question, why aswfilt.dll has one unnamed section and zeroed timestamp in PE-header. On screenshot below, you can see how the dropper initializes PE-header of aswfilt.dll driver before it was written to FS as executable file.

Driver (Ring 0 code) has following properties:

  • It has compact size and its code is stored into two PE sections inside dropper.
  • It has dynamic imports that are stored into special context structure.
  • It has 64-bit clone inside the dropper.
  • It has no DriverEntry function.
  • It serves for one purpose: execute code from ptr that was passed from user mode to FastIoDeviceControl handler.
  • It uses undocumented Windows kernel API.

Code and data of aswfilt.dll driver are stored into a separate section with name “.rwxdrv”, as you can see on screenshot below. Another two sections with names “.krwkr32”, “.krdrv32” and “.krwkr64”, “.krdrv64” are used for storing mentioned above 32-bit Ring 0 code and its x64 analog.

Like aswfilt.dll, kernel mode code from above mentioned sections uses special context structure where dynamically loaded imports are located. Format of this structure you can see below.

struct RootkitStruct {
PVOID pExAllocatePool;
PVOID pExFreePool;
PVOID pExQueueWorkItem;
PVOID pIofCompleteRequest;
PVOID pIoCreateDevice;
PVOID pIoDeleteDevice;
PVOID pIoDriverObjectType;
PVOID pIoGetCurrentProcess;
PVOID pKeInitializeEvent;
PVOID pKeSetEvent;
PVOID pKeStackAttachProcess;
PVOID pKeUnstackDetachProcess;
PVOID pKeWaitForSingleObject;
PVOID pObCreateObject;
PVOID pObInsertObject;
PVOID pObQueryNameString;
PVOID pObfDereferenceObject;
PVOID pZwClose;
PVOID pZwCreateFile;
PVOID pBuffer;
ULONG cbBuffer;
ULONG field1;
PVOID pProcessForAttach;
};

A problem is that start function of new kernel mode code doesn’t contain DriverEntry function, showing for us that, in first, this code is loaded into Ring 0 not by Windows functions like ZwLoadDriver and in second that it can be loaded into memory with exploit. Anyway, start function of this kernel mode code, where the control will be passed at the beginning of its execution, gets already initialized context with corresponding function ptrs. There is no function inside Ring 0 code, which is responsible for filling context with dynamic loaded functions ptrs.

First action, which fnRootkitStartFunction does, it is creating driver object for loaded Ring 0 code (fnCreateDriverObject). This function (fnCreateDriverObject) allocates an object in memory with help of ObCreateObject, initializes it and does it visible for Windows kernel by inserting it into objects list with ObInsertObject.

Next, it does copying of prepared data with already initialized ptr from user mode buffer to system buffer and saves ptr to it into DriverExtension->ServiceKeyName.Buffer.

The driver leverages interesting way for dispatching DeviceControl request. Unlike other drivers that are using IRP_MJ_DEVICE_CONTROL handler in such case, it registers FastIo function DriverObject->FastIoDispatch.FastIoDeviceControl.

As we already saw in case of aswfilt.dll, DeviceControl handler is responsible for performing only one task: execute function by ptr that has been passed to it from user mode client.

Unfortunately, I haven’t a lot of free time for reconstructing logic of Ring 3 code (dropper part) and how it forms context for kernel mode code. I know that IOCTL with code 0x839200BF (Rootkits_IOCTLs_ExecuteFunction) is used by the dropper only one time in function fnSendIOCTL_839200BF. It passes to driver ptr to function that located at address 0x1000741A.

The dropper also contains some code for exploiting NT Virtual DOS Machine (NTVDM), it contains section with name .vdmbios and it imports function NtVdmControl. The code also uses context structre for calling dynamic imports.

Share this post

Share on facebook
Share on linkedin
Share on print
Share on email

Subscribe to our Monthly Cyber Security Digest

Get monthly content to keep you up to date on the latest news and tips