- UID
- 63440
- 积分
- 477
- 回帖
- 0
- 贡献
-
- 金钱
-
- 注册时间
- 2018-8-25
- 最后登录
- 1970-1-1
- 在线时间
- 小时
TA的每日心情 | 开心 2023-10-16 20:08 |
---|
签到天数: 8 天 连续签到: 1 天 [LV.3]灯篭鬼
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?创建账号
×
本帖最后由 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
{
mov eax, cr0
or eax, 0x10000
mov cr0, 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_INTEGER PerformanceFrequency)
{
__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[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
BYTE nJmpCode2[5] = { 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;
}
代码仅为演示,没处理卸载函数!请自行处理!
|
|