Saturday, August 13, 2011

Hook Specials 6:hook ObOpenObjectByPointer

Author:dayed
code:
#include "ntddk.h"
#include <windef.h>
#include <stdlib.h>
#include "dayed.h"

#define OBJECT_TO_OBJECT_HEADER( o ) CONTAINING_RECORD( (o), OBJECT_HEADER, Body )   
extern POBJECT_TYPE *PsProcessType;
extern POBJECT_TYPE *PsThreadType;
KSPIN_LOCK SDTSpinLock;
KIRQL  oldIrql;

BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 };
BYTE g_OrigCode[5] = { 0 };
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 };
char* MyProtectName = "notepad.exe";
int MyProtectPID=0;

PEPROCESS EPROCESS,ProtectedProcess;

void StartHook ();

NTSYSAPI
NTSTATUS
NTAPI ObOpenObjectByPointer(
  IN PVOID  Object,
  IN ULONG  HandleAttributes,
  IN PACCESS_STATE  PassedAccessState  OPTIONAL,
  IN ACCESS_MASK  DesiredAccess  OPTIONAL,
  IN POBJECT_TYPE  ObjectType  OPTIONAL,
  IN KPROCESSOR_MODE  AccessMode,
  OUT PHANDLE  Handle);

NTKERNELAPI
NTSTATUS
PsLookupProcessByProcessId (
      IN ULONG          ProcessId,
      OUT PEPROCESS     *Process
);

NTKERNELAPI
PEPROCESS
NTAPI
IoThreadToProcess (
    IN PETHREAD Thread
);

void StopHook ()
{
  WPOFF();
  KeAcquireSpinLock( &SDTSpinLock, &oldIrql );
  RtlCopyMemory ( (BYTE*)ObOpenObjectByPointer, g_OrigCode, 5 );
  KeReleaseSpinLock( &SDTSpinLock, oldIrql );
  WPON();
}

__declspec (naked)
NTSTATUS
Proxy_ObOpenObjectByPointer(
  IN PVOID  Object,
  IN ULONG  HandleAttributes,
  IN PACCESS_STATE  PassedAccessState  OPTIONAL,
  IN ACCESS_MASK  DesiredAccess  OPTIONAL,
  IN POBJECT_TYPE  ObjectType  OPTIONAL,
  IN KPROCESSOR_MODE  AccessMode,
  OUT PHANDLE  Handle)
{
  __asm {  // 共12字节
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 前5字节实现原函数的头5字节功能
      _emit 0x90  // 这个填充jmp
      _emit 0x90
      _emit 0x90
      _emit 0x90
      _emit 0x90  // 这4字节保存原函数+5处的地址
      _emit 0x90 
      _emit 0x90  // 因为是长转移,所以必须是 0x0080
  }
}


NTSTATUS __stdcall
fake_ObOpenObjectByPointer(
  IN PVOID  Object,
  IN ULONG  HandleAttributes,
  IN PACCESS_STATE  PassedAccessState  OPTIONAL,
  IN ACCESS_MASK  DesiredAccess  OPTIONAL,
  IN POBJECT_TYPE  ObjectType  OPTIONAL,
  IN KPROCESSOR_MODE  AccessMode,
  OUT PHANDLE  Handle)
{
     if ((Object != NULL) && (MmIsAddressValid(Object))) // 地址有效性验证
    {
        if (((POBJECT_HEADER)(OBJECT_TO_OBJECT_HEADER(Object)))->Type == *PsProcessType) // 若为进程对象
        {
            if ((ProtectedProcess !=PsGetCurrentProcess())) // 若操作者不是受保护的进程自己
            {
                if (Object == ProtectedProcess) // 若被操作进程是受保护进程
                {
                    return STATUS_ACCESS_DENIED; // 拒绝访问
                }

             }
         }
        else
             if (OBJECT_TO_OBJECT_HEADER(Object) -> Type == *PsThreadType) // 若为线程对象
            {
                EPROCESS = IoThreadToProcess(Object); // 获取线程对应进程的 EPROCESS
                if (EPROCESS == ProtectedProcess) // 若是受保护进程
                {
                    if ((PsGetCurrentProcess() != ProtectedProcess)) // 若操作者不是受保护进程自己
                    {
                        return STATUS_ACCESS_DENIED; // 拒绝访问
                    }
                 }
             }
    }
    return Proxy_ObOpenObjectByPointer (Object, HandleAttributes,PassedAccessState,DesiredAccess,ObjectType,AccessMode,Handle);
}


void StartHook ()
{
  RtlCopyMemory (g_OrigCode, (BYTE*)ObOpenObjectByPointer, 5);
  DbgPrint("g_OrigCode address at %x\n",g_OrigCode);
  *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_ObOpenObjectByPointer - (ULONG)ObOpenObjectByPointer - 5;
  DbgPrint("fake_ObOpenObjectByPointer address at %x\n",fake_ObOpenObjectByPointer);
  DbgPrint("ObOpenObjectByPointer address at %x\n",ObOpenObjectByPointer);
  WPOFF();
  KeAcquireSpinLock( &SDTSpinLock, &oldIrql );
  RtlCopyMemory ( (BYTE*)ObOpenObjectByPointer, g_HookCode, 5 );
  *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)ObOpenObjectByPointer + 5 );
  RtlCopyMemory ( (BYTE*)Proxy_ObOpenObjectByPointer, g_OrigCode, 5);
  RtlCopyMemory ( (BYTE*)Proxy_ObOpenObjectByPointer+ 5, jmp_orig_code, 7);
  KeReleaseSpinLock( &SDTSpinLock, oldIrql );
  WPON();
  DbgPrint("Proxy_ObOpenObjectByPointer address at %x\n",Proxy_ObOpenObjectByPointer);
}

VOID Unload(PDRIVER_OBJECT  DriverObject)
{ 
if (MyProtectPID!=0)
{
   StopHook();
}
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING str)
{
  NTSTATUS      ntStatus;
  char ProcessName[256];
  ULONG cbBuffer = 0x8000;
  PSYSTEM_PROCESS_INFORMATION pInfo;
  VOID* pBuffer = NULL;
 
  DriverObject->DriverUnload = Unload;
          pBuffer = ExAllocatePool (NonPagedPool, cbBuffer);
        if (pBuffer == NULL)
        {
            return 1;
        }
        ntStatus = ZwQuerySystemInformation(5, pBuffer, cbBuffer, NULL);
   
        if (!NT_SUCCESS(ntStatus))
        {
            ExFreePool(pBuffer);
            return 1;
        }
  
    pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
   
    while(1){
        LPWSTR pszProcessName = pInfo->ProcessName.Buffer;
        if (pszProcessName == NULL)
        pszProcessName = L"NULL";

        wcstombs(ProcessName,pszProcessName,256);
    //    DbgPrint("%s\tPid=%d\n",ProcessName,pInfo->ProcessId);
           if(_stricmp(MyProtectName,ProcessName)==0)
           {
              MyProtectPID=pInfo->ProcessId;
              DbgPrint("the MyProtectPID is %d\n",pInfo->ProcessId);
           }
            
       
                if (pInfo->NextEntryDelta == 0)
            break;

        pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+ pInfo->NextEntryDelta);
    }
    ExFreePool(pBuffer);
 
  if (MyProtectPID!=0)
  {
  ntStatus = PsLookupProcessByProcessId(MyProtectPID, &ProtectedProcess);
  if(NT_SUCCESS(ntStatus))
  {
    ObDereferenceObject(ProtectedProcess);
  }
    StartHook();
    DbgPrint("ObOpenObjectByPointer address at %x\n",ObOpenObjectByPointer);
    DbgPrint("Hook Start");
    return STATUS_SUCCESS;
    }
    DbgPrint("Can't Hook");
  return STATUS_SUCCESS;
}

Friday, August 12, 2011

Hook Specials 5: inline hook In my humble opinion as beginner

Author:skymelai
It is unoccupied to work recently,has read things to not touched on work,That include inLine Hook,Next is understand of me,I wonder whether it is correct or no or not.
Usual step:Function Address is finded in memory and save first a few bytes of original function(The code was getted by kernel's debugging).  Write to jump  to our function address on original function startting(Calculate to get addrees).Regain first some bytes of original function on oneself function and jump to original function.

I believe stack' change that is important,Have two kinds of cases,Watch

The image show be hook of function passed parameter with stack,So We can't change value of EBP or value of ESP.

The image show be hook of function passed parameter with register(FASTCALL),So we can free use on our function, That don't change aprropriate register while entry be hook of function

next code will show two kinds of cases

code 1:
#include <ntddk.h>
#include <ntifs.h>
#include <windef.h>
ULONG g_KiInsertQueueApc;
ULONG g_uCr0;

BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 };
BYTE g_OrigCode[5] = { 0 }; // 原函数的前字节内容
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 };

BOOL g_bHooked = FALSE;

VOID
fake_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    );
   
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    );

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; //保存原有的 CRO 性
  
}

VOID WPON()
{
  
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢原有 CR0 性
        mov cr0, eax;
        pop eax;
    };
  
}


//
// 停止inline hook
//
VOID UnHookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
   
    RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_OrigCode, 5 );

    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = FALSE;
}


//
// 开始inline hook --  KiInsertQueueApc
//
VOID HookKiInsertQueueApc ()
{
    KIRQL  oldIrql;

    if (g_KiInsertQueueApc == 0) {
        DbgPrint("KiInsertQueueApc == NULL\n");
        return;
    }

    //DbgPrint("开始inline hook --  KiInsertQueueApc\n");
    DbgPrint( "KiInsertQueueApc的地址t0x%08x\n", (ULONG)g_KiInsertQueueApc );
    // 保存原函数的前字节内容
    RtlCopyMemory (g_OrigCode, (BYTE*)g_KiInsertQueueApc, 5);
    *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_KiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
   
   
    // 禁止系统写保护,提升IRQL到DPC
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();

    RtlCopyMemory ( (BYTE*)g_KiInsertQueueApc, g_HookCode, 5 );
    *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)g_KiInsertQueueApc + 5 );
   
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc, g_OrigCode, 5);
    RtlCopyMemory ( (BYTE*)Proxy_KiInsertQueueApc + 5, jmp_orig_code, 7);

    // 恢复写保护,降低IRQL
    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = TRUE;
   
   
}

//
// 跳转到我们的函数里面进行预处理
//
__declspec (naked)
VOID
fake_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
 

    // 去掉DbgPrint,不然这个hook会产生递归
    //DbgPrint("inline hook --  KiInsertQueueApc 成功\n");
 
    __asm
    {
               jmp Proxy_KiInsertQueueApc
    }
}

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked)
VOID
Proxy_KiInsertQueueApc (
    PKAPC Apc,
    KPRIORITY Increment
    )
{
 
    __asm {  // 共字节
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 前字节实现原函数的头字节功能
            _emit 0x90  // 这个填充jmp
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 这字节保存原函数+5处的地址
            _emit 0x90 
            _emit 0x90  // 因为是长转移,所以必须是0x0080
    }
}




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 OnUnload( IN PDRIVER_OBJECT DriverObject )
{
  DbgPrint("My Driver Unloaded!");
  UnHookKiInsertQueueApc();
}

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

  return STATUS_SUCCESS;
}

Code 2:
//===================inline hook KiInsertQueueApc====================
//KiInsertQueueApc为内核未导出函数,可以从导出函数KeInsertQueueApc定位
//修改KiInsertQueueApc开头5字节
//处理函数思路:apc-->kthread---apc_state--eprocess--进程名字
//HookKiInsertQueueApc---DetourMyKiInsertQueueApc---UnHookKiInsertQueueApc
#include "ntddk.h"

ULONG CR0VALUE;
ULONG g_KiInsertQueueApc;
          
unsigned char JmpAddress[5]={0xE9,0,0,0,0};       //跳转到HOOK函数的地址
unsigned char  OriginalBytes[5]={0};             //保存原始函数前五个字

VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment);

VOID WPOFF()
{
        _asm
               
        {
               
                push eax
                       
                        mov eax, cr0
                       
                        mov CR0VALUE, eax
                       
                        and eax, 0fffeffffh 
                       
                        mov cr0, eax
                       
                        pop eax
                        cli
                       
        };
       
}

VOID WPON()
{
    __asm
               
        {      
                sti
                push eax
                       
                        mov eax, CR0VALUE
                       
                        mov cr0, eax
                       
                        pop eax
                       
        };
}
//1、获取KiInsertQueueApc地址
ULONG GetFunctionAddr( IN PCWSTR FunctionName)     //PCWSTR常量指针,指向16位UNICODE
{
        UNICODE_STRING UniCodeFunctionName;
        RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
        return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );  
}

ULONG GetKiInsertQueueApcAddr()
{
        ULONG sp_code1=0x28,sp_code2=0xe8,sp_code3=0xd88a;  //特征码,sp_code3 windbg显示错误,应该为d88a
        ULONG address=0;
        PUCHAR addr;
        PUCHAR p;
        addr=(PUCHAR)GetFunctionAddr(L"KeInsertQueueApc");
        for(p=addr;p<p+PAGE_SIZE;p++)
        {
                if((*(p-1)==sp_code1)&&(*p==sp_code2)&&(*(PUSHORT)(p+5)==sp_code3))
                {
                        address=*(PULONG)(p+1)+(ULONG)(p+5);
                        break;
                }
        }
        KdPrint(("[KeInsertQueueApc] addr %x\n",(ULONG)addr));
    KdPrint(("[KiInsertQueueApc] address %x\n",address));
    return address;
}

VOID HookKiInsertQueueApc()
{  
        KIRQL Irql;
        g_KiInsertQueueApc=GetKiInsertQueueApcAddr();
        KdPrint(("[KiInsertQueueApc] KiInsertQueueApc %x\n",g_KiInsertQueueApc));
    // 保存原函数的前字节内容
    RtlCopyMemory (OriginalBytes, (unsigned char*)g_KiInsertQueueApc, 5);
        //新函数对原函数的偏移地址
    *( (ULONG*)(JmpAddress + 1) ) = (ULONG)DetourMyKiInsertQueueApc - (ULONG)g_KiInsertQueueApc - 5;
    // 禁止系统写保护,提升IRQL到DPC
    WPOFF();
    Irql = KeRaiseIrqlToDpcLevel();
    //inline hook函数
        RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, JmpAddress, 5 );
    // 恢复写保护,降低IRQL
    KeLowerIrql(Irql);
    WPON();       
}
//原函数
_declspec (naked) VOID FASTCALL OriginalKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)
{
        _asm
        {
                //前五个字节
                mov edi,edi
                        push ebp
                        mov ebp,esp
                       
                        mov eax,g_KiInsertQueueApc
                        add eax,5
                        jmp eax
        }
}
//处理函数
//apc--kthread--apc_state--eprocess
VOID FASTCALL DetourMyKiInsertQueueApc(IN PKAPC Apc,IN KPRIORITY Increment)
{
        ULONG thread;
        ULONG process;

  /*OriginalKiInsertQueueApc(Apc,Increment);*/

   
        if(MmIsAddressValid((PULONG)((ULONG)Apc+0x008)))    //地址验证 KAPC结构+008--->kthread
                thread=*((PULONG)((ULONG)Apc+0x008));
        else
                return ;
        if(MmIsAddressValid((PULONG)((ULONG)thread+0x044))) //kthread+30-->KAPC_STATE+10-->eprocess
                process=*((PULONG)((ULONG)thread+0x044));
        else
                return ;
    if(MmIsAddressValid((PULONG)((ULONG)process+0x174)))  //eprocess+174---->进程名字
        {
                if((_stricmp((char *)((ULONG)process+0x174),"notepad.exe")==0)&&(Increment==2))
                {
                        return ;

                }
                else
                        OriginalKiInsertQueueApc(Apc,Increment);

        }
        else
                return;
   
}

//卸载函数
VOID UnHookKiInsertQueueApc()
{
        KIRQL Irql;
    WPOFF();
    Irql = KeRaiseIrqlToDpcLevel();
    //inline hook函数
    RtlCopyMemory ( (unsigned char*)g_KiInsertQueueApc, OriginalBytes, 5);
    // 恢复写保护,降低IRQL
    KeLowerIrql(Irql);
    WPON();       
}

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

  UnHookKiInsertQueueApc();
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  DbgPrint("My Driver Loaded!");
 
 
  // TODO!!
  theDriverObject->DriverUnload = OnUnload;

  HookKiInsertQueueApc();
 
  return STATUS_SUCCESS;
}

Thursday, August 11, 2011

Hook Specials 4: combine inline hook with idt hook

Author:Sysnap
   Inline hook is to modify some bytes of a fuction for jump instruction go to funtions oneself to execute......

   IDT HOOK is to modify entry fuction for normal exception handling on IDT table be do function's address oneself.

   Put the two ideas of thoughts is combined - """"one byte's hook""""
   Watch:

    nt!NtOpenFile:
    80579fd0 8bff            mov     edi,edi
    80579fd2 55              push    ebp
    80579fd3 8bec            mov     ebp,esp

    No problem is do inline hook the funtion.....But there only modify one byte...So that isn't inline hook 

    mov     edi,edi The Opcode is 8bff...........We modify 8b to 0xCD.....Then executed
    Then nt!NtOpenFile.....The mean executed 0xCD 0xFF and the opcode is INT 0XFF...Ah.....Then exception is occur......Goto dispose exception handling of INT 0XFF的............We can IDT HOOK INT 0XFF.........So our function onself is executed

     Summarizes:::The way can bypass many of tools about inline hook now...Because We modified one byte of function's start...In essence,That isn's inline hook,Because without jmp.....

     But modified IDT.....Need DUMP IDT for realize to have exception  ..........So dectect IDT is important....The table is used for virus....Except that,""""one byte hook"""""and keyboard record...Ban debug etc..........

Hook Specials 3: Bypass head of functions for inline hook

 Anthor:xacker
Alway lurk and benefit from watch past master posts,So published the article.
The ways is simple,Not dispose relocation table.
that is code:
http://filemarkets.com/file/newbing/399eb37e/

Tuesday, August 9, 2011

Hook Specials 2: Inline hook for the first time emerge BSOD

Anthor:emc
While debugging inline hook wirtten by oneself,BSOD was be emerged.Then windbg was be used to debug file of dump.The information as:

PEB is paged out (Peb.Ldr =7ffd500c) .   Type " . hh dbgerr001"  for details
PEB is paged out (Peb.Ldr =7ffd500c) .   Type " . hh dbgerr001"  for details

I had already check up peb structure and _ PEB_LDE_DATA structure,But does not understand what meaning the information above is.Past master helps me to have a watch for change it.

Inline hook was on ObReferenceObjectByHandle,That is code:

#include <ntddk.h >
#include <string.h >

extern POBJECT_TYPE *PsProcessType;

void close_write_protected()
{
  //cancel write protected
  __asm
  {
    CLI           
    MOV eax, CR0     
    AND eax, NOT 10000H 
    MOV CR0, eax
  }
}

void open_write_protected()
{
  __asm
  {
    MOV eax, CR0
    OR eax, 10000H
    MOV CR0, eax
    STI
  } 
}

//this routine unload current driver
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
  KIRQL irql;

  unsigned char routine_head[5] = {0x8b,0xff,0x55,0x8b,0xec} ;

  irql = KeRaiseIrqlToDpcLevel() ;
  close_write_protected() ;
 
  //unload inline hook
  RtlCopyMemory(ObReferenceObjectByHandle,routine_head ,5);
 
  open_write_protected() ;
  KeLowerIrql(irql) ;

  DbgPrint(" inline hook success unload." );

  return;
}

int call_failed(
        IN HANDLE Handle,
        IN ACCESS_MASK DesiredAccess,
        IN POBJECT_TYPE ObjectType,
        IN KPROCESSOR_MODE AccessMode,
        OUT PVOID *Object,
        OUT POBJECT_HANDLE_INFORMATION HandleInfo
        )
{ 
  KIRQL irql;
 
  //mov edi,edi
  //push ebp
  //mov ebp,esp
  unsigned char routine_head[5] = {0x8b,0xff,0x55,0x8b,0xec} ;
 
  //jmp address
  unsigned char jmp_code[5] = {0xe9,0x00,0x00,0x00,0x00} ;

  if(ObjectType == *PsProcessType)   //this object is a process
  {
   
    irql = KeRaiseIrqlToDpcLevel() ;
    close_write_protected() ;

    //unload inline hook
    RtlCopyMemory(ObReferenceObjectByHandle,routine_head ,5);
   
    ObReferenceObjectByHandle(
        Handle,        
        DesiredAccess,
        ObjectType,
        AccessMode,
        Object,
        HandleInfo
      );
   
    open_write_protected() ;
    KeLowerIrql(irql) ;

    if(_stricmp((const char *) Object+0x174," notepad.exe" ) ! =0)  //this process is protected
    {
      return 1;
    }
    else
    {
      *Object = (PVOID) -1;
      return 0;
    }   
  }
  return 0;
}

//jmp this routine
__declspec(naked)  my_routine()
{
  __asm
  {
    mov edi,edi
    push ebp
    mov ebp,esp

    //parameter enter the stack
    push [ebp+0x1c]
    push [ebp+0x18]
    push [ebp+0x14]
    push [ebp+0x10]
    push [ebp+0xc]
    push [ebp+8]

    call call_failed
  }
}

//driver program entry routine
//rewrite ObReferenceObjectByHandle()  start 5 byte for jmp address to my_routine
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
  int jmp_offset; //a jmp operation from current to my_routine
  KIRQL irql;
  unsigned char jmp_code[5] = {0xe9,0x00,0x00,0x00,0x00} ;

  DriverObject -> DriverUnload = DriverUnload; //set this driver unload routinue
 
  irql = KeRaiseIrqlToDpcLevel() ;
  close_write_protected() ;
 
  //inline hook ObReferenceObjectByHandle()
  jmp_offset = (char *) my_routine - (char *) ObReferenceObjectByHandle - 5;
  RtlCopyMemory(jmp_code+1,&jmp_offset ,4);
  RtlCopyMemory(ObReferenceObjectByHandle,jmp_code ,5);

  open_write_protected() ;
  KeLowerIrql(irql) ;
 
  DbgPrint(" install inline hook success." );

  return STATUS_SUCCESS;
} 

Answer:

Refer to code:

Monday, August 8, 2011

Hook Specials 1: Pubilish project about inline hook

Anthor:shdaianita
The project is simpler and refer to master-hand's code to practise oneself.While that is simpler,Novice is be suggest practice much.

The code:

NTSTATUS
DriverEntry(
  PDRIVER_OBJECT pDriverObj,
  PUNICODE_STRING pRegistryString
  )
{
  NTSTATUS status = STATUS_SUCCESS;
  UNICODE_STRING ustrLinkName;
  UNICODE_STRING ustrDevName;   
  PDEVICE_OBJECT pDevObj;

  //HardCode For Searching……
  ULONG Addr_KiInsertQueueApc=0;
  CHAR FindCode[1][5]={
    {0xe8,0x4b,0x2b,0x00,0x00}
  };

  KdPrint(("==>DriverEntry\n"));
 
  pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
  pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
  pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
  pDriverObj->DriverUnload = DriverUnload;


  RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
  status = IoCreateDevice(pDriverObj,
        0,
        &ustrDevName,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDevObj);

  if(!NT_SUCCESS(status))  {
    return status;
  }

  RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
  status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); 
  if(!NT_SUCCESS(status)) {
    IoDeleteDevice(pDevObj); 
    return status;
  }
 

  //
  // 添加执行代码
  //

  KdPrint(("Search ……\n"));
    OrigfnAddr.KiInsertQueueApc=GetTargetFnAddrFromExportedFn(FindCode[0],L"KeInsertQueueApc",100,0x2b4b);
  if (OrigfnAddr.KiInsertQueueApc!=0)
  {
    KdPrint(("We find it!Address of KiInsertQueueApc: 0x%08x\n",OrigfnAddr.KiInsertQueueApc));
  }
  else
  {
    KdPrint(("Not Find~ \n"));
    return STATUS_UNSUCCESSFUL;
  }

  status=InlineHook(OrigfnAddr.KiInsertQueueApc,(ULONG)fake_KiInsertQueueApc,(ULONG)Proxy_KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc); //进行inlineHook
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  KdPrint(("<==DriverEntry\n"));

  return status;
}


VOID
DriverUnload(
  PDRIVER_OBJECT pDriverObj
  )
{ 
  UNICODE_STRING strLink;
  NTSTATUS status;

  RtlInitUnicodeString(&strLink, LINK_NAME);


  //
  // add unload's code
  //

  status=UnHook(OrigfnAddr.KiInsertQueueApc,OrigHeadCode.KiInsertQueueApc);
  if (!NT_SUCCESS(status))
  {
    KdPrint(("DriverUnload!UnHook Failre~"));
  }

 
  IoDeleteSymbolicLink(&strLink);
  IoDeleteDevice(pDriverObj->DeviceObject);
  KdPrint(("==>DriverUnload\n"));
}

 
Next codes realize hooking:

//WriteProtect OFF/ON By MDL!
PVOID WPOFFByMdl(PVOID VirtualAddr,ULONG uLen,PMDL pMDL)
{
  PVOID MVA=NULL; //system-base VA maps physical pages that MDL describes

  pMDL=IoAllocateMdl(VirtualAddr,uLen,FALSE,FALSE,NULL);
  if (pMDL==NULL)
  {
    KdPrint(("WPOFF!IoAllocateMdl FAILURE pMdl==NULL\n"));
    return NULL;
  }

  MmBuildMdlForNonPagedPool(pMDL);

  _try
  {
    MmProbeAndLockPages(pMDL,KernelMode,IoModifyAccess);
  }
  _except(EXCEPTION_EXECUTE_HANDLER)
  {
    return NULL;
  }

  pMDL->MdlFlags|=MDL_MAPPED_TO_SYSTEM_VA;

  MVA=MmGetSystemAddressForMdlSafe(pMDL,NormalPagePriority);
  if (MVA)
  {
    KdPrint(("MVA : %x",MVA));
  }

    KdPrint(("WPOFFByMdl Successful"));
  return MVA;
}

VOID WPONByMdl(PMDL pMdl)
{
  if (pMdl==NULL)
  {
    return ;
  }

  MmUnlockPages(pMdl);
  IoFreeMdl(pMdl);


}

//Write Protect OFF/ON By CR0!
VOID WPOFFByCR0()
{
  
    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; //Keep original CRO  
}

VOID WPONByCR0()
{
  
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢原有 CR0 性
        mov cr0, eax;
        pop eax;
    };
  

}

///////////////////////////////////////////////////////////////////////
//Get the exported function's address
ULONG GetFunctionAddr(PCWSTR FunctionName)
{
  UNICODE_STRING uFnName;

  RtlInitUnicodeString(&uFnName,FunctionName);

  return (ULONG)MmGetSystemRoutineAddress(&uFnName);
}

//Find  address of the function that we want to hook
//
//Description:Through known function to find us target function
//
//ARGUMENTs:
//
//FindCode:find target function(want to hook functiong),use hard code
//ExportedFnName:Known function's name
//SearchLen:at Known functions search length
//Offset:relatively jump value
//
ULONG GetTargetFnAddrFromExportedFn(CHAR* FindCode,PCWSTR ExportedFnName,ULONG SearchLen,ULONG Offset)
{
  ULONG i=0,j=0;
    CHAR * Addr_ExportedFn=NULL;
  ULONG TargetFnAddr=0;

  Addr_ExportedFn=(CHAR*)GetFunctionAddr(ExportedFnName);
  if (Addr_ExportedFn==NULL)
  {
    KdPrint(("GetTargetFnAddrFromExportedFn!GetFunctionAddr FAILURE\n"));
    return 0;
  }

  for (i=0;i<SearchLen;i++)                //搜索用户指定长度的函数字节
  {
    if (Addr_ExportedFn[i]==FindCode[0])
    {
      for (j=1;j<sizeof(FindCode);j++)
      {
        if (Addr_ExportedFn[i+j]==FindCode[j])
        {
          continue;
        }
        else
        {
          break;
        }
      }

      if (j==sizeof(FindCode))
      {
     
        TargetFnAddr=(ULONG)&Addr_ExportedFn[i]+Offset+5;  //由相对jmp的dword值得到

        break;
      }
    }
  }


  return TargetFnAddr;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//
//Hook Function
//
NTSTATUS InlineHook(ULONG OrigFnAddr,ULONG FakeFnAddr,ULONG ProxyFnAddr,PVOID OrigHeadCode)
{
  KIRQL oldIrql;
  BYTE  HookCode[5]={0xe9,0x00,0x00,0x00,0x00};
  BYTE  jmpCode[7]={0xEA,0x00,0x00,0x00,0x00,0x08,0x00};

  PVOID MVA=NULL;

  if (!OrigFnAddr||!FakeFnAddr||!ProxyFnAddr||!OrigHeadCode)
  {
    return STATUS_UNSUCCESSFUL;
  }

  RtlCopyMemory(OrigHeadCode,(BYTE*)OrigFnAddr,5);

  *(ULONG*)(HookCode+1)=(ULONG)FakeFnAddr-(ULONG)OrigFnAddr-5;

  *(ULONG*)(jmpCode+1)=(ULONG)((BYTE*)OrigFnAddr+0x05);// 不需要相对跳转,这里是长转移

  RtlCopyMemory((BYTE*)ProxyFnAddr,(BYTE*)OrigHeadCode,5);
  RtlCopyMemory((BYTE*)ProxyFnAddr+5,(BYTE*)jmpCode,7);

  /*WPOFFByCR0();*/                                   //这里是去掉内存写保护,两种方法,我们选择MDL的方法
  MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
  if (!MVA)
  {
    KdPrint(("WPOFFByMdl FAILURE~"));
    return STATUS_UNSUCCESSFUL;
  }

  oldIrql=KeRaiseIrqlToDpcLevel();

  /*RtlCopyMemory((BYTE*)OrigFnAddr,(BYTE*)HookCode,5);*/      //将要HOOK的函数的函数头前5个字节改写 跳到我们的fake函数里面
  RtlCopyMemory((BYTE*)MVA,(BYTE*)HookCode,5);        

  KeLowerIrql(oldIrql);

  /*WPONByCR0();*/
    WPONByMdl(MDLs.KiInsertQueueApc);    //Recover write-protect

  return STATUS_SUCCESS;
}


//
// Stop inline hook
//
NTSTATUS UnHook(ULONG OrigFnAddr,PVOID OrigHeadCode)
{
    KIRQL  oldIrql;
  PVOID MVA=NULL;

  if (!OrigFnAddr||!OrigHeadCode)
  {
    return STATUS_UNSUCCESSFUL;
  }

    /*WPOFFByCR0();*/
  MVA=WPOFFByMdl((PVOID)OrigFnAddr,10,MDLs.KiInsertQueueApc);
  if (!MVA)
  {
    KdPrint(("WPOFFByMdl FAILURE~"));
    return STATUS_UNSUCCESSFUL;
  }

    oldIrql = KeRaiseIrqlToDpcLevel();
   
    RtlCopyMemory ( (BYTE*)OrigFnAddr, OrigHeadCode, 5 );

    KeLowerIrql(oldIrql);
   
  /*WPONByCR0();*/
  WPONByMdl(MDLs.KiInsertQueueApc);

  return STATUS_SUCCESS;
}

Sunday, August 7, 2011

The Blogs will translate article of chinese hook's technology

I plan to translate article of chinese hook's technology as of this month at a random time.My english is not good,but I wish you read to know and join all comments,Thanks!