[驱动开发]重载内核(一)

注意事项 : 我用的OD是 自己有保护的,经过内核重载 CE就能打开OD了 没重载之前呢 是看不到OD进程的
不要跟360HOOK了一个点 要不就会蓝屏 ,  加载驱动前一定要检查 有没有被HOOK NtCreateFile 函数否则就会加载失败的
重点注意QQ 它的驱动HOOK了不少函数而且是重启不会取消的HOOK  解决办法就是把它的驱动删除了 重启 就OK
比如打开了 CE 一定要先把CE关掉以后 才能卸载重载驱动 要不就会蓝屏

首先呢我们要学的是一个思想,过程代码就放在哪跟着代码一步一步看最后作者的意思是什么就会明白.也能自己调用但是如果分析的内容变了我们如何操作.假如换个系统  有好多东西要变,一个微小的改变就会造成致命的错误.
所以要学的是思路.百变不离其宗,如果我们明白细节了 我们就可以以不变应万变.(废话就说到这里了)
1.应用层要进入内核层要通过一个函数来进行KiFastCallEntry()函数  我们要定位到这个函数就要用到栈回溯(其中一个方法);
就是如果应用层进入KiFastCallEntry()函数 在这个函数里就要CALL SSDT里的函数才行.   
每次call  函数后 就会把CALL下面一个地址保存到堆栈里 然后更据函数调用约定 每次调用CALL就会在函数头部
mov edi,edi   push ebp  mov ebp,esp    所有到函数里后我们去堆栈里获取ebp加4的地址 就是我们要转跳的
KiFastCallEntry 这个函数里 然后更加搜索特征码找到我们要HOOK的点进行HOOK就行了

2__declspec(naked)  这是一个函数调用约定 目的是 不让函数开头  mov edi,edi   push ebp  mov ebp,esp 这3句  
这要放到我们要JMP转跳的那个函数上边,  本来函数调用要有 mov edi,edi   push ebp  mov ebp,esp 到结束的时候会 pop ebp
但是我们没有执行到retn 语句 不会pop  为了 堆栈平衡 我们要在函数头加上 __declspec(naked
3.HOOK点  由于360 也HOOK了那个点  相同的位置会蓝屏  我们就分析 直接从上边的一个5字节地址开始
进入自己的函数 然后把中间缺少的代码 复制到我们自己的函数里 然后转跳到360HOOK的下面的地址
这样就绕过360了.我们也得到了我们想要得到的数据 及实现的功能
JMP哪的 是有5个字节的代码的  我们可以从一个没有被HOOK过也从来没打开过360的系统里用windbg来获取相关的
反汇编代码

4经过分析发现edx正是一个SSDT的函数地址
所有我们判断如果进入SSDT的函数的进程使我们的工具就 把堆栈里的edx值修改成我们新内核的SSDT函数对应的地址
这样我们的工具就通行无阻了 ;    edx在堆栈中如何找到呢 看下图  esp(当前栈顶位置)加0x18的位置就是我们要修改的值edx的位置



具体的实现步骤呢  
内核重载:
1.把ntkrnlpa.exe从磁盘中 加载到内存 
2.内核基地址重定位 
3 SSDT重定位    .还有一个动态获取已加载驱动ntkrnlpa.exe的首地址
4. 先自己调用一个SSDT函数 获得KiFastCallEntry 的函数地址 然后HOOK  

获取 调用SSDT程序的进程名字 判断是不是我们工具的名字 是 转入新内核 不是走旧内核;


代码如下:


#pragma once //只编译一次
#ifdef __cplusplus
extern"C"
{
#endif
#include "ntddk.h"
#include "ntimage.h"
#ifdef __cplusplus
}
#endif //如果是c++代码用c的方式链接{它}
#define _max(a,b)  a>b?a:b
//这是一个SSDT表的结构类型先声明一下
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase;
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
extern "C"{
        __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
}
//遍历驱动名用的一个结构
typedef struct _LDR_DATA_TABLE_ENTRY {
        LIST_ENTRY InLoadOrderLinks;
        LIST_ENTRY InMemoryOrderLinks;
        LIST_ENTRY InInitializationOrderLinks;
        PVOID DllBase;
        PVOID EntryPoint;
        ULONG SizeOfImage;
        UNICODE_STRING FullDllName;
        UNICODE_STRING BaseDllName;
        ULONG Flags;
        USHORT LoadCount;
        USHORT TlsIndex;
        union {
                LIST_ENTRY HashLinks;
                struct {
                        PVOID SectionPointer;
                        ULONG CheckSum;
                };
        };
        union {
                struct {
                        ULONG TimeDateStamp;
                };
                struct {
                        PVOID LoadedImports;
                };
        };
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
//全局变量
PVOID sizeof_image;    //映射到内存的地址指针
ULONG  OrigImage;    //原来的内核基地址
ServiceDescriptorTableEntry_t *  pNewSSDT;//新SSDT地址
ULONG        g_ntcreatefile;         //保存原始的SSDT
ULONG        g_fastcall_hookpointer; //保存要HOOK的地址
ULONG        g_goto_origfunc;        //判断后要返回的地址
//恢复内存保护 
void PageProtectOn()
{
        __asm
        {
                mov  eax, cr0
                        or   eax, 10000h
                        mov  cr0, eax
                        sti
        }
}
//去掉内存保护
void PageProtectOff()
{
        __asm
        {
                cli
                        mov  eax, cr0
                        and  eax, not 10000h
                        mov  cr0, eax
        }
}
//****************************************判断HOOK部分的******************************************
//声明函数指针
typedef NTSTATUS(*NTCREATEFILE) (
        __out PHANDLE FileHandle,
        __in ACCESS_MASK DesiredAccess,
        __in POBJECT_ATTRIBUTES ObjectAttributes,
        __out PIO_STATUS_BLOCK IoStatusBlock,
        __in_opt PLARGE_INTEGER AllocationSize,
        __in ULONG FileAttributes,
        __in ULONG ShareAccess,
        __in ULONG CreateDisposition,
        __in ULONG CreateOptions,
        __in_bcount_opt(EaLength) PVOID EaBuffer,
        __in ULONG EaLength
        );  //声明
//特征码搜寻
ULONG SearchHookPointer(ULONG StartAddress)
{
        ULONG        u_index;
        UCHAR        *p = (UCHAR*)StartAddress;
        for (u_index = 0; u_index < 200; u_index++)
        {
                if (
                        *p == 0x33 &&
                        *(p + 1) == 0xC9 &&
                        *(p + 2) == 0x8B &&
                        *(p + 3) == 0x57 &&
                        *(p + 4) == 0x0C)
                {
                        return (ULONG)p;
                }
                p--;
        }
        return 0;
}
//进程判断
ULONG   FilterKiFastCallEntry()
{

        ULONG l_deviation;//偏移
        ULONG l_base_address;// 基地址
        ULONG l_current_address;//当前地址
        __asm
        {
                mov     l_deviation, eax
                        mov     l_base_address, edi
                        mov     l_current_address, edx
        }

        //判断是不是要进入SSDT中的函数
        if (l_base_address == (ULONG)KeServiceDescriptorTable.ServiceTableBase)
        {
                
                if (strstr((char*)PsGetCurrentProcess() + 0x16c, "FishcOD.exe") || strstr((char*)PsGetCurrentProcess() + 0x16c, "cheatengine") != 0)
                {
                        //返回新重载的SSDT里
                        return pNewSSDT->ServiceTableBase[l_deviation];
                }
        }
        //返回原来的地址
        return l_current_address;
}
//判断是否是我们通行的进程
__declspec(naked)
void NewKiFastCallEntry()
{
        
        __asm
        {
                xor     ecx, ecx
                        mov     edx, dword ptr[edi + 0Ch]
                        mov     edi, dword ptr[edi]
                        mov     cl, byte ptr[eax + edx]
                        mov     edx, dword ptr[edi + eax * 4]
                        sub     esp, ecx
                        shr     ecx, 2
                        pushad
                        pushfd
                        call        FilterKiFastCallEntry
                        mov[esp + 0x18], eax //换的是栈里边的值

                        popfd
                        popad
                        jmp                g_goto_origfunc
        }
}
//还原HOOK   KiFastCallEntry
void UnHookKiFastCallEntry()
{
        UCHAR        str_origfuncode[5] = { 0x33, 0xC9, 0x8B, 0x57, 0x0C };
        if (g_fastcall_hookpointer == 0)
        {
                return;
        }
        PageProtectOff();
        RtlCopyMemory((PVOID)g_fastcall_hookpointer, str_origfuncode, 5);
        PageProtectOn();
}
//替换转跳指令
void HookKiFastCallEntry(ULONG HookPointer)
{
        ULONG        u_temp;
        UCHAR        str_jmp_code[5];
        str_jmp_code[0] = 0xE9;
        u_temp = (ULONG)NewKiFastCallEntry - HookPointer - 5;
        *(ULONG*)&str_jmp_code[1] = u_temp;
        PageProtectOff();
        RtlCopyMemory((PVOID)HookPointer, str_jmp_code, 5);
        PageProtectOn();
}
//我们呢自己的NtCreateFile
NTSTATUS NewNtCreateFile(
        __out PHANDLE FileHandle,
        __in ACCESS_MASK DesiredAccess,
        __in POBJECT_ATTRIBUTES ObjectAttributes,
        __out PIO_STATUS_BLOCK IoStatusBlock,
        __in_opt PLARGE_INTEGER AllocationSize,
        __in ULONG FileAttributes,
        __in ULONG ShareAccess,
        __in ULONG CreateDisposition,
        __in ULONG CreateOptions,
        __in_bcount_opt(EaLength) PVOID EaBuffer,
        __in ULONG EaLength
        )
{
        
        ULONG        u_call_retaddr;
        __asm{
                pushad
                        mov                eax, [ebp + 0x4]
                        mov                u_call_retaddr, eax
                        popad
        }
        g_fastcall_hookpointer = SearchHookPointer(u_call_retaddr);
        if (g_fastcall_hookpointer == 0)
        {
                KdPrint(("search failed."));
        }
        else{
                KdPrint(("search success."));
        }
        g_goto_origfunc = g_fastcall_hookpointer + 0x12;
        HookKiFastCallEntry(g_fastcall_hookpointer);
        //还原SSDT
        PageProtectOff();
        KeServiceDescriptorTable.ServiceTableBase[66] = (unsigned int)g_ntcreatefile;
        PageProtectOn();
        
        return ((NTCREATEFILE)g_ntcreatefile)(
                FileHandle, \
                DesiredAccess, \
                ObjectAttributes, \
                IoStatusBlock, \
                AllocationSize, \
                FileAttributes, \
                ShareAccess, \
                CreateDisposition, \
                CreateOptions, \
                EaBuffer, \
                EaLength);
}
//HOOKNtCreateFile
void SearchKiFastCallEntry()
{
        
        HANDLE                                hFile;
        NTSTATUS                        Status;
        OBJECT_ATTRIBUTES        ObjAttr;
        UNICODE_STRING                usFileName;
        IO_STATUS_BLOCK                IoStatusBlock;
        RtlInitUnicodeString(&usFileName, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");
        InitializeObjectAttributes(\
                &ObjAttr, \
                &usFileName, \
                OBJ_CASE_INSENSITIVE, \
                NULL, \
                NULL);
        g_ntcreatefile = KeServiceDescriptorTable.ServiceTableBase[66];
        PageProtectOff();
        KeServiceDescriptorTable.ServiceTableBase[66] = (unsigned int)NewNtCreateFile;
        PageProtectOn();
        Status = ZwCreateFile(\
                &hFile, \
                FILE_ALL_ACCESS, \
                &ObjAttr, \
                &IoStatusBlock, \
                NULL, \
                FILE_ATTRIBUTE_NORMAL, \
                FILE_SHARE_READ, \
                FILE_OPEN, \
                FILE_NON_DIRECTORY_FILE, \
                NULL, \
                0);
        if (NT_SUCCESS(Status))
        {
                ZwClose(hFile);
        }
}
//************************************重定位部分********************************************************************
//SSDT重定位
VOID RelocationSSDT(PVOID NewAddress, ULONG RawAddress)
{                       
        
        ULONG RelativeOffset; //相对的偏移量
        RelativeOffset = (ULONG)NewAddress - RawAddress;//相对的偏移地址
        pNewSSDT = (ServiceDescriptorTableEntry_t*)((ULONG)&KeServiceDescriptorTable + RelativeOffset); //新SSDT地址
        if (!MmIsAddressValid(pNewSSDT))
        {
                KdPrint(("pNewSsdt is Error"));
                return;
        }

        pNewSSDT->NumberOfServices = KeServiceDescriptorTable.NumberOfServices; //拷贝SSDT函数数量
        ULONG uDeviation; //函数偏移
        uDeviation = (ULONG)KeServiceDescriptorTable.ServiceTableBase - RawAddress;//Relative Virtual Address 相对于基址
        pNewSSDT->ServiceTableBase = (unsigned int*)((ULONG)NewAddress + uDeviation); //新地址加相对偏移地址(旧SSDT-旧基址)
        if (!MmIsAddressValid(pNewSSDT->ServiceTableBase))
        {
                KdPrint(("pNewSSDT->ServiceTableBase is Error"));
                return;
        }
        //遍历修改SSDTServiceTableBase数组的值
        int i;
        for (i = 0; i<pNewSSDT->NumberOfServices; i++)
        {
                pNewSSDT->ServiceTableBase[i] += RelativeOffset;
        }

        KdPrint(("success RelocationSSDT"));
}
//基地址重定位
void BaseRelocation(PVOID pNewImage)
{
        ULONG                                        i;                    //for循环变量
        ULONG                                        uRelocTableSize;      //存放数据块中的数据总个数
        ULONG                                        OriginalImageBase;    //内存文件的首装入地址
        ULONG                                        Type;                 //16位数据高4位
        ULONG                                         *uRelocAddress;       //指向需要修改内容的地址
        PIMAGE_DOS_HEADER                pImageDosHeader;      //DOS头
        PIMAGE_NT_HEADERS                pImageNtHeader;       //NT头
        IMAGE_DATA_DIRECTORY        ImageDataDirectory;   //数据表
        IMAGE_BASE_RELOCATION        *pImageBaseRelocation;//重定位表

        //将新内核地址作为一个PE文件头,依次向下,目的是寻找重定位表结构
        pImageDosHeader = (PIMAGE_DOS_HEADER)pNewImage;
        //定位到IMAGE_NT_HEADER
        pImageNtHeader = (PIMAGE_NT_HEADERS)((ULONG)pNewImage + pImageDosHeader->e_lfanew);
        //获取内核文件的imagebase,以便后面做偏移修改。
        OriginalImageBase = pImageNtHeader->OptionalHeader.ImageBase;
        //定位到数据目录
        ImageDataDirectory = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
        //定位到重定位表结构
        pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(ImageDataDirectory.VirtualAddress + (ULONG)pNewImage);
        if (pImageBaseRelocation == NULL)
        {
                return;
        }
        //修改数据*************************
        while (pImageBaseRelocation->SizeOfBlock)
        {   //得到需要更改数据的个数

                uRelocTableSize = (pImageBaseRelocation->SizeOfBlock - 8) / 2;
                //循环遍历
                for (i = 0; i<uRelocTableSize; i++)
                {//判断高4位是否等于3
                        Type = pImageBaseRelocation->TypeOffset[i] >> 12;
                        if (Type == IMAGE_REL_BASED_HIGHLOW)
                        {
                                //让指针指向要修改的数据
                                uRelocAddress = (ULONG *)((ULONG)(pImageBaseRelocation->TypeOffset[i] & 0xfff) + pImageBaseRelocation->VirtualAddress + (ULONG)pNewImage);
                                //修改重定位数据,原数据加上一个偏移
                                *uRelocAddress = (*uRelocAddress + (OrigImage - OriginalImageBase));

                        }
                }
                //把指针移到下一个快,如果->SizeOfBlock为空了,表示没有块了退出循环
                pImageBaseRelocation = (IMAGE_BASE_RELOCATION *)((ULONG)pImageBaseRelocation + pImageBaseRelocation->SizeOfBlock);
        }
        KdPrint(("基址重定位完毕"));
}
//重载内核
VOID  ReloadKernel()  //重载内核
{

        //创建文件*******
        HANDLE    hfile;     //接受句柄
        NTSTATUS  status;    //状态
        IO_STATUS_BLOCK      io_status_block;    //接受状态结构
        OBJECT_ATTRIBUTES    object_attributes;  //句柄属性
        UNICODE_STRING       path_name;
        RtlInitUnicodeString(&path_name, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");
        //初始化对象属性
        InitializeObjectAttributes(&object_attributes, //对象属性变量 POBJECT_ATTRIBUTES OUT  
                &path_name,                                                                   //文件名   PUNICODE_STRING
                OBJ_CASE_INSENSITIVE,                      //表示不区分大小写
                NULL,                                      //NULL
                NULL);                                     //NULL
        //创建文件
        status = ZwCreateFile(
                &hfile,                  //返回的句柄  OUT PHANDLE
                FILE_ALL_ACCESS,         //访问权限->所有权限
                &object_attributes,      //POBJECT_ATTRIBUTES 该结构包含要打开的文件名
                &io_status_block,        //PIO_STATUS_BLOCK 返回结果状态 OUT
                0,                       //初始分配大小,0是动态分配
                FILE_ATTRIBUTE_NORMAL,   //文件属性 一般为<-或者0;
                FILE_SHARE_READ,         //指定共享方式一般<- 或者0;
                FILE_OPEN,               //这个参数指定要对文件干嘛
                FILE_NON_DIRECTORY_FILE, //指定控制打开操作和句柄使用的附加标志位
                NULL,                    //指向可选的扩展属性区
                0);                      //扩展属性区的长度
        if (!NT_SUCCESS(status))
        {
                KdPrint(("ZwCreateFile Failed!"));
                return;
        }
        //读取DOS头******
        IMAGE_DOS_HEADER        image_dos_header;//dos头结构
        LARGE_INTEGER       large_integer;//记录偏移
        large_integer.QuadPart = 0;
        status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
                NULL,                        //一个事件  NULL
                NULL,                        //回调例程。NULL
                NULL,                        //NULL
                &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
                &image_dos_header,           //存放读取数据的缓冲区 OUT PVOID  
                sizeof(IMAGE_DOS_HEADER),    //试图读取文件的长度
                &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
                0);                          //NULL
        if (!NT_SUCCESS(status))
        {
                KdPrint(("Read ImageDosHeader Failed!"));
                ZwClose(hfile);
                return;
        }
        //读取NT头*******
        IMAGE_NT_HEADERS   image_nt_header;//NT头
        large_integer.QuadPart = image_dos_header.e_lfanew; //PE头偏移
        status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
                NULL,                        //一个事件  NULL
                NULL,                        //回调例程。NULL
                NULL,                        //NULL
                &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
                &image_nt_header,           //存放读取数据的缓冲区 OUT PVOID  
                sizeof(IMAGE_NT_HEADERS),    //试图读取文件的长度
                &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
                0);                          //NULL
        if (!NT_SUCCESS(status))
        {
                KdPrint(("Read image_nt_header Failed!"));
                ZwClose(hfile);
                return;
        }
        //读取区块*****
        IMAGE_SECTION_HEADER * p_image_section_header;//指向多个区块结构
        //分配所有模块总大小
        p_image_section_header = (IMAGE_SECTION_HEADER*)ExAllocatePool(NonPagedPool,        //NonPagedPool  从非分页内存池中分配内存 
                sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections);
        //读
        large_integer.QuadPart += sizeof(IMAGE_NT_HEADERS); //区块偏移
        status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
                NULL,                        //一个事件  NULL
                NULL,                        //回调例程。NULL
                NULL,                        //NULL
                &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
                p_image_section_header,           //存放读取数据的缓冲区 OUT PVOID  
                sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections,    //试图读取文件的长度
                &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
                0);                          //NULL
        if (!NT_SUCCESS(status))
        {
                KdPrint(("Read p_image_section_header Failed!"));
                ExFreePool(p_image_section_header);
                ZwClose(hfile);
                return;
        }
        //复制数据**********
        //PVOID sizeof_image;//定义成全局变量  因为卸载的时候要释放掉内存
        sizeof_image = ExAllocatePool(NonPagedPool, image_nt_header.OptionalHeader.SizeOfImage);//NonPagedPool  从非分页内存池中分配内存 
        if (sizeof_image == 0)
        {
                KdPrint(("sizeof_image ExAllocatePool Failed!"));
                ExFreePool(sizeof_image);
                ExFreePool(p_image_section_header);  //释放内存
                ZwClose(hfile);
                return;
        }
        //初始化下内存
        memset(sizeof_image, 0, image_nt_header.OptionalHeader.SizeOfImage);
        RtlCopyMemory(sizeof_image, &image_dos_header, sizeof(IMAGE_DOS_HEADER));        //dos头
        RtlCopyMemory((PVOID)((ULONG)sizeof_image + image_dos_header.e_lfanew),
                &image_nt_header, sizeof(IMAGE_NT_HEADERS));                                 //nt头
        RtlCopyMemory((PVOID)((ULONG)sizeof_image + image_dos_header.e_lfanew + sizeof(IMAGE_NT_HEADERS)),       //区块
                p_image_section_header, sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections);//计算区块总大小

        
        ULONG sizeof_raw_data;
        for (ULONG i = 0; i<image_nt_header.FileHeader.NumberOfSections; i++)
        {   
                sizeof_raw_data = _max(p_image_section_header[i].Misc.VirtualSize, p_image_section_header[i].SizeOfRawData);
                large_integer.QuadPart = p_image_section_header[i].PointerToRawData;   
                //读
                status = ZwReadFile(hfile,        
                        NULL,                        
                        NULL,                        
                        NULL,                        
                        &io_status_block,            
                        (PVOID)((ULONG)sizeof_image + p_image_section_header[i].VirtualAddress),          
                        sizeof_raw_data,             
                        &large_integer,              
                        0);                          
                if (!NT_SUCCESS(status))
                {
                        KdPrint(("循环区块出错[%s]%x\n",
                                p_image_section_header[i].Name,
                                (ULONG)sizeof_image + p_image_section_header[i].VirtualAddress));

                        ExFreePool(sizeof_image);
                        ExFreePool(p_image_section_header);  //释放内存
                        ZwClose(hfile);
                        return;
                }
        }
        BaseRelocation(sizeof_image);
        KdPrint(("重载内存成功"));

        ExFreePool(p_image_section_header);  
        ZwClose(hfile);
        return;
}
//动态获取基地址
PVOID SearchDriver(PDRIVER_OBJECT pDriverObject, wchar_t *strDriverName)
{   


        LDR_DATA_TABLE_ENTRY        *pDataTableEntry, *pTempDataTableEntry;
        PLIST_ENTRY                                pList;        //下一个节点
        UNICODE_STRING                        usModuleName; // 存放字符串
        
        RtlInitUnicodeString(&usModuleName, strDriverName);
        
        pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;
        if (!pDataTableEntry)
        {
                return 0;
        }

        pList = pDataTableEntry->InLoadOrderLinks.Flink;

        
        while (pList != &pDataTableEntry->InLoadOrderLinks)
        {
                
                pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY *)pList;

                
                if (0 == RtlCompareUnicodeString(&pTempDataTableEntry->BaseDllName, &usModuleName, FALSE))
                {
                        return pTempDataTableEntry->DllBase;

                }
                
                pList = pList->Flink;
        }
        KdPrint(("获取ntkrnlpa.exe基地址失败"));
        return 0;
}
//***************************************************************************
//卸载函数
VOID MyDriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
        KdPrint(("成功进入卸载函数"));
        if (sizeof_image != 0)
        {
                KdPrint(("sizeof_image内存释放"));
                ExFreePool(sizeof_image);//释放内存
        }
        UnHookKiFastCallEntry();
        KdPrint(("全部卸载完成"));
}
//驱动入口
extern"C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
        IN PUNICODE_STRING pRegistryPath)
{
        KdPrint(("加载驱动成功"));
        pDriverObject->DriverUnload = MyDriverUnload;//卸载函数
        //获取基地址
        OrigImage = (ULONG)SearchDriver(pDriverObject, L"ntoskrnl.exe");
        if (!OrigImage)
        {
                KdPrint(("获取ntoskrnl.exe失败"));
                return 0;
        }
        KdPrint(("ntoskrnl.exe驱动模块首地址=%x", OrigImage));
        //内核重载
        ReloadKernel();
        RelocationSSDT(sizeof_image, OrigImage);
        KdPrint(("加载内存模块首地址=%x", sizeof_image));
        //HOOK KiFastCallEntry;
        SearchKiFastCallEntry();
        return STATUS_SUCCESS;
}
复制代码

原文链接: [驱动开发]重载内核(一) 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://www.gyarmy.com/post-497.html )

发表评论

0则评论给“[驱动开发]重载内核(一)”