Zoom Icon

Our first DKOM

From UIC Archive

Our first DKOM


Our first DKOM
Author: X-Treem
Email: [email protected]
Date: 11/03/2011 (dd/mm/yyyy)
Level: Luck and skills are required
Language: English Flag English.gif
Comments: Heaven Gates, Hell Gates, Bill Gates!


We are going to make a small step forward starting from Quequero's 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.




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.


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

  1. include <ntddk.h>
  1. define VER_PRODUCTBUILD /* NT */ 2600

But lets go to what we are really interested in

typedef struct _LIST_ENTRY {

 struct _LIST_ENTRY *Flink;  //Forward link
 struct _LIST_ENTRY *Blink;  //Back Link


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];


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).

EPROCESS circular double linked list.jpg

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 PEPROCESS PsGetCurrentProcess(void); and then simply unlink itself from the previous EPROCESS.ActiveProcessLink.Flink and the following EPROCESS.ActiveProcessLink.Flink. pEProcess->ActiveProcessLinks.Blink->Flink = pEProcess->ActiveProcessLinks.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



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.


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.