Code:
#include <ntddk.h>
typedef unsigned long DWORD, *PDWORD;
typedef unsigned char BYTE, *PBYTE, *PCHAR;
typedef unsigned long ULONG_PTR;
typedef ULONG_PTR DWORD_PTR;
NTSTATUS( *Real_ZwClose )( HANDLE Handle );
#define _Lookup( _Call ) \
KeServiceDescriptorTable.ServiceTable[* ( unsigned int * ) \
( ( unsigned char * ) _Call + 1 )]
typedef struct _SSDT
{
PDWORD ServiceTable;
PDWORD CounterTableBase;
DWORD ServiceLimit;
PCHAR ArgumentTable;
} SSDT;
__declspec(dllimport) SSDT KeServiceDescriptorTable;
DWORD_PTR *SSDT_Hook( DWORD_PTR *_OrigCall, DWORD_PTR *_Hook )
{
unsigned long *returnVal = _Lookup( _OrigCall );
_Lookup( _OrigCall ) = _Hook;
return( returnVal );
}
void DriverUnload( PDRIVER_OBJECT DriverObject)
{
SSDT_Hook( ( DWORD_PTR * ) ZwClose, ( DWORD_PTR * ) Real_ZwClose );
}
NTSTATUS my_ZwClose( HANDLE Handle )
{
DbgPrint( "ZwClose called!" );
Real_ZwClose( Handle );
return( STATUS_SUCCESS );
}
NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
DriverObject->DriverUnload = DriverUnload;
Real_ZwClose = SSDT_Hook( ( DWORD_PTR * ) ZwClose, ( DWORD_PTR * ) my_ZwClose );
return( STATUS_SUCCESS );
}
Requires WinDDK to compile/link; note, you should remove your hook in the "Unload" event, otherwise, a BSOD will most likely occur dependent on what function you're hooking, how often it's called, etc.
EDIT: The above example now has a safe-unload mechanism.
From here, you can write an anti-cheat by hooking functions known to be used for cheats; for example, hook ZwOpenProcess, and check if the PID parameter matches the process ID of the Gunz process; if so, return an error message, and do not hand off the request to the actual ZwOpenProcess call.
Otherwise, this is just a poc demonstrating how easy it is to hook functions in the SSDT
Downloads:
WinDDK - http://www.microsoft.com/whdc/devtools/WDK/default.mspx
InstDvr (Allows quick loading/unloading of kernel driver) - http://nsis.sourceforge.net/InstDrv_plug-in
Last edited: