过游戏保护之重载内核

原文链接:http://www.ghostasm.com/thread-1898-1-1.html    


因为之前 代码与360冲突跟基址重定位出了点问题. 今天重新复习改进后 可以直接跳过360hook 与360 不冲突了.

 

注意事项 : 我用的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程序的进程名字 判断是不是我们工具的名字 是 转入新内核 不是走旧内核;
具体的实现方法看代码:

本帖隐藏的内容
  1. #pragma once //只编译一次
  2. #ifdef __cplusplus
  3. extern"C"
  4. {
  5. #endif
  6. #include "ntddk.h"
  7. #include "ntimage.h"
  8. #ifdef __cplusplus
  9. }
  10. #endif //如果是c++代码用c的方式链接{它}
  11. #define _max(a,b)  a>b?a:b
  12. //这是一个SSDT表的结构类型先声明一下
  13. #pragma pack(1)
  14. typedef struct ServiceDescriptorEntry {
  15.         unsigned int *ServiceTableBase;
  16.         unsigned int *ServiceCounterTableBase;
  17.         unsigned int NumberOfServices;
  18.         unsigned char *ParamTableBase;
  19. } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
  20. #pragma pack()
  21. extern "C"{
  22.         __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
  23. }
  24. //遍历驱动名用的一个结构
  25. typedef struct _LDR_DATA_TABLE_ENTRY {
  26.         LIST_ENTRY InLoadOrderLinks;
  27.         LIST_ENTRY InMemoryOrderLinks;
  28.         LIST_ENTRY InInitializationOrderLinks;
  29.         PVOID DllBase;
  30.         PVOID EntryPoint;
  31.         ULONG SizeOfImage;
  32.         UNICODE_STRING FullDllName;
  33.         UNICODE_STRING BaseDllName;
  34.         ULONG Flags;
  35.         USHORT LoadCount;
  36.         USHORT TlsIndex;
  37.         union {
  38.                 LIST_ENTRY HashLinks;
  39.                 struct {
  40.                         PVOID SectionPointer;
  41.                         ULONG CheckSum;
  42.                 };
  43.         };
  44.         union {
  45.                 struct {
  46.                         ULONG TimeDateStamp;
  47.                 };
  48.                 struct {
  49.                         PVOID LoadedImports;
  50.                 };
  51.         };
  52. } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  53. //全局变量
  54. PVOID sizeof_image;    //映射到内存的地址指针
  55. ULONG  OrigImage;    //原来的内核基地址
  56. ServiceDescriptorTableEntry_t *  pNewSSDT;//新SSDT地址
  57. ULONG        g_ntcreatefile;         //保存原始的SSDT
  58. ULONG        g_fastcall_hookpointer; //保存要HOOK的地址
  59. ULONG        g_goto_origfunc;        //判断后要返回的地址
  60. //恢复内存保护 
  61. void PageProtectOn()
  62. {
  63.         __asm
  64.         {
  65.                 mov  eax, cr0
  66.                         or   eax, 10000h
  67.                         mov  cr0, eax
  68.                         sti
  69.         }
  70. }
  71. //去掉内存保护
  72. void PageProtectOff()
  73. {
  74.         __asm
  75.         {
  76.                 cli
  77.                         mov  eax, cr0
  78.                         and  eax, not 10000h
  79.                         mov  cr0, eax
  80.         }
  81. }
  82. //****************************************判断HOOK部分的******************************************
  83. //声明函数指针
  84. typedef NTSTATUS(*NTCREATEFILE) (
  85.         __out PHANDLE FileHandle,
  86.         __in ACCESS_MASK DesiredAccess,
  87.         __in POBJECT_ATTRIBUTES ObjectAttributes,
  88.         __out PIO_STATUS_BLOCK IoStatusBlock,
  89.         __in_opt PLARGE_INTEGER AllocationSize,
  90.         __in ULONG FileAttributes,
  91.         __in ULONG ShareAccess,
  92.         __in ULONG CreateDisposition,
  93.         __in ULONG CreateOptions,
  94.         __in_bcount_opt(EaLength) PVOID EaBuffer,
  95.         __in ULONG EaLength
  96.         );  //声明
  97. //特征码搜寻
  98. ULONG SearchHookPointer(ULONG StartAddress)
  99. {
  100.         ULONG        u_index;
  101.         UCHAR        *p = (UCHAR*)StartAddress;
  102.         for (u_index = 0; u_index < 200; u_index++)
  103.         {
  104.                 if (
  105.                         *p == 0x33 &&
  106.                         *(p + 1) == 0xC9 &&
  107.                         *(p + 2) == 0x8B &&
  108.                         *(p + 3) == 0x57 &&
  109.                         *(p + 4) == 0x0C)
  110.                 {
  111.                         return (ULONG)p;
  112.                 }
  113.                 p--;
  114.         }
  115.         return 0;
  116. }
  117. //进程判断
  118. ULONG   FilterKiFastCallEntry()
  119. {

  120.         ULONG l_deviation;//偏移
  121.         ULONG l_base_address;// 基地址
  122.         ULONG l_current_address;//当前地址
  123.         __asm
  124.         {
  125.                 mov     l_deviation, eax
  126.                         mov     l_base_address, edi
  127.                         mov     l_current_address, edx
  128.         }

  129.         //判断是不是要进入SSDT中的函数
  130.         if (l_base_address == (ULONG)KeServiceDescriptorTable.ServiceTableBase)
  131.         {
  132.                 
  133.                 if (strstr((char*)PsGetCurrentProcess() + 0x16c, "FishcOD.exe") || strstr((char*)PsGetCurrentProcess() + 0x16c, "cheatengine") != 0)
  134.                 {
  135.                         //返回新重载的SSDT里
  136.                         return pNewSSDT->ServiceTableBase[l_deviation];
  137.                 }
  138.         }
  139.         //返回原来的地址
  140.         return l_current_address;
  141. }
  142. //判断是否是我们通行的进程
  143. __declspec(naked)
  144. void NewKiFastCallEntry()
  145. {
  146.         
  147.         __asm
  148.         {
  149.                 xor     ecx, ecx
  150.                         mov     edx, dword ptr[edi + 0Ch]
  151.                         mov     edi, dword ptr[edi]
  152.                         mov     cl, byte ptr[eax + edx]
  153.                         mov     edx, dword ptr[edi + eax * 4]
  154.                         sub     esp, ecx
  155.                         shr     ecx, 2
  156.                         pushad
  157.                         pushfd
  158.                         call        FilterKiFastCallEntry
  159.                         mov[esp + 0x18], eax //换的是栈里边的值

  160.                         popfd
  161.                         popad
  162.                         jmp                g_goto_origfunc
  163.         }
  164. }
  165. //还原HOOK   KiFastCallEntry
  166. void UnHookKiFastCallEntry()
  167. {
  168.         UCHAR        str_origfuncode[5] = { 0x33, 0xC9, 0x8B, 0x57, 0x0C };
  169.         if (g_fastcall_hookpointer == 0)
  170.         {
  171.                 return;
  172.         }
  173.         PageProtectOff();
  174.         RtlCopyMemory((PVOID)g_fastcall_hookpointer, str_origfuncode, 5);
  175.         PageProtectOn();
  176. }
  177. //替换转跳指令
  178. void HookKiFastCallEntry(ULONG HookPointer)
  179. {
  180.         ULONG        u_temp;
  181.         UCHAR        str_jmp_code[5];
  182.         str_jmp_code[0] = 0xE9;
  183.         u_temp = (ULONG)NewKiFastCallEntry - HookPointer - 5;
  184.         *(ULONG*)&str_jmp_code[1] = u_temp;
  185.         PageProtectOff();
  186.         RtlCopyMemory((PVOID)HookPointer, str_jmp_code, 5);
  187.         PageProtectOn();
  188. }
  189. //我们呢自己的NtCreateFile
  190. NTSTATUS NewNtCreateFile(
  191.         __out PHANDLE FileHandle,
  192.         __in ACCESS_MASK DesiredAccess,
  193.         __in POBJECT_ATTRIBUTES ObjectAttributes,
  194.         __out PIO_STATUS_BLOCK IoStatusBlock,
  195.         __in_opt PLARGE_INTEGER AllocationSize,
  196.         __in ULONG FileAttributes,
  197.         __in ULONG ShareAccess,
  198.         __in ULONG CreateDisposition,
  199.         __in ULONG CreateOptions,
  200.         __in_bcount_opt(EaLength) PVOID EaBuffer,
  201.         __in ULONG EaLength
  202.         )
  203. {
  204.         
  205.         ULONG        u_call_retaddr;
  206.         __asm{
  207.                 pushad
  208.                         mov                eax, [ebp + 0x4]
  209.                         mov                u_call_retaddr, eax
  210.                         popad
  211.         }
  212.         g_fastcall_hookpointer = SearchHookPointer(u_call_retaddr);
  213.         if (g_fastcall_hookpointer == 0)
  214.         {
  215.                 KdPrint(("search failed."));
  216.         }
  217.         else{
  218.                 KdPrint(("search success."));
  219.         }
  220.         g_goto_origfunc = g_fastcall_hookpointer + 0x12;
  221.         HookKiFastCallEntry(g_fastcall_hookpointer);
  222.         //还原SSDT
  223.         PageProtectOff();
  224.         KeServiceDescriptorTable.ServiceTableBase[66] = (unsigned int)g_ntcreatefile;
  225.         PageProtectOn();
  226.         
  227.         return ((NTCREATEFILE)g_ntcreatefile)(
  228.                 FileHandle, \
  229.                 DesiredAccess, \
  230.                 ObjectAttributes, \
  231.                 IoStatusBlock, \
  232.                 AllocationSize, \
  233.                 FileAttributes, \
  234.                 ShareAccess, \
  235.                 CreateDisposition, \
  236.                 CreateOptions, \
  237.                 EaBuffer, \
  238.                 EaLength);
  239. }
  240. //HOOKNtCreateFile
  241. void SearchKiFastCallEntry()
  242. {
  243.         
  244.         HANDLE                                hFile;
  245.         NTSTATUS                        Status;
  246.         OBJECT_ATTRIBUTES        ObjAttr;
  247.         UNICODE_STRING                usFileName;
  248.         IO_STATUS_BLOCK                IoStatusBlock;
  249.         RtlInitUnicodeString(&usFileName, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");
  250.         InitializeObjectAttributes(\
  251.                 &ObjAttr, \
  252.                 &usFileName, \
  253.                 OBJ_CASE_INSENSITIVE, \
  254.                 NULL, \
  255.                 NULL);
  256.         g_ntcreatefile = KeServiceDescriptorTable.ServiceTableBase[66];
  257.         PageProtectOff();
  258.         KeServiceDescriptorTable.ServiceTableBase[66] = (unsigned int)NewNtCreateFile;
  259.         PageProtectOn();
  260.         Status = ZwCreateFile(\
  261.                 &hFile, \
  262.                 FILE_ALL_ACCESS, \
  263.                 &ObjAttr, \
  264.                 &IoStatusBlock, \
  265.                 NULL, \
  266.                 FILE_ATTRIBUTE_NORMAL, \
  267.                 FILE_SHARE_READ, \
  268.                 FILE_OPEN, \
  269.                 FILE_NON_DIRECTORY_FILE, \
  270.                 NULL, \
  271.                 0);
  272.         if (NT_SUCCESS(Status))
  273.         {
  274.                 ZwClose(hFile);
  275.         }
  276. }
  277. //************************************重定位部分********************************************************************
  278. //SSDT重定位
  279. VOID RelocationSSDT(PVOID NewAddress, ULONG RawAddress)
  280. {                       
  281.         
  282.         ULONG RelativeOffset; //相对的偏移量
  283.         RelativeOffset = (ULONG)NewAddress - RawAddress;//相对的偏移地址
  284.         pNewSSDT = (ServiceDescriptorTableEntry_t*)((ULONG)&KeServiceDescriptorTable + RelativeOffset); //新SSDT地址
  285.         if (!MmIsAddressValid(pNewSSDT))
  286.         {
  287.                 KdPrint(("pNewSsdt is Error"));
  288.                 return;
  289.         }

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

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

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

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

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

  357.         //创建文件*******
  358.         HANDLE    hfile;     //接受句柄
  359.         NTSTATUS  status;    //状态
  360.         IO_STATUS_BLOCK      io_status_block;    //接受状态结构
  361.         OBJECT_ATTRIBUTES    object_attributes;  //句柄属性
  362.         UNICODE_STRING       path_name;
  363.         RtlInitUnicodeString(&path_name, L"\\??\\C:\\Windows\\System32\\ntkrnlpa.exe");
  364.         //初始化对象属性
  365.         InitializeObjectAttributes(&object_attributes, //对象属性变量 POBJECT_ATTRIBUTES OUT  
  366.                 &path_name,                                                                   //文件名   PUNICODE_STRING
  367.                 OBJ_CASE_INSENSITIVE,                      //表示不区分大小写
  368.                 NULL,                                      //NULL
  369.                 NULL);                                     //NULL
  370.         //创建文件
  371.         status = ZwCreateFile(
  372.                 &hfile,                  //返回的句柄  OUT PHANDLE
  373.                 FILE_ALL_ACCESS,         //访问权限->所有权限
  374.                 &object_attributes,      //POBJECT_ATTRIBUTES 该结构包含要打开的文件名
  375.                 &io_status_block,        //PIO_STATUS_BLOCK 返回结果状态 OUT
  376.                 0,                       //初始分配大小,0是动态分配
  377.                 FILE_ATTRIBUTE_NORMAL,   //文件属性 一般为<-或者0;
  378.                 FILE_SHARE_READ,         //指定共享方式一般<- 或者0;
  379.                 FILE_OPEN,               //这个参数指定要对文件干嘛
  380.                 FILE_NON_DIRECTORY_FILE, //指定控制打开操作和句柄使用的附加标志位
  381.                 NULL,                    //指向可选的扩展属性区
  382.                 0);                      //扩展属性区的长度
  383.         if (!NT_SUCCESS(status))
  384.         {
  385.                 KdPrint(("ZwCreateFile Failed!"));
  386.                 return;
  387.         }
  388.         //读取DOS头******
  389.         IMAGE_DOS_HEADER        image_dos_header;//dos头结构
  390.         LARGE_INTEGER       large_integer;//记录偏移
  391.         large_integer.QuadPart = 0;
  392.         status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
  393.                 NULL,                        //一个事件  NULL
  394.                 NULL,                        //回调例程。NULL
  395.                 NULL,                        //NULL
  396.                 &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
  397.                 &image_dos_header,           //存放读取数据的缓冲区 OUT PVOID  
  398.                 sizeof(IMAGE_DOS_HEADER),    //试图读取文件的长度
  399.                 &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
  400.                 0);                          //NULL
  401.         if (!NT_SUCCESS(status))
  402.         {
  403.                 KdPrint(("Read ImageDosHeader Failed!"));
  404.                 ZwClose(hfile);
  405.                 return;
  406.         }
  407.         //读取NT头*******
  408.         IMAGE_NT_HEADERS   image_nt_header;//NT头
  409.         large_integer.QuadPart = image_dos_header.e_lfanew; //PE头偏移
  410.         status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
  411.                 NULL,                        //一个事件  NULL
  412.                 NULL,                        //回调例程。NULL
  413.                 NULL,                        //NULL
  414.                 &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
  415.                 &image_nt_header,           //存放读取数据的缓冲区 OUT PVOID  
  416.                 sizeof(IMAGE_NT_HEADERS),    //试图读取文件的长度
  417.                 &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
  418.                 0);                          //NULL
  419.         if (!NT_SUCCESS(status))
  420.         {
  421.                 KdPrint(("Read image_nt_header Failed!"));
  422.                 ZwClose(hfile);
  423.                 return;
  424.         }
  425.         //读取区块*****
  426.         IMAGE_SECTION_HEADER * p_image_section_header;//指向多个区块结构
  427.         //分配所有模块总大小
  428.         p_image_section_header = (IMAGE_SECTION_HEADER*)ExAllocatePool(NonPagedPool,        //NonPagedPool  从非分页内存池中分配内存 
  429.                 sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections);
  430.         //读
  431.         large_integer.QuadPart += sizeof(IMAGE_NT_HEADERS); //区块偏移
  432.         status = ZwReadFile(hfile,       //ZwCreateFile成功后得到的句柄  
  433.                 NULL,                        //一个事件  NULL
  434.                 NULL,                        //回调例程。NULL
  435.                 NULL,                        //NULL
  436.                 &io_status_block,            //PIO_STATUS_BLOCK 返回结果状态 OUT ,同上
  437.                 p_image_section_header,           //存放读取数据的缓冲区 OUT PVOID  
  438.                 sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections,    //试图读取文件的长度
  439.                 &large_integer,              //要读取数据相对文件的偏移量PLARGE_INTEGER
  440.                 0);                          //NULL
  441.         if (!NT_SUCCESS(status))
  442.         {
  443.                 KdPrint(("Read p_image_section_header Failed!"));
  444.                 ExFreePool(p_image_section_header);
  445.                 ZwClose(hfile);
  446.                 return;
  447.         }
  448.         //复制数据**********
  449.         //PVOID sizeof_image;//定义成全局变量  因为卸载的时候要释放掉内存
  450.         sizeof_image = ExAllocatePool(NonPagedPool, image_nt_header.OptionalHeader.SizeOfImage);//NonPagedPool  从非分页内存池中分配内存 
  451.         if (sizeof_image == 0)
  452.         {
  453.                 KdPrint(("sizeof_image ExAllocatePool Failed!"));
  454.                 ExFreePool(sizeof_image);
  455.                 ExFreePool(p_image_section_header);  //释放内存
  456.                 ZwClose(hfile);
  457.                 return;
  458.         }
  459.         //初始化下内存
  460.         memset(sizeof_image, 0, image_nt_header.OptionalHeader.SizeOfImage);
  461.         RtlCopyMemory(sizeof_image, &image_dos_header, sizeof(IMAGE_DOS_HEADER));        //dos头
  462.         RtlCopyMemory((PVOID)((ULONG)sizeof_image + image_dos_header.e_lfanew),
  463.                 &image_nt_header, sizeof(IMAGE_NT_HEADERS));                                 //nt头
  464.         RtlCopyMemory((PVOID)((ULONG)sizeof_image + image_dos_header.e_lfanew + sizeof(IMAGE_NT_HEADERS)),       //区块
  465.                 p_image_section_header, sizeof(IMAGE_SECTION_HEADER)*image_nt_header.FileHeader.NumberOfSections);//计算区块总大小

  466.         
  467.         ULONG sizeof_raw_data;
  468.         for (ULONG i = 0; i<image_nt_header.FileHeader.NumberOfSections; i++)
  469.         {   
  470.                 sizeof_raw_data = _max(p_image_section_header[i].Misc.VirtualSize, p_image_section_header[i].SizeOfRawData);
  471.                 large_integer.QuadPart = p_image_section_header[i].PointerToRawData;   
  472.                 //读
  473.                 status = ZwReadFile(hfile,        
  474.                         NULL,                        
  475.                         NULL,                        
  476.                         NULL,                        
  477.                         &io_status_block,            
  478.                         (PVOID)((ULONG)sizeof_image + p_image_section_header[i].VirtualAddress),          
  479.                         sizeof_raw_data,             
  480.                         &large_integer,              
  481.                         0);                          
  482.                 if (!NT_SUCCESS(status))
  483.                 {
  484.                         KdPrint(("循环区块出错[%s]%x\n",
  485.                                 p_image_section_header[i].Name,
  486.                                 (ULONG)sizeof_image + p_image_section_header[i].VirtualAddress));

  487.                         ExFreePool(sizeof_image);
  488.                         ExFreePool(p_image_section_header);  //释放内存
  489.                         ZwClose(hfile);
  490.                         return;
  491.                 }
  492.         }
  493.         BaseRelocation(sizeof_image);
  494.         KdPrint(("重载内存成功"));

  495.         ExFreePool(p_image_section_header);  
  496.         ZwClose(hfile);
  497.         return;
  498. }
  499. //动态获取基地址
  500. PVOID SearchDriver(PDRIVER_OBJECT pDriverObject, wchar_t *strDriverName)
  501. {   


  502.         LDR_DATA_TABLE_ENTRY        *pDataTableEntry, *pTempDataTableEntry;
  503.         PLIST_ENTRY                                pList;        //下一个节点
  504.         UNICODE_STRING                        usModuleName; // 存放字符串
  505.         
  506.         RtlInitUnicodeString(&usModuleName, strDriverName);
  507.         
  508.         pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;
  509.         if (!pDataTableEntry)
  510.         {
  511.                 return 0;
  512.         }

  513.         pList = pDataTableEntry->InLoadOrderLinks.Flink;

  514.         
  515.         while (pList != &pDataTableEntry->InLoadOrderLinks)
  516.         {
  517.                 
  518.                 pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY *)pList;

  519.                 
  520.                 if (0 == RtlCompareUnicodeString(&pTempDataTableEntry->BaseDllName, &usModuleName, FALSE))
  521.                 {
  522.                         return pTempDataTableEntry->DllBase;

  523.                 }
  524.                 
  525.                 pList = pList->Flink;
  526.         }
  527.         KdPrint(("获取ntkrnlpa.exe基地址失败"));
  528.         return 0;
  529. }
  530. //***************************************************************************
  531. //卸载函数
  532. VOID MyDriverUnload(IN PDRIVER_OBJECT pDriverObject)
  533. {
  534.         KdPrint(("成功进入卸载函数"));
  535.         if (sizeof_image != 0)
  536.         {
  537.                 KdPrint(("sizeof_image内存释放"));
  538.                 ExFreePool(sizeof_image);//释放内存
  539.         }
  540.         UnHookKiFastCallEntry();
  541.         KdPrint(("全部卸载完成"));
  542. }
  543. //驱动入口
  544. extern"C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
  545.         IN PUNICODE_STRING pRegistryPath)
  546. {
  547.         KdPrint(("加载驱动成功"));
  548.         pDriverObject->DriverUnload = MyDriverUnload;//卸载函数
  549.         //获取基地址
  550.         OrigImage = (ULONG)SearchDriver(pDriverObject, L"ntoskrnl.exe");
  551.         if (!OrigImage)
  552.         {
  553.                 KdPrint(("获取ntoskrnl.exe失败"));
  554.                 return 0;
  555.         }
  556.         KdPrint(("ntoskrnl.exe驱动模块首地址=%x", OrigImage));
  557.         //内核重载
  558.         ReloadKernel();
  559.         RelocationSSDT(sizeof_image, OrigImage);
  560.         KdPrint(("加载内存模块首地址=%x", sizeof_image));
  561.         //HOOK KiFastCallEntry;
  562.         SearchKiFastCallEntry();
  563.         return STATUS_SUCCESS;
  564. }
复制代码
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值