- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
/*
内核挂钩NtUserSetTimer实现游戏加速。
虽然现在游戏加速没啥子意思了,放点代码出来给大家学习一下。
这个例子可以实现扫雷加速。
这是从以前写的一个工程里面分割出来的,主要代码都在了,但是不能直接编译。
*/
#include <ntddk.h>
#include "ldasm.h"
NTKERNELAPI
NTSTATUS
KeAddSystemServiceTable(
IN PULONG_PTR Base,
IN PULONG Count OPTIONAL,
IN ULONG Limit,
IN PUCHAR Number,
IN ULONG Index
);
NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(
PEPROCESS Process
);
typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
PULONG_PTR Base;
PULONG Count;
ULONG Limit;
PUCHAR Number;
}
KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
typedef ULONG (__stdcall *pfnNtUserSetTimer)(
ULONG pwnd,
ULONG nIDEvent,
int dwElapse,
PVOID pTimerFunc
);
PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow = NULL;
pfnNtUserSetTimer pfnProxyNtUserSetTimer = NULL;
pfnNtUserSetTimer NtUserSetTimer = NULL;
ULONG OldCr0 = NULL;
ULONG ulLen = NULL;
///////////////////////////////////////////////////////////////////
/*
lkd> u KeAddSystemServiceTable L 10
nt!KeAddSystemServiceTable:
805a008a 8bff mov edi,edi
805a008c 55 push ebp
805a008d 8bec mov ebp,esp
805a008f 837d1803 cmp dword ptr [ebp+18h],3
805a0093 7760 ja nt!KeAddSystemServiceTable+0x6b (805a00f5)
805a0095 8b4518 mov eax,dword ptr [ebp+18h]
805a0098 c1e004 shl eax,4
805a009b 83b8e0b6558000 cmp dword ptr nt!KeServiceDescriptorTable (8055b6e0)[eax],0
805a00a2 7551 jne nt!KeAddSystemServiceTable+0x6b (805a00f5)
805a00a4 8d88a0b65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055b6a0)[eax]
所以特征码是0x888D
*/
VOID GetSSDTShadowBase()
{
__try
{
UCHAR *cPtr;
UCHAR *pOpcode;
ULONG Length;
for (cPtr = (PUCHAR)KeAddSystemServiceTable;
cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;
cPtr += Length)
{
Length = SizeOfCode(cPtr, &pOpcode);
if (!Length) break;
if ( *(PUSHORT)cPtr == 0x888D )
{
KeServiceDescriptorTableShadow = (PKSERVICE_TABLE_DESCRIPTOR)(*(ULONG *)((ULONG)pOpcode + 2));
break;
}
}
} __except(EXCEPTION_EXECUTE_HANDLER)
{
dprintf("GetSSDTShadowBase : Raised exception 0x%X.\n", GetExceptionCode());
}
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
//必须在GDI线程中进行挂钩
PVOID pfnProxy = NULL;
PTIMER pMov = NULL;
GetSSDTShadowBase(); //Shadow 表没有被导出,所以搜索一下
dprintf("ShadowBase : 0x%08X\n", KeServiceDescriptorTableShadow);
dprintf("NtUserSetTimer : 0x%08X\n", KeServiceDescriptorTableShadow[1].Base[0x21E]); //0x21E为NtUserSetTimer在SSDTShadow表中的Index
NtUserSetTimer = (PVOID)KeServiceDescriptorTableShadow[1].Base[0x21E];
pfnProxy = NULL;
HookSystemRoutine(
NtUserSetTimer,
&pfnProxy,
Hook_NtUserSetTimer,
&ulLen
);
pfnProxyNtUserSetTimer = (pfnNtUserSetTimer)pfnProxy;
//////////////////////////////////////////////////////////////////////////
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
if (NtUserSetTimer)
{
UnhookInlineHook(
NtUserSetTimer,
ulLen,
pfnProxyNtUserSetTimer);
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
dprintf("[EnumTimer] IRP_MJ_CLOSE\n");
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID WPOff() //关闭写保护
{
ULONG uAttr;
_asm
{
cli;
push eax;
mov eax , cr0;
mov uAttr , eax;
and eax , 0FFFEFFFFh;
mov cr0 , eax;
pop eax;
}
OldCr0 = uAttr;
}
VOID WPOn() //开写保护
{
_asm
{
push eax;
mov eax , OldCr0;
mov cr0 , eax;
pop eax;
sti;
}
}
BOOLEAN HookSystemRoutine(PVOID pfnOrig,
PVOID *pfnProxy,
PVOID pfnHook,
ULONG *Length
)
{
KIRQL oldIrql;
UCHAR HookCode[] = {0x68, 0x00, 0x00, 0x00, 0x00, 0xC3}; //push + Ret
UCHAR JumpCode[] = {0xEA, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00};
ULONG BackupLength = 0;
PUCHAR pOpCode;
PVOID pJump;
*(ULONG *)( (ULONG)HookCode + 1) = (ULONG)pfnHook;
while(BackupLength<6)
{
BackupLength+=SizeOfCode( (PVOID)((ULONG)pfnOrig + BackupLength ),&pOpCode);
}
*(ULONG *)((ULONG)JumpCode + 1) = ((ULONG)pfnOrig + BackupLength);//Jump to Orig
pJump = ExAllocatePool(NonPagedPool,BackupLength + 8);
if (!pJump)
return FALSE;
*Length = BackupLength;
RtlCopyMemory( pJump , pfnOrig , BackupLength);
RtlCopyMemory( (PVOID)( (ULONG)pJump + BackupLength), JumpCode, 7 );
*pfnProxy = pJump;
oldIrql = KeRaiseIrqlToDpcLevel();
WPOff();
__try
{
RtlCopyMemory( (PCHAR)pfnOrig , HookCode , 6); //写入Hook Code
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dprintf("HookSystemRoutine: Raised exception 0x%X.\n",GetExceptionCode());
}
WPOn();
KeLowerIrql(oldIrql);
return TRUE;
}
VOID UnhookInlineHook(PVOID pfnOrig,
ULONG uPatchLen,
PVOID pfnProxy
)
{
KIRQL oldIrql;
LARGE_INTEGER Delay;
Delay.QuadPart = -5000000;
KeDelayExecutionThread(KernelMode, TRUE, &Delay);
oldIrql = KeRaiseIrqlToDpcLevel(); //Raise IRQL
WPOff();
__try
{
RtlCopyMemory( (PUCHAR)pfnOrig , (PUCHAR)pfnProxy , uPatchLen);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dprintf("HookSystemRoutine: Raised exception 0x%X.\n",GetExceptionCode());
}
WPOn();
KeLowerIrql(oldIrql);
ExFreePool(pfnProxy);
}
ULONG Hook_NtUserSetTimer(
ULONG pwnd,
ULONG nIDEvent,
int dwElapse,
PVOID pTimerFunc
)
{
char *pName = PsGetProcessImageFileName( IoGetCurrentProcess() ); //当前进程的进程名
int n = 0;
if( strcmp( pName,"winmine.exe") == 0 ) //判断是不是扫雷
{
dprintf("[NtUserSetTimer] %s . dwElapse : %d . \n", pName,
dwElapse
);
n = dwElapse;
n = n / 4; //减少四倍。
return pfnProxyNtUserSetTimer(pwnd,nIDEvent,n,pTimerFunc);
}
return pfnProxyNtUserSetTimer(pwnd,nIDEvent,dwElapse,pTimerFunc);
} |
|