• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

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

            創建時間:2003-03-26
            文章屬性:原創
            文章來源: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;
              };

            }


            關于我們:

            WSS(Whitecell Security Systems),一個非營利性民間技術組織,致力于各種系統安全技術的研究。堅持傳統的hacker精神,追求技術的精純。
            WSS 主頁:http://www.whitecell.org/

            posted on 2007-07-29 13:43 旅途 閱讀(740) 評論(0)  編輯 收藏 引用 所屬分類: 深入windows

            国产精品伦理久久久久久| 国产精品一久久香蕉国产线看 | 久久久久久噜噜精品免费直播| 精品久久香蕉国产线看观看亚洲| 国产精品久久波多野结衣| 久久亚洲国产精品五月天婷| 香蕉久久夜色精品国产2020| 久久久久久久精品成人热色戒| 激情伊人五月天久久综合| 性欧美丰满熟妇XXXX性久久久| 精品久久无码中文字幕| 久久夜色撩人精品国产| 久久久久人妻一区精品色| 久久精品无码一区二区三区免费 | 亚洲人成网站999久久久综合 | 偷偷做久久久久网站| www久久久天天com| 久久人人添人人爽添人人片牛牛| 99久久99久久久精品齐齐| 一本一本久久a久久精品综合麻豆| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 偷窥少妇久久久久久久久| 国产精品伦理久久久久久| …久久精品99久久香蕉国产| 日本加勒比久久精品| 日本精品久久久久中文字幕| 久久天堂AV综合合色蜜桃网| 少妇被又大又粗又爽毛片久久黑人| 久久av无码专区亚洲av桃花岛| 亚洲精品99久久久久中文字幕| 26uuu久久五月天| 99久久777色| 久久99免费视频| AV狠狠色丁香婷婷综合久久| 欧美一区二区三区久久综合| 亚洲午夜无码久久久久| 日本WV一本一道久久香蕉| 亚州日韩精品专区久久久| 日韩欧美亚洲综合久久影院Ds| 久久成人永久免费播放| 久久播电影网|