idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
阅读:2102回复:17

hook ntoskrnl.exe的奇怪现象(很久不说\"奇怪\"两个字了)

楼主#
更多 发布于:2005-03-06 18:05
通过hook PE的方式(不是hook ServiceTable),
我参考以下文章的代码,去hook 多个内核函数.
已经可以正确得到ntoskrnl.exe module的基址了,
但是奇怪的事情却发生了.
调试下面这个函数的时候,我为了验证获取的函数名称和函数地址是否匹配,特意注释掉了几句,大家请看.
结果使用softice调试惊讶的发现,FunName和pOldFun完全对应不起来.也就是说,所有几百个函数名称和函数地址全部乱了套.
My god!
请问大虾原因何在呢?--太--奇--怪--了--.

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;
}


内核级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 = 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 = 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/
[b]万水千山总是情,回个帖子行不行?[/b]
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-03-06 18:12
大家注意看我下断点的地方(有头像):

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 ) )
 :D :D :D :D :D :D :D :D :D :D上句话被我注释掉了
{
DbgPrint(\" HOOK %s()\\n\",FunName);
DisableWriteProtect( &uAttrib );
pOldFun = ( FARPROC )( pModuleBase + *dwAddrFun );
//*dwAddrFun = ( PCHAR )HookFun - pModuleBase;
 :D :D :D :D :D :D :D :D :D :D上句话被我注释掉了
EnableWriteProtect( uAttrib );
 :D :D :D :D :D :D :D :D :D :D我在此下断点,并且使用softice察看FunName和pOldFun,发现pOldFun的真正函数名称永远不是FunName.
---太---奇---怪---了---.
 :D :D :D :D :D :D :D :D :D
//return pOldFun;
 :D :D :D :D :D :D :D :D :D :D上句话被我注释掉了
}

dwAddrName ++;
dwAddrFun ++;
}
}

pSecHdr++;
}
}
}

return NULL;
}
 :D
[b]万水千山总是情,回个帖子行不行?[/b]
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2005-03-06 18:14
自己顶一下. :D
[b]万水千山总是情,回个帖子行不行?[/b]
liuyan1
驱动老牛
驱动老牛
  • 注册日期2001-08-27
  • 最后登录2023-04-18
  • 粉丝0
  • 关注0
  • 积分1031分
  • 威望477点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2005-04-04 01:04
真是太奇怪了。找到原因了吗?说来听听,好好学习一下。
楼上的客,楼下的客,听我老坎说明白,要苛屎有草纸,不要扯我的麦席子,要苛尿有夜壶,不要在床上划地图。
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2005-04-04 09:26
我到现在还是不明白。
[b]万水千山总是情,回个帖子行不行?[/b]
liuyan1
驱动老牛
驱动老牛
  • 注册日期2001-08-27
  • 最后登录2023-04-18
  • 粉丝0
  • 关注0
  • 积分1031分
  • 威望477点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
  • 社区居民
5楼#
发布于:2005-04-04 09:33
我这里的情况是ZwCreatefile .ZwReadfile 。。这些函数还对应的上。但是其他函数比如KeWaitForsignleObject.或者Ex系列的。Io系列的在ntoskernl.exe 中简直一团是糨糊。

难道这些函数的实际Export_TABLE 不是在ntoskernl.exe 中吗?



真是太奇怪了!
楼上的客,楼下的客,听我老坎说明白,要苛屎有草纸,不要扯我的麦席子,要苛尿有夜壶,不要在床上划地图。
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2005-04-04 12:38
我也在好几台机器上试验过。
可能还是通过service table来hook才行。
[b]万水千山总是情,回个帖子行不行?[/b]
liuyan1
驱动老牛
驱动老牛
  • 注册日期2001-08-27
  • 最后登录2023-04-18
  • 粉丝0
  • 关注0
  • 积分1031分
  • 威望477点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
  • 社区居民
7楼#
发布于:2005-04-04 13:18
在osr找的,因为偶只需要修改IAT而不hook,这几个MmGetSystemRoutineAddress还满好用的。不知道你用过没有?
Re: LoadLibrary & GetProcAddress in KM
From: Prasad Dabak <xxx@yahoo.com>
Date: Tue, 13 Mar 2001 21:53:40 -0800 (PST)
 

Hello,

If you are using Windows 2000, you can dynamically get
the address of any NTOSKRNL.EXE or HAL.DLL function
using MmGetSystemRoutineAddress function. The function
is prototyped in NTDDK.H file. The only parameter
which it takes is PUNICODE_STRING pointing to name of
the routine. Note, however, it works only for
NTOSKRNL.EXE or HAL.DLL routines.

The reason is: the code for MmGetSystemRoutineAddress
enumerates all the loaded modules in the system and
for the module names matching NTOSKRNL/HAL it walks
the import tables to locate the address of function.

I dont understand, why this function is restricted
only to NTOSKRNL/HAL modules. It can always be
extended to support any module by adding one more
parameter to this function viz. ModuleName. I hope
Microsoft will add support for this in future versions
of the OS.

Alternatively, you can look at the Gary Nebbett\'s
\"Windows NT/200 Native API reference\" book page 433,
where he has written a kernel mode equivalent of
GetProcAddress.

Hope this helps.

-Prasad



--- Anders Fogh  wrote:
> Hello Matteo,
>
> As stated in a previous reply there is no documented
> and well behaved
> way of doing this. If you wanna embelish on hacks,
> Dmitri Lehman wrote
> a fairly good article which contains a working
> solution. I advice that
> you proceed with caution using this code - I did
> find a few minor bugs
> in it.
>
> http://www.wdj.com/archive/1104/feature.html
>
> Regards,
> Anders Fogh
>
>
> Tuesday, March 13, 2001, 5:53:12 AM, you wrote:
>
> MP> Is there an equivalent of the Win32 functions:
> LoadLibrary and GetProcAddress in kernel mode ?
>
> MP> Thanks
> MP> Matteo
>
>
> MP> ---
> xxx@flaffer.com
>
>
>
> --
> Best regards,
>  Anders                          
> mailto:xxx@flaffer.com
>
>
>
> xxx@yahoo.com


=====
Prasad S. Dabak
Director of Engineering, Windows NT/2000 Division
Cybermedia Software Private Limited
http://www.cybermedia.co.in
Co-author of the book \"Undocumented Windows NT\"
ISBN 0764545698

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - Buy the things you want at great prices.
http://auctions.yahoo.com/

楼上的客,楼下的客,听我老坎说明白,要苛屎有草纸,不要扯我的麦席子,要苛尿有夜壶,不要在床上划地图。
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2005-04-04 14:47
你得到ntoskrnl.exe module的基址是多少
看我的垃圾贴中的\"注释\"
http://www.driverdevelop.com/forum/html_89958.html?1112596992
加载基址在xp中和w2k中不一样了

滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2005-04-04 16:39
这么说来,等我再去试验一下.
[b]万水千山总是情,回个帖子行不行?[/b]
liuyan1
驱动老牛
驱动老牛
  • 注册日期2001-08-27
  • 最后登录2023-04-18
  • 粉丝0
  • 关注0
  • 积分1031分
  • 威望477点
  • 贡献值0点
  • 好评度187点
  • 原创分0分
  • 专家分0分
  • 社区居民
10楼#
发布于:2005-04-07 10:02
有两个疑问

(1)是不是每个导出函数都有名字,这个函数能这么写吗?

(2)就算有都有名字,也不见得名字的排列次序跟对应函数的排列次序一样,能这么查找吗?

_____________________________________________
请bmyyyud 和idapro5老大其他熟悉PE的兄弟抽宝贵时间帮忙解惑一下,偶对PE是一窍不通.

另:idapro5,你的idapro5软件能够共享一下吗?偶的才version :4。3

楼上的客,楼下的客,听我老坎说明白,要苛屎有草纸,不要扯我的麦席子,要苛尿有夜壶,不要在床上划地图。
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2005-04-07 14:07
我的idapro是4.7,从驱网下载的。
函数名称的偏移和函数地址的偏移都在一个数组里,可以查的。
[b]万水千山总是情,回个帖子行不行?[/b]
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2005-04-07 14:09
你可以到
http://soft.0zones.com/
去下载idapro4.7
[b]万水千山总是情,回个帖子行不行?[/b]
bmyyyud
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2010-01-21
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望130点
  • 贡献值0点
  • 好评度106点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2005-04-07 14:30
有两个疑问

(1)是不是每个导出函数都有名字,这个函数能这么写吗?

(2)就算有都有名字,也不见得名字的排列次序跟对应函数的排列次序一样,能这么查找吗?

_____________________________________________
请bmyyyud 和idapro5老大其他熟悉PE的兄弟抽宝贵时间帮忙解惑一下,偶对PE是一窍不通.

另:idapro5,你的idapro5软件能够共享一下吗?偶的才version :4。3

 

不是每个导出函数都有名字,有的只有序号
名字的排列次序跟对应函数的排列次序不一样,但有个对应表可以查找
为了使效率最高,一般把调用最频繁的函数排在前面,这是由编译器决定的
滚滚长江东逝水 浪花淘尽英雄 是非成败转头空 青山依旧在 几度夕阳红 白发渔樵江渚上 惯看秋月春风 一壶浊酒喜相逢 古今多少事 尽付笑谈中
idaxsy
驱动大牛
驱动大牛
  • 注册日期2004-12-09
  • 最后登录2006-03-17
  • 粉丝0
  • 关注0
  • 积分386分
  • 威望54点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2005-04-26 14:05
 
不是每个导出函数都有名字,有的只有序号
名字的排列次序跟对应函数的排列次序不一样,但有个对应表可以查找
为了使效率最高,一般把调用最频繁的函数排在前面,这是由编译器决定的



有道理,我已经调试通过了。
[b]万水千山总是情,回个帖子行不行?[/b]
riceworm
驱动小牛
驱动小牛
  • 注册日期2004-10-27
  • 最后登录2008-10-22
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2005-04-26 14:15
请问楼上的老大,你是怎样解决这个问题的啊?
还有你能帮忙看看下面的帖字吗
http://www.driverdevelop.com/forum/html_91174.html?1114496060
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
16楼#
发布于:2005-04-29 16:30
导出表通过ord来连接的。
PVOID HookFunction(PVOID pBaseAddress, PCSTR Name, PVOID InFunc, ULONG* OutFunc)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeader = NULL;
PIMAGE_DATA_DIRECTORY pDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExports = NULL;
ULONG nSize, Address, i;
PULONG pFunctions = NULL;
PSHORT pOrdinals = NULL;
PULONG pNames = NULL;
PVOID pFunction = NULL;
ULONG Ordinal = 0;

if(pBaseAddress == NULL)
return NULL;

//Pe
pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pBaseAddress + pDosHeader->e_lfanew);
pDirectory = pNtHeader->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;

nSize = pDirectory->Size;
Address = pDirectory->VirtualAddress;

pExports = (PIMAGE_EXPORT_DIRECTORY)((PCHAR)pBaseAddress + Address);

//export directory
pFunctions = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfFunctions);
pOrdinals  = (PSHORT)((PCHAR)pBaseAddress + pExports->AddressOfNameOrdinals);
pNames   = (PULONG)((PCHAR)pBaseAddress + pExports->AddressOfNames);

for(i = 0; i < pExports->NumberOfNames; i++)
{
Ordinal = pOrdinals;
if(pFunctions[Ordinal] < Address || pFunctions[Ordinal] >= Address + nSize)
{
if(strcmp((PSTR)((PCHAR)pBaseAddress + pNames), Name) == 0)
{
pFunction = (PCHAR)pBaseAddress + pFunctions[Ordinal];
*OutFunc = (ULONG)pFunction;
DisableProtection();
pFunctions[Ordinal] = (ULONG)((ULONG)InFunc - (ULONG)pBaseAddress);
EnableProtection();
break;
}
}
}

return pFunction;
}
走走看看开源好 Solaris vs Linux
xiaofang
驱动牛犊
驱动牛犊
  • 注册日期2002-03-12
  • 最后登录2013-04-26
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望67点
  • 贡献值0点
  • 好评度22点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2008-02-02 00:17
Re:hook ntoskrnl.exe的奇怪现象(很久不说\
是这样的名字的导出索引号和导出表中的顺序号不是对应的
必须通过 AddressOfNameOrdinals 取出名字的索引号,才能从导出表中获取正确的地址。
游客

返回顶部