Friday, September 9, 2011

Hook Specials 31 : Debugg driver

Author:softworm
Worte driver , Watch the driver to work, only learn driver. First register image loader message routine.

Code:
VOID LoadImageNotify (
  PUNICODE_STRING FullImageName,
  HANDLE ProcessId,
  PIMAGE_INFO ImageInfo
  )
{
  ANSI_STRING  asImageName;
  PCHAR    Delimiter;
  NTSTATUS  Status;
  ULONG    Base;
  ULONG    Entry;
  ULONG    Patch;
  ULONG    i;
 
 
  RtlUnicodeStringToAnsiString(&asImageName, FullImageName, TRUE);
 
  if (!ImageInfo->SystemModeImage)
  {
    goto __End; //不是驱动
  }
 
  Delimiter = strrchr(asImageName.Buffer, '\\');
  if (Delimiter == NULL)
    goto __End;
 
  Delimiter++;
 
  if( _strnicmp(Delimiter,"xxx.sys",strlen("xxx.sys")) != 0)
    goto __End;

  Base = (ULONG)ImageInfo->ImageBase;
       
  DbgPrint("%s Loaded, MappingAddress=%08X, Size=%08X\n",
     asImageName.Buffer,
     ImageInfo->ImageBase,
     ImageInfo->ImageSize );
 

  //The address immediate hard code, May analysis PE file and use disassemb engine
  // Original driver's DriverEntry export:
  //   leave
  //   retn    8
  //  
  //  

  Entry = Base + 0x1111;
  Patch = Base + 0x2222;
  g_ReturnAddress = Base + 0x3333;

  if (!(*(PULONG)Entry == 0x83EC8B55 &&  *(PUCHAR)(Entry+5) == 0x14)) //Check Entry
  {
    DbgPrint("Mismatched Entry!\n");
    goto __End;
  }

  if (*(PULONG)Patch != 0x0008C2C9)
  {
    DbgPrint("Mismatched Patch Point!\n");
    goto __End;
  }

  __asm
  {
    CLI
    MOV   EAX, CR0
    AND   EAX, NOT 10000H  //disable WP bit
    MOV   CR0, EAX
  }

  *(PUCHAR)Entry = 0xE9;
  *(PULONG)(Entry+1) = (ULONG)&SaveDriverObject - (Entry+5);

  *(PUCHAR)Patch = 0xE9;
  *(PULONG)(Patch+1) = (ULONG)&ReplaceDispatch - (Patch+5);
 

  __asm
  {
    MOV   EAX, CR0
    OR    EAX, 10000H  //enable WP bit
    MOV   CR0, EAX
    STI
  }
 
__End:
  RtlFreeAnsiString(&asImageName);
}
The function patch two part of original driver

DriverEntry entry of original driver, Be designed to get paramter of DriverObject, Because optimize compiler, The paramter is cleared to 0, So first save a share.

Second export of DriverEntry, Here replace dispatch function of DriverObject registered.

Code:
VOID __declspec (naked) SaveDriverObject()
{
  // 55               push    ebp
  // 8B EC            mov     ebp, esp
  // 83 EC 14         sub     esp, 14h

  __asm {
    pushad
    mov  eax, [esp+20h+4]
    mov  g_DrvObj, eax
    popad

    push ebp ; Original code
    mov  ebp, esp
    sub  esp, 14h

    jmp  [g_ReturnAddress]
  }
}


VOID __declspec (naked) ReplaceDispatch()
{
  __asm {
    pushad
   
    mov  eax, g_DrvObj 

    mov  ecx, [eax+18h]  ; DriverExtension
   
     
    mov  ebx, [eax+34h]  ; Unload
    mov  g_Unload, ebx
    mov  ebx, MyUnload
    mov  [eax+34h], ebx
   
    mov  ebx, [eax+38h]
    mov  g_Create, ebx
    mov  ebx, MyCreateCloseCleanup
    mov  [eax+38h], ebx  ; Create
    mov  [eax+40h], ebx  ; Close
    mov  [eax+80h], ebx  ; CleanUp
     
    mov  ebx, [eax+70h]
    mov  g_DeviceControl, ebx
    mov  ebx, MyDeviceControl
    mov  [eax+70h], ebx
   
    popad

    //Execute original export code 执行原出口代码

    __emit 0xC9 //VC6的汇编不支持leave
    retn  8
  }
}

Then may mount oneself code , Start only PassThru :

Code:
VOID MyUnload( PDRIVER_OBJECT DriverObject )
{
  DbgPrint("MyUnload\n");
  ((PDRIVER_UNLOAD)g_Unload)(DriverObject);
  return;
}


NTSTATUS MyCreateCloseCleanup( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
  DbgPrint("MyCreateCloseCleanup\n");
  return ((PDRIVER_DISPATCH)g_Create)(DeviceObject, Irp);
}


NTSTATUS MyDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
  PIO_STACK_LOCATION  irpSp;
  PVOID            inputBuff, outputBuff;
      ULONG            inputLen, outputLen, ctlCode;
  NTSTATUS          Status = STATUS_UNSUCCESSFUL;
   

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  // Buffered io

  inputBuff  = Irp->AssociatedIrp.SystemBuffer;
      outputBuff = Irp->AssociatedIrp.SystemBuffer;
  inputLen   = irpSp->Parameters.DeviceIoControl.InputBufferLength;
      outputLen  = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  ctlCode    = irpSp->Parameters.DeviceIoControl.IoControlCode;

  switch (ctlCode)
  {
  case IOCTL_INIT:
      //逆的代码...
      break;

  default:
      DbgPrint("DeviceControl : Not Implemented IOCTL=%08X\n", ctlCode);
      return ((PDRIVER_DISPATCH)g_DeviceControl)(DeviceObject, Irp);
      break;
  }

__End:
  Irp->IoStatus.Information = outputLen;
  Irp->IoStatus.Status = Status;
      IoCompleteRequest (Irp, IO_NO_INCREMENT);
  return Status;
}

Then it doesn't matter, Reverse IOCTL code and one by one replace.

No comments:

Post a Comment