Sandbox/Our first DKOM
From UIC
Our first DKOM
Contents |
| Sandbox/Our first DKOM | |
|---|---|
| Author: | X-Treem |
| Email: | youwouldlike@tohave.it |
| Website: | |
| Date: | 11/03/2011 (dd/mm/yyyy) |
| Level: |
|
| Language: | English |
| Comments: | Heaven Gates, Hell Gates, Bill Gates! |
Introduction
We are going to make a small step forward starting from Quequero tutorial about writing our first driver. In this small essay we are going to see a very easy (even thou not fully legit, i will explain later) Direct Kernel Objects Manipulation targetting a Windows XP machine.
Tools
- Windows Driver Kit
Windows Driver Kit - DbgView - Let you see any OutputDebugString and DbgPrint output
DbgView - OSRLoader - A complete driver loader
OSR Driver Loader
Source
- Our_first_DKOM.zip : source of our driver and test application
Essay
I am assuming that you already got the basics from Quequero article about the basics of writing a driver, so i will skip everything related to DriverEntry, DriverUnload and IRP_MJ_CREATE and get straight to the point.
What is DKOM?
DKOM stands for Direct Kernel Objects Manipulation, it explains itself: making changes to Kernel Objects.
The Windows NT Kernel keeps track of many structures (that describe Object), often opaque, that it uses for keeping the system up and running. These structures are internal to the Kernel and should not be directly manipulated by drivers, that is why i said not fully legit in the introduction. There are many reasons why not to manipulate these structures with first being exclusive access, being internal structures also any synchronization mechanism used would be internal, causing our access to be non exclusive with possibility of overlapping manipulation and possible system crash. We can also add that no application should have the need of manipulating such structures unless...we want to mess up with the normal functioning of the kernel and its expected behavior.
EPROCESS
In this tutorial we are focusing on the EPROCESS structure to do our magic.
If you check the MSDN library you can see that there is no definition for this structure, so it is opaque.
In my source code you can see that i have included an undocumented.h file that is an extract of ntifs.h from
Bo Brantén website
As i said in the introduction i was focusing on a Windows XP machine (SP3) so to make the undocumented.h precompiler statements do their job i had to add the define with the product build
#define VER_PRODUCTBUILD /* NT */ 2600
But lets go to what we are really interested in
struct _LIST_ENTRY *Flink; //Forward link
struct _LIST_ENTRY *Blink; //Back Link
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _EPROCESS {
KPROCESS Pcb;
EX_PUSH_LOCK ProcessLock;
LARGE_INTEGER CreateTime;
LARGE_INTEGER ExitTime;
EX_RUNDOWN_REF RundownProtect;
ULONG UniqueProcessId;
LIST_ENTRY ActiveProcessLinks; //LIST_ENTRY that link this EPROCESS
//to all the other active EPROCESS
//...
UCHAR ImageFileName[16];
//...
} EPROCESS, *PEPROCESS;
What is very interesting is that the Windows Kernel keeps a circular Double Linked List (LIST_ENTRY) that links all EPROCESS structures for all the running processes and, most of all, this list is also used to give feedback of running processes to any requesting service/application (like the ToolHelp library).
What happens if we remove our process EPROCESS structure from this list? It magically disappear from being reported as an active running process.
If you are starting to play around with kernel mode maybe you are wondering how is it possible that we remove a process from the EPROCESS.ActiveProcessLinks chain and
our process keeps running. But this is easily explained: think of a process as a "container" for threads. Each process just describes the context in which those threads are going to run (or are running).
Each process has at least its starting thread, thus in the end is not a process that is being ran by the Kernel scheduler but its threads.
Something that you will notice is that ActiveProcessLinks is not the head of the structure, so when walking the chain to get the EPROCESS ptr you have to offset the Blink/Flink ptrs. I showed this offseting in my source code, even if it is not needed for our purpose.
In the end, the purpose of the driver is to receive a request from user mode from a process, get the process EPROCESS structure through PsGetCurrentProcess() whose prototype is
and then simply unlink itself from the previous EPROCESS.ActiveProcessLink.Flink and the following EPROCESS.ActiveProcessLink.Flink.
pEProcess->ActiveProcessLinks.Flink->Blink = pEProcess->ActiveProcessLinks.Blink;
To do that we are using an IOCTL (defined as NEITHER_IO vs Quequero example using BUFFERED_IO).
Our application
To test the provided source, first build the driver and the application, use the OSRLoader to load the driver to memory (you just need to browse to the .sys, click register service and start service) and launch the application.
Final Notes
As you have seen, this is a very effective way to hide a process even if you should not have the need to hide your process in a "normal" environment.
This kind of DKOM is often used by malware that install a driver that among other things prevent usermode process detection.
The most effective way to counterstrike this kind of process hiding is to traverse the running threads kernel objects ETHREAD list which all have a back reference ptr
to their respective EPROCESS and check against all EPROCESS from the EPROCESS.ActiveProcessLinks. Any missing EPROCESS in the EPROCESS.ActiveProcessLinks means a hidden process.
Again, because you are not supposed to directly manipulate these structures because you cant lock any exclusive access to them, using this tecnique can lead to system
crash
X-Treem
Thanks
A thanks go to Quequero for this fantastic website, to EvOlUtIoN for having been a padawan and now being a Jedi, to my wife for standing me, and my little Ethan for bringing me joy.
Disclaimer
I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.
Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.