Click here to Skip to main content
13,550,805 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


50 bookmarked
Posted 17 Feb 2008
Licenced CPOL

KitKat - The Lazy/Poor Man's Rootkit

, 26 Oct 2010
Rate this:
Please Sign up or sign in to vote.
A Very Simple Pseudo-RootKit


This article is about using global hooks and window subclassing to create a pseudo-rootkit capable of hiding files from Explorer, Task Manager, Registry Editor, etc.


It is assumed that the reader knows basic C++, Windows Programming, Global Hooks (for DLL injection) and of course, knows what a RootKit is.


Although The program has been well tested, I have to include this disclaimer: The following program attempts to modify your operating system, which may/can make your system unstable. By executing/compiling the program you agree that neither the author nor the site hosting this article shall be held responsible for any damages occured due to this program. This program comes with NO WARRANTY. USE AT YOUR OWN RISK!! If this scares you, you probably shouldn't run this program. The author hereby disclaims himself. This article may not be re-published elsewhere without the permission of the author.

Using the code

Compile the VC++ Project to obtain a DLL. You could write your own loader, but i have enclosed a small DLL Tester written in VB just in case. Once loaded, the DLL will establish a CallWnd hook.


Before I start a flame war or get found out by the Gurus out there, I'd like to state Kitkat is not a "System Roothit". It's more of a "User Rootkit" not to be confused with "UserMode Rootkits (Ring 3)"...

There are 2 basic kinds of Rootkits:

  1. Kernel Mode Rootkits (Run in Ring0 and filters requests at the highest level)
  2. UserMode Rootkits (Run in UserMode, uses API redirection, IAT hooking to get the job done)

The most powerful rootkits are no doubt the kernel rootkits. Usermode rootkits are less desirable because it is well known[^] that not all API calls can be hooked using IAT patching. (Link to Article)

So which of these does KitKat belong to? Actually, its None of the above. Most rootkits have the following model

OS --->  RootKit Filter ---> User

Every file that is being stealthed is hidden from the system itself, which means even if one programmatically tries to locate a file, you'll not be able to find it since the filter intercepts any such requests. As a result it effectively stealths the files/processes from BOTH the SYSTEM and THE USER. If an AntiVirus (AV) program requests a file that was being stealthed, the AV would get an "INVALID_FILE_HANDLE" response. In contrast, Kitkat is based on the following model:

Windows GUI ----> Kitkat RootKit Filter  ----> User

As You can see, The OS doesn't figure in the diagram because KitKat only modifies/affects the GUI of the system. KitKat does NOT stealth your files from the system itself. It only hides your files from the "User's Sight". The files can be read and written programmatically by any program.

For example, say Kitkat is hiding the file c:\test.txt. Although you won't be able to see the file using Windows Explorer, if you tried to execute notepad c:\test.txt it would work fine, since the system can "see" the file. The system remains unaffected; only the GUI is affected. As a result, this can be used to

  1. Hide process listing (from Task Manager, etc.)
  2. Hide files in Explorer (Folders, Files, Common Dialog Boxes)
  3. Hide entries in the Registry Editor (Regedit)

I hope that has clarified things.

DLL Injection

The DLL injection method is based on Ivo Ivanov's[^] code. A million thanks to him.


Grab your trusty Spy++ and find the class name of the main window (where folders and files are displayed) used by

  1. Explorer.exe
  2. Regedit.exe
  3. Taskmgr.exe
  4. Common Dialogs (Open File, Save File)
  5. Etc. (pretty much everything on your PC)

You'll notice all the the main windows (where folders and files are displayed) are of class SysListView32 which is popularly called a ListView. Note that almost every control in Windows is also a window and all are created using CreateWindow. Windows differentiates between a Button and a List by means of a class name. In addition, every window has a WinProc Window procedure.

For each class there are specific procedures. For a Button, the WM_COMMAND may simulate a depressed button. The same Message for a List simply highlights the selection. As you can see, every control has its own in-built default procedure and we are going to redirect this default procedure to our filter.

Kitkat.dll is going to be injected into every process that has a message queue using the CallWnd hook. Once injected, by using global subclassing we can redirect the default window procedure of ListView to our own filter function. To perform the redirection, we only need one API call to SetClassLong.

Hooking The ListView Procedure

// Create temporary SysListView32 window since you need 
// an instance of that control for SetClassLong
  HWND hWnd = CreateWindow("SysListView32","",0, 0, 0, 0, 0,NULL, NULL, hInstance, NULL);
//get previous addr
  OldWndProc = SetClassLong(hWnd,GCL_WNDPROC,(LONG)NewWndProc); 
//destroy it, don't need it anymore

Once this is done, every ListView created AFTER the hook was established will be affected. Note: ListViews created before are unaffected, which is just one of the many drawbacks of the Kitkat method. Although it can be implemented using SetWindowLong() we have to remember the old procedure for each one of them. After all, this is just a demo.

Notice, that we now have the OldWndProc. You need to store this, because we'll need it to call the real procedure.

Filter Function

char temp[MAX];

LONG OldWndProc;
    // Why Hook the WM_PAINT? Because it was the Only Common Message i found that 
    // was sent to all "Explorer.exe","Regedit.exe",  "taskmgr.exe"
    case WM_PAINT:

      //Find Number of Columns...We'll Search Every Column
      HWND hdr = (HWND)SendMessage(Hwnd,LVM_GETHEADER,0,0);
      int Col = SendMessage(hdr,HDM_GETITEMCOUNT,0,0);
      int i,j,k,itemCount = ListView_GetItemCount(Hwnd);

      for(i=0;i < Col;i++)
        for(j=0;j < itemCount;j++)

          for(k=0;k < UBOUND_PROCLIST;k++)
            //substring search
  return CallWindowProc((WNDPROC)OldWndProc, Hwnd, Message, wParam, lParam);


A ListView can have multiple columns. Let's say I'm an evil malicious hacker dude that those guys at Microsoft always seem to be talking about. I now have my backdoor.exe which has created an AutoRun entry in the registry. Now, I want the entry to also be hidden. This is done as follows:

  1. Inject DLL into Regedit.exe
  2. Subclass SysListView32
  3. Intercept the WM_PAINT message
  4. Search through ALL columns and rows to find backdoor.exe
  5. If found, delete the entire row.
  6. Call the default procedure.


  1. Does not affect console programs (because they don't have message queue's)
  2. Any program can "detect" files, if we are actively looking for them. Assuming the user doesn't know he's been compromised, then he'll never look for the file.
  3. Controls created prior to hooking are unaffected.


A : I tried to monitor all messages that were sent to SysListView32 and the only common message that was sent to Explorer.exe, Taskmgr.exe, and Regedit.exe was WM_PAINT. There are other messages, but they are not consistent with all the applications

Q : In Explorer, there's an empty space where the icon (for the stealthed file) was supposed to fall. What's with that?
A : I'm guessing that the positions are assigned before WM_PAINT is called, so when we filter the result, the space is already allocated for the icon. I guess if we intercept another message this could be fixed, but I haven't tried any.

Q : What is its Purpose?
A : Unfortunately, the only purpose I can tell you, involves malicious applications, but I hope something good can come out of it.

Q : Hey,I can see the stealthed files using cmd. Can you implement a method that works for them?
A : It can be implemented, but we'll have to redirect StdIn, StdOut, and StdError using pipes, but that's a story for another time. Who knows, if I get the time I will do it.

Q : It doesn't work on my system?
A : As of now, I have tested it out on my system which is Windows 2000 SP4. If it doesn't work on your system please report it, so that the article can be corrected.

Q : It's a DLL, how do i execute it?
A : You could write your own loader, but I have enclosed a small DLL tester written in VB just in case. Once Loaded, the DLL will establish a CallWnd hook. You can customize it for your own needs.

Authors Notes

  • The processes to hide are hardcoded. To make it more flexible you can use ini-files to check filenames.
  • You can prevent the DLL from injecting itself into certain processes by matching g_exePath with the filename (say explorer.exe)
  • More notes can be found in the source code comments.


  • 17 Feb 08 : Original Draft


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Other Student
India India
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionI'm quite a fan of this one. Pin
Member 1353626022-Nov-17 13:06
memberMember 1353626022-Nov-17 13:06 
GeneralDLLTester Pin
rojaldearintok26-Apr-14 15:28
memberrojaldearintok26-Apr-14 15:28 
QuestionWhich is the difference between API Hooking and a Ring3? Pin
Member 300374521-Jan-11 5:27
memberMember 300374521-Jan-11 5:27 
GeneralMy vote of 5 Pin
Member 300374521-Jan-11 5:21
memberMember 300374521-Jan-11 5:21 
GeneralMy vote of 2 Pin
amleth27-Oct-10 9:38
memberamleth27-Oct-10 9:38 
JokeKitKat Pin
PogoboyKramer27-Oct-10 3:39
memberPogoboyKramer27-Oct-10 3:39 
GeneralRe: KitKat Pin
st0le30-Oct-10 19:34
memberst0le30-Oct-10 19:34 
GeneralMy vote of 2 Pin
SledgeHammer0126-Oct-10 13:33
memberSledgeHammer0126-Oct-10 13:33 
Generalcompilation error Pin
matwachich19-May-10 14:07
membermatwachich19-May-10 14:07 
Questionhow to do this in Pin
abhi146-Jun-09 9:21
memberabhi146-Jun-09 9:21 
AnswerRe: how to do this in Pin
st0le7-Jun-09 0:20
memberst0le7-Jun-09 0:20 
GeneralMistake... Pin
Hackelberry1-Nov-08 8:38
memberHackelberry1-Nov-08 8:38 
GeneralRe: Mistake... Pin
st0le2-Nov-08 0:52
memberst0le2-Nov-08 0:52 
GeneralSetClassLong returning 0 Pin
Member 356950628-Aug-08 2:46
memberMember 356950628-Aug-08 2:46 
GeneralRe: SetClassLong returning 0 Pin
Member 356950630-Aug-08 1:32
memberMember 356950630-Aug-08 1:32 
QuestionIt's working on xp sp2? Pin
Member 356950628-Aug-08 0:17
memberMember 356950628-Aug-08 0:17 
AnswerRe: It's working on xp sp2? Pin
Member 356950630-Aug-08 1:34
memberMember 356950630-Aug-08 1:34 
GeneralRe: It's working on xp sp2? Pin
st0le12-Sep-08 2:13
memberst0le12-Sep-08 2:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180515.1 | Last Updated 26 Oct 2010
Article Copyright 2008 by st0le
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid