線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2309
推到 Plurk!
推到 Facebook!

內核級HOOK的幾種實現與應用

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-30 01:37:43 IP:61.64.xxx.xxx 未訂閱
內核級HOOK的幾種實現與應用        文章來源:http://www.whitecell.org
文章提交:sinister (jiasys_at_21cn.com)    內核級HOOK的幾種實現與應用    Author  : sinister
Email   : sinister@whitecell.org
HomePage: http://www.whitecell.org      實現內核級 HOOK 對於攔截、分析、跟蹤系統內核起著致關重要的作用。實現的方法不同意味著應用側重點的不同。    如想要攔截 NATIVE API 那麼可能常用的就是 HOOK SERVICE TABLE 的方法。
如果要分析一些系統調用,那麼可能想到用 HOOK INT 2E 中斷來實現。    如果想要攔截或跟蹤其他內核 DRIVER 的調用,那麼就要用到HOOK PE 的方法來實現。    這裏我們更注重的是實現,原理方面已有不少高手在網上發表過文章。    大家可以結合起來讀。
下面以我寫的幾個實例程式來講解一下各種方法的實現。
錯誤之處還望各位指正。    1、HOOK SERVICE TABLE 方法:
   這種方法對於攔截 NATIVE API 來說用的比較多。
原理就是通過替換系統導
出的一個 SERVICE TABLE 中相應的 NATIVE API 的位址來達到攔截的目的。
因為此方法較為簡單,網上也有不少資料來介紹。
所以這裏就不給出實例程式了。SERVICE TABLE 的結構如下:    typedef struct ServiceDescriptorEntry {
    unsigned int *ServiceTableBase;
    unsigned int *ServiceCounterTableBase; 
    unsigned int NumberOfServices;
    unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
       2、HOOK INT 2E 方法:
   這種方法對於跟蹤、分析系統調用來說用的比較多。原理是通過替換 IDT
表中的 INT 2E 中斷,使之指向我們自己的中斷服務處理常式來實現的。
掌握此方法需要你對保護模式有一定的基礎。下面的程式演示了這一過程。    /*****************************************************************
檔案名        : WssHookInt2e.c
描述          : 系統調用跟蹤
作者          : sinister
最後修改日期  : 2002-11-02
*****************************************************************/    #include "ntddk.h"
#include "string.h"    #define DWORD unsigned __int32
#define WORD unsigned __int16
#define BYTE unsigned __int8
#define BOOL __int32    #define LOWORD(l)           ((WORD)(l))
#define HIWORD(l)           ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
#define LOBYTE(w)           ((BYTE)(w))
#define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))    #define MAKELONG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16))     #define SYSTEMCALL 0x2e
#define SYSNAME "System"
#define PROCESSNAMELEN 16    #pragma pack(1)    //定義 IDTR 
typedef struct tagIDTR {
        WORD IDTLimit;
        WORD LowIDTbase;
        WORD HiIDTbase;
}IDTR, *PIDTR;    //定義 IDT 
typedef struct tagIDTENTRY{
    WORD OffsetLow;
    WORD selector;
    BYTE unused_lo;
    unsigned char unused_hi:5;
    unsigned char DPL:2;
    unsigned char P:1;
    WORD OffsetHigh;
} IDTENTRY, *PIDTENTRY;    #pragma pack()    DWORD    OldInt2eService;
ULONG    ProcessNameOffset;
TCHAR   ProcessName[PROCESSNAMELEN];    static NTSTATUS  MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
ULONG GetProcessNameOffset();
VOID GetProcessName( PCHAR Name );
VOID InstallNewInt2e();
VOID UninstallNewInt2e();    VOID __fastcall NativeApiCall()
{
    KIRQL OldIrql;
    
    DWORD ServiceID;
    DWORD ProcessId;        __asm mov ServiceID,eax;        ProcessId = (DWORD)PsGetCurrentProcessId();
    GetProcessName(ProcessName);        KeRaiseIrql(HIGH_LEVEL, &OldIrql); // 提升當前的 IRQL 級別防止被中斷        switch ( ServiceID )
    {
            case 0x20:
                 DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateFile() \n",ProcessName,ProcessId);
                 break;                case 0x2b:
                 DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateSection() \n",ProcessName,ProcessId);                 
                 break;                case 0x30:
                 DbgPrint("NEWINT2E: ProcessName: %s; ProcessID: %d; Native Api: NtCreateToken() \n",ProcessName,ProcessId);                 
                 break;
                 
    }        KeLowerIrql(OldIrql); //恢復原始 IRQL    }    __declspec(naked) NewInt2eService()
{
    __asm{
        pushad
        pushfd
        push fs
        mov bx,0x30
        mov fs,bx
        push ds
        push es            sti
        call NativeApiCall; // 調用記錄函數
        cli            pop es
        pop ds
        pop fs
        popfd
        popad            jmp    OldInt2eService;  //跳到原始 INT 2E 繼續工作
    }
}    VOID InstallNewInt2e()
{        IDTR         idtr;
    PIDTENTRY    OIdt;
    PIDTENTRY    NIdt;        //得到 IDTR 中得段界限與基底位址
    __asm { 
        sidt idtr;
    }        //得到IDT基底位址
    OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);         //保存原來的 INT 2E 服務常式
    OldInt2eService = MAKELONG(OIdt[SYSTEMCALL].OffsetLow,OIdt[SYSTEMCALL].OffsetHigh);
    
    NIdt = &(OIdt[SYSTEMCALL]);        __asm {
        cli
        lea eax,NewInt2eService;  //得到新的 INT 2E 服務常式偏移
        mov ebx, NIdt;
        mov [ebx],ax;   //INT 2E 服務常式低 16 位元
        shr eax,16      //INT 2E 服務常式高 16 位元
        mov [ebx 6],ax;
        lidt idtr  //裝入新的 IDT
        sti
    }    }    VOID UninstallNewInt2e()
{
    IDTR         idtr;
    PIDTENTRY    OIdt;
    PIDTENTRY    NIdt;        __asm {
        sidt idtr;
    }        OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);         NIdt = &(OIdt[SYSTEMCALL]);        _asm {
        cli
        lea eax,OldInt2eService;
        mov ebx, NIdt;
        mov [ebx],ax;
        shr eax,16
        mov [ebx 6],ax;
        lidt idtr
        sti
    }    }        // 驅動入口
NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath ) 
{
    
    UNICODE_STRING  nameString, linkString;
    PDEVICE_OBJECT  deviceObject;
    NTSTATUS        status;
    HANDLE          hHandle;
    int                i;
            //卸載驅動
    DriverObject->DriverUnload = DriverUnload;        //建立設備
    RtlInitUnicodeString( &nameString, L"\\Device\\WssHookInt2e" );
    
    status = IoCreateDevice( DriverObject,
                             0,
                             &nameString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             TRUE,
                             &deviceObject
                           );
                                   if (!NT_SUCCESS( status ))
        return status;
            RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssHookInt2e" );        status = IoCreateSymbolicLink (&linkString, &nameString);        if (!NT_SUCCESS( status ))
    {
        IoDeleteDevice (DriverObject->DeviceObject);
        return status;
    }    
            for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i  )    {              DriverObject->MajorFunction[i] = MydrvDispatch;
    }          DriverObject->DriverUnload = DriverUnload;        ProcessNameOffset = GetProcessNameOffset();
    InstallNewInt2e();      return STATUS_SUCCESS; 
}         //處理設備物件操作    static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{ 
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0L;
    IoCompleteRequest( Irp, 0 );
    return Irp->IoStatus.Status;
    
}        VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
{
    UNICODE_STRING  nameString;        UninstallNewInt2e();
    RtlInitUnicodeString( &nameString, L"\\DosDevices\\WssHookInt2e" );    
    IoDeleteSymbolicLink(&nameString);
    IoDeleteDevice(pDriverObject->DeviceObject);        return;
}        ULONG GetProcessNameOffset()
{
        PEPROCESS curproc;
        int i;
        
        curproc = PsGetCurrentProcess();            //
        // Scan for 12KB, hopping the KPEB never grows that big!
        //
        for( i = 0; i < 3*PAGE_SIZE; i   ) {                if( !strncmp( SYSNAME, (PCHAR) curproc   i, strlen(SYSNAME) )) {                    return i;
            }
        }            //
        // Name not found - oh, well
        //
        return 0;
}    VOID GetProcessName( PCHAR Name )
{            PEPROCESS curproc;
        char *nameptr;
        ULONG i;            if( ProcessNameOffset ) {                curproc = PsGetCurrentProcess();
            nameptr = (PCHAR) curproc   ProcessNameOffset;
            strncpy( Name, nameptr, 16 );            } else {                strcpy( Name, "???");
        }
}     3、 HOOK PE 方法
這種方法對於攔截、分析其他內核驅動的函數調用來說用的比較多。
原理
是根據替換 PE 格式導出表中的相應函數來實現的。
此方法中需要用到一些小技巧。
如內核模式並沒有直接提供類似應用層的 GetModuleHandl()、GetProcAddress() 等函數來獲得模組的位址。
那麼我們就需要自己來編寫,這裏用到了一個未公開的函數與結構。
ZwQuerySystemInformation 與 SYSTEM_MODULE_INFORMATION 來實現得到模組的基底位址。
這樣我們就可以根據PE 格式來枚舉導出表中的函數來替換了。
但這又引出了一個問題,那就是從WINDOWS 2000 後內核資料的頁屬性都是唯讀的,不能更改。
內核模式也沒有提供類似應用層的 VirtualProtectEx() 等函數來修改頁面屬性。
那麼也需要我們自己來編寫。
因為我們是在內核模式所以我們可以通過修改 cr0 寄存器的的防寫位元來達到我們的目的。
這樣我們所期望的攔截內核模式函數的功能便得以實現。
此方法需要你對 PE 格式有一定的基礎。下面的程式演示了這一過程。        /*****************************************************************
檔案名        : WssHookPE.c
描述          : 攔截內核函數
作者          : sinister
最後修改日期  : 2002-11-02
*****************************************************************/    #include "ntddk.h"
#include "windef.h"    typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation,
    SystemProcessorInformation,
    SystemPerformanceInformation,
    SystemTimeOfDayInformation,
    SystemNotImplemented1,
    SystemProcessesAndThreadsInformation,
    SystemCallCounts,
    SystemConfigurationInformation,
    SystemProcessorTimes,
    SystemGlobalFlag,
    SystemNotImplemented2,
    SystemModuleInformation,
    SystemLockInformation,
    SystemNotImplemented3,
    SystemNotImplemented4,
    SystemNotImplemented5,
    SystemHandleInformation,
    SystemObjectInformation,
    SystemPagefileInformation,
    SystemInstructionEmulationCounts,
    SystemInvalidInfoClass1,
    SystemCacheInformation,
    SystemPoolTagInformation,
    SystemProcessorStatistics,
    SystemDpcInformation,
    SystemNotImplemented6,
    SystemLoadImage,
    SystemUnloadImage,
    SystemTimeAdjustment,
    SystemNotImplemented7,
    SystemNotImplemented8,
    SystemNotImplemented9,
    SystemCrashDumpInformation,
    SystemExceptionInformation,
    SystemCrashDumpStateInformation,
    SystemKernelDebuggerInformation,
    SystemContextSwitchInformation,
    SystemRegistryQuotaInformation,
    SystemLoadAndCallImage,
    SystemPrioritySeparation,
    SystemNotImplemented10,
    SystemNotImplemented11,
    SystemInvalidInfoClass2,
    SystemInvalidInfoClass3,
    SystemTimeZoneInformation,
    SystemLookasideInformation,
    SystemSetTimeSlipEvent,
    SystemCreateSession,
    SystemDeleteSession,
    SystemInvalidInfoClass4,
    SystemRangeStartInformation,
    SystemVerifierInformation,
    SystemAddVerifier,
    SystemSessionProcessesInformation
} SYSTEM_INFORMATION_CLASS;    typedef struct tagSYSTEM_MODULE_INFORMATION {
    ULONG Reserved[2];
    PVOID Base;
    ULONG Size;
    ULONG Flags;
    USHORT Index;
    USHORT Unknown;
    USHORT LoadCount;
    USHORT ModuleNameOffset;
    CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;    #define IMAGE_DOS_SIGNATURE        0x5A4D      // MZ
#define IMAGE_NT_SIGNATURE      0x50450000  // PE00
#define IMAGE_NT_SIGNATURE1        0x00004550    // 00EP    typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;    typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;    typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;    #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16    //
// Optional header format.
//    typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //        WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;        //
    // NT additional fields.
    //        DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;    typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;    typedef IMAGE_NT_HEADERS32                  IMAGE_NT_HEADERS;
typedef PIMAGE_NT_HEADERS32                 PIMAGE_NT_HEADERS;    //
// Section header format.
//    #define IMAGE_SIZEOF_SHORT_NAME              8    typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;    #define IMAGE_SIZEOF_SECTION_HEADER          40
//
// Export Format
//    typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     // RVA from base of image
    DWORD   AddressOfNames;         // RVA from base of image
    DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;    #define BASEADDRLEN 10    NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    IN OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );    typedef NTSTATUS (* ZWCREATEFILE)(
  OUT PHANDLE FileHandle,
  IN ACCESS_MASK DesiredAccess,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  OUT PIO_STATUS_BLOCK IoStatusBlock,
  IN PLARGE_INTEGER AllocationSize  OPTIONAL,
  IN ULONG FileAttributes,
  IN ULONG ShareAccess,
  IN ULONG CreateDisposition,
  IN ULONG CreateOptions,
  IN PVOID EaBuffer  OPTIONAL,
  IN ULONG EaLength
  );    ZWCREATEFILE    OldZwCreateFile;    static NTSTATUS  MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
VOID DisableWriteProtect( PULONG pOldAttr);
VOID EnableWriteProtect( ULONG ulOldAttr );
FARPROC HookFunction(    PCHAR pModuleBase, PCHAR pHookName, FARPROC pHookFunc );    NTSTATUS  
HookNtCreateFile(
  OUT PHANDLE FileHandle,
  IN ACCESS_MASK DesiredAccess,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  OUT PIO_STATUS_BLOCK IoStatusBlock,
  IN PLARGE_INTEGER AllocationSize  OPTIONAL,
  IN ULONG FileAttributes,
  IN ULONG ShareAccess,
  IN ULONG CreateDisposition,
  IN ULONG CreateOptions,
  IN PVOID EaBuffer  OPTIONAL,
  IN ULONG EaLength
  );        PCHAR MyGetModuleBaseAddress( PCHAR pModuleName ) 
{
    PSYSTEM_MODULE_INFORMATION    pSysModule;            ULONG            uReturn;
    ULONG            uCount;
    PCHAR            pBuffer = NULL;
    PCHAR            pName    = NULL;
    NTSTATUS        status;
    UINT            ui;        CHAR            szBuffer[BASEADDRLEN];
    PCHAR            pBaseAddress;
    
    status = ZwQuerySystemInformation( SystemModuleInformation, szBuffer, BASEADDRLEN, &uReturn );        pBuffer = ( PCHAR )ExAllocatePool( NonPagedPool, uReturn );        if ( pBuffer )
    {
        status = ZwQuerySystemInformation( SystemModuleInformation, pBuffer, uReturn, &uReturn );            if( status == STATUS_SUCCESS )
        {
            uCount = ( ULONG )*( ( ULONG * )pBuffer );
            pSysModule = ( PSYSTEM_MODULE_INFORMATION )( pBuffer   sizeof( ULONG ) );                for ( ui = 0; ui < uCount; ui   )
            {
                pName = MyStrchr( pSysModule->ImageName, '\\' );                    if ( !pName ) 
                {
                    pName = pSysModule->ImageName;
                }                    else {
                    pName  ;
                }                    if( !_stricmp( pName, pModuleName ) )
                {
                    pBaseAddress = ( PCHAR )pSysModule->Base;
                    ExFreePool( pBuffer );
                    return pBaseAddress;
                }                    pSysModule   ;
            }
        }            ExFreePool( pBuffer );
    }        return NULL;
}    FARPROC HookFunction( PCHAR pModuleBase, PCHAR HookFunName, FARPROC HookFun )
{
    PIMAGE_DOS_HEADER         pDosHdr;
    PIMAGE_NT_HEADERS         pNtHdr;
    PIMAGE_SECTION_HEADER     pSecHdr;
    PIMAGE_EXPORT_DIRECTORY  pExtDir;        UINT                    ui,uj;
    PCHAR                    FunName;
    DWORD                    *dwAddrName;
    DWORD                    *dwAddrFun;
    FARPROC                    pOldFun;
    ULONG                    uAttrib;        pDosHdr = ( PIMAGE_DOS_HEADER )pModuleBase;        if ( IMAGE_DOS_SIGNATURE == pDosHdr->e_magic )
    {
        pNtHdr = ( PIMAGE_NT_HEADERS )( pModuleBase   pDosHdr->e_lfanew );            if( IMAGE_NT_SIGNATURE  == pNtHdr->Signature ||    IMAGE_NT_SIGNATURE1 == pNtHdr->Signature )
        {
            pSecHdr = ( PIMAGE_SECTION_HEADER )( pModuleBase   pDosHdr->e_lfanew   sizeof( IMAGE_NT_HEADERS ) );                for ( ui = 0; ui < (UINT)pNtHdr->FileHeader.NumberOfSections; ui   )
            {
                if ( !strcmp( pSecHdr->Name, ".edata" ) )
                {                
                    pExtDir = ( PIMAGE_EXPORT_DIRECTORY )( pModuleBase   pSecHdr->VirtualAddress );
                    dwAddrName = ( PDWORD )(pModuleBase   pExtDir->AddressOfNames );
                    dwAddrFun = ( PDWORD )(pModuleBase   pExtDir->AddressOfFunctions );                        for ( uj = 0; uj < (UINT)pExtDir->NumberOfFunctions; uj   )
                    {
                        FunName = pModuleBase   *dwAddrName;                            if( !strcmp( FunName, HookFunName ) )
                        {
                            DbgPrint(" HOOK  %s()\n",FunName);
                            DisableWriteProtect( &uAttrib );
                            pOldFun = ( FARPROC )( pModuleBase   *dwAddrFun );
                            *dwAddrFun = ( PCHAR )HookFun - pModuleBase;
                            EnableWriteProtect( uAttrib );
                            return pOldFun;
                        }                          dwAddrName   ;
                      dwAddrFun   ;
                    }
                }                    pSecHdr  ;
            }
        }
    }        return NULL;
}    // 驅動入口
NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath ) 
{
    
    UNICODE_STRING  nameString, linkString;
    PDEVICE_OBJECT  deviceObject;
    NTSTATUS        status;
    HANDLE          hHandle;
    PCHAR            pModuleAddress;
    int                i;
            //卸載驅動
    DriverObject->DriverUnload = DriverUnload;        //建立設備
    RtlInitUnicodeString( &nameString, L"\\Device\\WssHookPE" );
    
    status = IoCreateDevice( DriverObject,
                             0,
                             &nameString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             TRUE,
                             &deviceObject
                           );
                                   if (!NT_SUCCESS( status ))
        return status;
            RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssHookPE" );        status = IoCreateSymbolicLink (&linkString, &nameString);        if (!NT_SUCCESS( status ))
    {
        IoDeleteDevice (DriverObject->DeviceObject);
        return status;
    }    
    
    pModuleAddress = MyGetModuleBaseAddress("ntoskrnl.exe");
    if ( pModuleAddress == NULL)
    {
        DbgPrint(" MyGetModuleBaseAddress()\n");
        return 0;
    }        OldZwCreateFile = (ZWCREATEFILE)HookFunction( pModuleAddress, "ZwCreateFile",(ZWCREATEFILE)HookNtCreateFile);
    if ( OldZwCreateFile == NULL)
    {
        DbgPrint(" HOOK FAILED\n");
        return 0;
    }        DbgPrint("HOOK SUCCEED\n");        for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i  )    {              DriverObject->MajorFunction[i] = MydrvDispatch;
    }          DriverObject->DriverUnload = DriverUnload;
     
  return STATUS_SUCCESS; 
}         //處理設備物件操作    static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{ 
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0L;
    IoCompleteRequest( Irp, 0 );
    return Irp->IoStatus.Status;
    
}        VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
{
    UNICODE_STRING  nameString;
    PCHAR            pModuleAddress;        pModuleAddress = MyGetModuleBaseAddress("ntoskrnl.exe");
    if ( pModuleAddress == NULL)
    {
        DbgPrint("MyGetModuleBaseAddress()\n");
        return ;
    }        OldZwCreateFile = (ZWCREATEFILE)HookFunction( pModuleAddress, "ZwCreateFile",(ZWCREATEFILE)OldZwCreateFile);
    if ( OldZwCreateFile == NULL)
    {
        DbgPrint(" UNHOOK FAILED!\n");
        return ;
    }        DbgPrint("UNHOOK SUCCEED\n");        RtlInitUnicodeString( &nameString, L"\\DosDevices\\WssHookPE" );    
    IoDeleteSymbolicLink(&nameString);
    IoDeleteDevice(pDriverObject->DeviceObject);        return;
}    NTSTATUS  
HookNtCreateFile(
  OUT PHANDLE FileHandle,
  IN ACCESS_MASK DesiredAccess,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  OUT PIO_STATUS_BLOCK IoStatusBlock,
  IN PLARGE_INTEGER AllocationSize  OPTIONAL,
  IN ULONG FileAttributes,
  IN ULONG ShareAccess,
  IN ULONG CreateDisposition,
  IN ULONG CreateOptions,
  IN PVOID EaBuffer  OPTIONAL,
  IN ULONG EaLength
  )
{
    NTSTATUS    status;        DbgPrint("Hook ZwCreateFile()\n");        status = ((ZWCREATEFILE)(OldZwCreateFile))(
               FileHandle,
               DesiredAccess,
               ObjectAttributes,
               IoStatusBlock,
               AllocationSize,
               FileAttributes,
               ShareAccess,
               CreateDisposition,
               CreateOptions,
               EaBuffer,
               EaLength
              );        return status;
}    VOID DisableWriteProtect( PULONG pOldAttr)
{         ULONG uAttr;         _asm
    {
          push eax;
          mov  eax, cr0;
          mov  uAttr, eax;
          and  eax, 0FFFEFFFFh; // CR0 16 BIT = 0
          mov  cr0, eax;
          pop  eax;
    };         *pOldAttr = uAttr; //保存原有的 CRO 屬性    }    VOID EnableWriteProtect( ULONG uOldAttr )
{      _asm
  {
       push eax;
       mov  eax, uOldAttr; //恢復原有 CR0 屬性
       mov  cr0, eax;
       pop  eax;
  };    }
 
發表人 - conundrum 於 2004/05/30 16:19:06
系統時間:2024-05-13 2:15:01
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!