Explain how to write the Hook filter function, for example newzwopenprocess. Open the process.
This function will be Hookup with a lot of game protection.
Because we don't have the game-protected code, we don't know how the game company is writing this filter function.
I see a lot of strange-looking Hook filter functions. The egg is very painful to see.
Example:
http://bbs.pediy.com/showthread.php?t=126802
Http://bbs.pediy.com/showthread.php?
t=126077
First bug:
Call this function
status = Pslookupprocessbyprocessid (
Clientid->uniqueprocess,
&process
);
This function is where we should pay attention. Did not see the purge call argument obdereferenceobject (process);
A second bug:
Number of references pclient_id ClientId
Suppose this parameter is null. So clientid-->uniqueprocess
A blue screen is generated and read directly to a NULL variable.
Http://bbs.pediy.com/showthread.php?
t=105418
t=82548 ">http://bbs.pediy.com/showthread.php?t=82548
http://bbs.pediy.com/showthread.php?t=82043
Note : Suppose you use naked (bare function) in this form, there should be no parameters, assuming you use __stdcall to invoke the rules. You should have a number of references.
I think this is standard (at least very readable):
t=176477 ">http://bbs.pediy.com/showthread.php?
t=176477
To focus on detail, this is the process of writing code stability.
Find the code of the previous Hook filter function. Comparing WRK, the use of the various parameters of the validation, write a stable filter function .
Example of a stable SSDT Hook Code Demo
SSDT.h the encoding of the header file:
#ifndef _ssdt_h_#define _ssdt_h_#include <ntifs.h>//kernel derived SSDT table structure typedef struct _SERVICE_DESCRIPTOR_TABLE {/** Table containing cservices elements of pointers to service handler* functions, indexed by service Id.*/pulong Servicetab le;/** Table, counts how many times, each service is used. This table* was only updated in checked Builds.*/pulong countertable;/** number of services contained in this Table.*/ulon G tablesize;/** Table containing the number of bytes of parameters the handler* function Takes.*/puchar argumenttable;} service_descriptor_table, *pservice_descriptor_table;//global variable pmdl pmdl_system_call; PVOID *pdword_mapped_table;//******************** SSDT Hook Macro (fixed) ************************************************ Get Hook function Index#define syscall_index (_function) * (Pulong) ((Puchar) _function+1)//Implement SSDT table hook# Define Hook_syscall (_function, _hook, _orig) _orig = (PVOID) interlockedexchange ((Plong) &PDWORD_MAPPED_TABLE[SYSC All_index (_function)], (LONG) _hook)//restore SSDT table Hook#define unhook_syscall (_function, _hook, _orig) InterlockedExchange ((Plong) &pdword_ Mapped_table[syscall_index (_function)], (LONG) _hook)//declares the export of SSDT extern pservice_descriptor_table keservicedescriptortable; #endif
SSDTHook.h the encoding of the header file:
#ifndef _ssdt_hook_h_#define _ssdt_hook_h_#include <ntifs.h> #include "SSDT.h" // Declares a function that is not documented psgetprocessimagefilenameuchar* Psgetprocessimagefilename (__in peprocess Process); //************************************************************************************************************* Defines the pointer type of the original function typedef NTSTATUS (__stdcall *realzwopenprocess) (out Phandle processhandle,in access_mask Desiredaccess,in pobject_attributes objectattributes,in pclient_id ClientId);//define the function pointer realzwopenprocess realzwopenprocess;//Save the real address of the hook function ulong_ptr ul_zwopenprocess;//Save the name of the hook function unicode_string unicode_string;// MDL Way of SSDT table Hookntstatus Mdlssdthook (ulong_ptr ul_real_function, Ulong_ptr hook_function_addr, ULONG_PTR *ul_save_ REAL_FUNCTION_ADDR);//Hookntstatus Mdlremovessdthook (ulong_ptr ul_real_function, ulong_ptr Hook_) to remove the MDL form of SSDT table FUNCTION_ADDR, Ulong_ptr *ul_save_real_function_addr); #endif
Preparation of ssdt.c files
#include "SSDT.h"//******************************************************************************************// Use a more secure method to alter the SSDT table//Because the virtual address paging property of SSDT is read-only, we cannot change it directly, otherwise a blue screen is generated//we use MDL to allocate a virtual address mapping to the physical address where SSDT resides,// At the same time, because our mapped MDL memory properties can be writable, you can change SSDT, which replaces the CR0 method. Hookntstatus of the SSDT table for MDL mode Mdlssdthook (ulong_ptr ul_real_function, Ulong_ptr hook_function_addr, ulong_ptr *ul_save_real_function_addr) {// Build memory Descriptive Descriptor Mdlpmdl_system_call = MMCREATEMDL (NULL, Keservicedescriptortable->servicetable, Keservicedescriptortable->tablesize*sizeof (ULONG_PTR)); if (!pmdl_system_call) {return status_unsuccessful;} Allocate memory Mmbuildmdlfornonpagedpool (Pmdl_system_call) based on MDL request;//Set Mdl_mapped_to_system_va identity. Let this memory become writable Pmdl_system_call->mdlflags = Pmdl_system_call->mdlflags | mdl_mapped_to_system_va;//Lock Memory Pdword_mapped_table = Mmmaplockedpages (Pmdl_system_call, KernelMode); if (Pdword_ mapped_table) {Hookhook_syscall of the//SSDT table (ul_real_funCtion, HOOK_FUNCTION_ADDR, *ul_save_real_function_addr);} return status_success;} Remove the MDL form of SSDT table Hookntstatus Mdlremovessdthook (ulong_ptr ul_real_function, ulong_ptr hook_function_addr, ULONG_PTR * UL_SAVE_REAL_FUNCTION_ADDR) {//Recover SSDT table Hookunhook_syscall (ul_real_function, *ul_save_real_function_addr,hook_ FUNCTION_ADDR); if (Pmdl_system_call) {//Unlock memory lock Mmunmaplockedpages (pdword_mapped_table, Pmdl_system_call);// Release request Memory iofreemdl (Pmdl_system_call); return status_success;} return status_unsuccessful;}
Preparation of SSDTHOOK.C files
#include "SSDTHook.h"//Depth of String checksum Boolean validateunicodestring (punicode_string usstr) {ULONG i;__try{// Infer if the memory of the string is accessible if (! Mmisaddressvalid (USSTR)) {return FALSE;} Inferred if nullif (Usstr->buffer = = NULL | | usstr->length = = 0) {return FALSE;} Each byte is checked for (i = 0; i < usstr->length; i++) {if (! Mmisaddressvalid ((Puchar) Usstr->buffer + i) {return FALSE;}}} __except (Exception_execute_handler) {//trigger exception return FALSE; }return TRUE;} Self-defined zwopenprocess function (newzwopenprocess) NTSTATUS __stdcall newzwopenprocess (out Phandle processhandle,in ACCESS_ MASK desiredaccess,in pobject_attributes objectattributes,in pclient_id ClientId) {NTSTATUS status; ULONG PID; HANDLE Handle_process_handle; Peprocess Eprocess_process_object; Kprocessor_mode premode;//Gets the current system mode Modepremode = Exgetpreviousmode ();//******************************* assumes non-kernel mode, It's time to start checking if these parameters are readable ****************************//each hook a function before you have to compare wrk:if (premode! = KernelMode) {__try{// Here with Probeforread to test the number of ClientID, and then add try to capture//check the readability of the user mode address must be called in RING0 pRobeforread (ClientId, sizeof (client_id), sizeof (ULONG));} __except (Exception_execute_handler) {//Returns the exception code return GetExceptionCode ();}} Run here to show that the change is to be able to access, then we have to check whether ClientId is Nullif (ClientId! = NULL && mmisaddressvalid (ClientId)) {//safer access to PID = ( ULONG) Clientid->uniqueprocess;dbgprint ("OpenProcess%d by%s[0x%08x]\r\n", PID, Psgetprocessimagefilename ( Psgetcurrentprocess ()), psgetcurrentprocess ());} /*typedef struct _object_attributes {ULONG Length; HANDLE rootdirectory; Punicode_string ObjectName; Bufferulong Attributes; PVOID SecurityDescriptor; PVOID Securityqualityofservice;} Object_attributes, *pobject_attributes;*/if (objectattributes! = NULL && mmisaddressvalid (objectattributes)) {//This member is a pointer ObjectName. Check if the pointer is empty, and then you can access it. This is the second level of the checksum if (objectattributes->objectname! = NULL && mmisaddressvalid (objectattributes->objectname)) {/ /depth Check checks if (Objectattributes->objectname->buffer! = NULL && validateunicodestring (OBjectattributes->objectname->buffer) {//are now safe enough to visit this bufferdbgprint without a blue screen ("Openobjectname%ws\r\n", Objectattributes->objectname->buffer);}}} What if we're going to take processhandle? Status = Realzwopenprocess (ProcessHandle, desiredaccess, Objectattributes, ClientId); if (nt_success (status)) {// Why don't we use the processhandle here? Because the function call succeeded Handle_process_handle = *processhandle;//then we were able to get eprocess through handle. That is handle->eprocess. Another heap of conversions, for example eprocess->handle, Handle->fileobjectstatus = Obreferenceobjectbyhandle (Handle_process_handle, Generic_read,*psprocesstype, KernelMode, (pvoid*) &eprocess_process_object, 0); if (nt_success (status)) {Dbgprint ("@@ openprocess%s by%s\r\n", Psgetprocessimagefilename (Eprocess_process_object), Psgetprocessimagefilename (Psgetcurrentprocess ()));//Here is very important to eliminate the reference count Obdereferenceobject (Eprocess_process_object);} Just to realzwopenprocess the call succeeds, be sure to return to success STATUS = Status_success;} return status;} //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//driver offload routine function void Driverunload (in Pdriver_object driverobject) {//unload Hookif (ul_zwopenprocess) {// Remove Hookif from SSDT table (Mdlremovessdthook ((ULONG_PTR) ul_zwopenprocess, newzwopenprocess, &realzwopenprocess) = = STATUS_ SUCCESS) {dbgprint ("zwopenprocess Remove hook success\r\n");}} Dbgprint ("driverunload\r\n");} Driver entry routine function Ntstatus DriverEntry (in Pdriver_object driverobject,punicode_string registrypath) {// Set the driver's unload routine function driverobject->driverunload = driverunload; Rtlinitunicodestring (&unicode_string, L "zwopenprocess");//Get the real function address of the hook function ul_zwopenprocess = (ULONG_PTR) Mmgetsystemroutineaddress (&unicode_string); if (ul_zwopenprocess) {if (Mdlssdthook (ULONG_PTR) ul_ZwOpenProcess , newzwopenprocess, &realzwopenprocess) = = status_success) {dbgprint ("zwzwopenprocess hook success\r\n");}} return status_success;}
Makefile File writing:
# # does not EDIT the This FILE!!! Edit. \sources. If you want to add a new source# file to this component. This file merely indirects to the real make file#, which is a shared by all the driver components of the Windows NT ddk#! INCLUDE $ (ntmakeenv) \makefile.def
Sources file writing:
# $Id $targetname=ssdthooktargetpath=objtargettype=driver# Create Browse Info#browser_info=1#browserfile=<some path># Additional defines for the C + + preprocessorc_defines=$ (c_defines) sources=ssdthook.cssdt.c
References:
Modification and collation of AGP lecture materials.
Ssdthook Instance-writing a stable hook filter function