a2205368958 发表于 2018-8-27 10:04:27

windows驱动开发从零基础到入坑!

本帖最后由 a2205368958 于 2018-8-29 08:09 编辑

这只是个X86钩子的例子,学好原理去X64下一样可以用
不要给我说什么X64 有PG保护,无法进行Hook 操作,PG是PG钩子是钩子,再说PG很难过吗?



讲一下内核实现inline hook的过程
和钩子原理
这个东西,不是什么深奥技术,和R3层的path补丁没啥本质上的区别
我只用了例子来讲解。

用内核钩子技术实现驱动级变速,可以加速很多游戏。

B站地址
https://www.bilibili.com/video/av26193169/
百度地址
链接:https://pan.baidu.com/s/1ivk596To_rRCP5_V2Aje_A 密码:t0gf

这次我上传下源码吧
方便大家分析
#include <ntddk.h>
#include <windef.h>

PVOID orinUpdateTime = NULL;
PVOID orinQuery = NULL;
// 变速基数
const DWORD g_dwSpeedBase = 100;
// 变速数值
DWORD g_dwSpeed_X = 1000;
PVOID orinUpdateTimeCode =NULL;
LARGE_INTEGER g_liPreOriginalCounter;

// 变化后的性能指标数值
LARGE_INTEGER g_liPreReturnCounter;
PVOID orinQueryCode = NULL;
void __declspec(naked) WPOFF()
{
      __asm
      {
                cli
                        mov eax, cr0
                        and eax, not 0x10000
                        mov cr0, eax
                        ret
      }
}


// 开中断
void __declspec(naked) WPON()
{
      __asm
      {
                moveax, cr0
                        or   eax, 0x10000
                        movcr0, eax
                        sti
                        ret
      }
}


VOID __declspec(naked) __cdecl JmpOriginal_KeUpdateSystemTime()
{
      __asm
      {
                nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        mov esi, orinUpdateTime
                        add esi, 5
                        jmp esi
      }
}

LARGE_INTEGER __declspec(naked) __stdcall JmpOriginal_KeQueryPerformanceCounter(OUT PLARGE_INTEGERPerformanceFrequency)
{
      __asm
      {
                nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        mov eax, KeQueryPerformanceCounter
                        add eax, 5
                        jmp eax
      }
}
LARGE_INTEGER __stdcall Fake_KeQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency)
{
      LARGE_INTEGER liResult;
      LARGE_INTEGER liCurrent;

      liCurrent = JmpOriginal_KeQueryPerformanceCounter(PerformanceFrequency);//10s

      // 上次返回时间 + Round((当前返回时间 - 上次正常时间) * Power(2,倍数));
      liResult.QuadPart = g_liPreReturnCounter.QuadPart + (liCurrent.QuadPart - g_liPreOriginalCounter.QuadPart) * g_dwSpeed_X / g_dwSpeedBase;//10

      // 保存当前的原始数值
      g_liPreOriginalCounter.QuadPart = liCurrent.QuadPart;
      // 保持返回值
      g_liPreReturnCounter.QuadPart = liResult.QuadPart;

      return liResult;
}

VOID __declspec(naked) __cdecl Fake_KeUpdateSystemTime()
{
      // 跳转到新函数去执行
      __asm
      {
                // 参数是EAX和EDX传参的, 分别是 OUT PLARGE_INTEGER CurrentTime 的高位和低位
                // 进行变速处理 (EAX * 当前速度值 / 速度基数)
                mul g_dwSpeed_X
                        div g_dwSpeedBase
                        jmp JmpOriginal_KeUpdateSystemTime
      }
}


NTSTATUS Unload(PDRIVER_OBJECT driver)
{
      return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
      driver->DriverUnload = Unload;
      UNICODE_STRING hookname = RTL_CONSTANT_STRING(L"KeUpdateSystemTime");
      orinUpdateTime = MmGetSystemRoutineAddress(&hookname);
      UNICODE_STRING hookname2 = RTL_CONSTANT_STRING(L"KeQueryPerformanceCounter");
      orinQuery = MmGetSystemRoutineAddress(&hookname2);
      DbgPrint("%p", orinUpdateTime, orinQuery);

      g_liPreOriginalCounter.QuadPart = 0;
      g_liPreReturnCounter.QuadPart = 0;
      g_liPreOriginalCounter = KeQueryPerformanceCounter(NULL);//驱动入口处先查询一次   0S
      g_liPreReturnCounter.QuadPart = g_liPreOriginalCounter.QuadPart;


      BYTE nJmpCode1 = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
      BYTE nJmpCode2 = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
      *(DWORD*)(nJmpCode1 + 1) = (DWORD)Fake_KeUpdateSystemTime - ((DWORD)orinUpdateTime + 5);//nJmpCode1   jmp   xxxx
      *(DWORD*)(nJmpCode2 + 1) = (DWORD)Fake_KeQueryPerformanceCounter - ((DWORD)orinQuery + 5);
      orinUpdateTimeCode = ExAllocatePool(NonPagedPool, 20);//事实上这里 还要对内存清理处理
      orinQueryCode= ExAllocatePool(NonPagedPool, 20);
      WPOFF();
      KIRQL Irql = KeRaiseIrqlToDpcLevel();
      RtlCopyMemory(orinUpdateTimeCode, orinUpdateTime, 5);
      RtlCopyMemory(JmpOriginal_KeUpdateSystemTime, orinUpdateTime, 5);
      RtlCopyMemory((BYTE*)orinUpdateTime, nJmpCode1, 5);
      ///////////////
      RtlCopyMemory(orinQueryCode, orinQuery, 5);
      RtlCopyMemory(JmpOriginal_KeQueryPerformanceCounter, orinQuery, 5);
      RtlCopyMemory((BYTE*)orinQuery, nJmpCode2, 5);

      KeLowerIrql(Irql);
      WPON();
      
      return STATUS_SUCCESS;
}


代码仅为演示,没处理卸载函数!请自行处理!

a2205368958 发表于 2018-8-27 10:05:01

日常自顶
页: [1]
查看完整版本: windows驱动开发从零基础到入坑!