Explains how to write Hook filtering functions, such as newzwopenprocess. Open the process. A lot of game protection will Hook up this function . 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 function notation. The egg is very painful to see. For 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:
Parameter pclient_id ClientId
If this parameter is null, then clientid-->uniqueprocess
A blue screen is generated and read directly to a NULL variable.
http://bbs.pediy.com/showthread.php?t=105418
http://bbs.pediy.com/showthread.php?t=82548
http://bbs.pediy.com/showthread.php?t=82043
Note : If you use naked (bare function) This form, there should be no parameters, if you use __stdcall This call rule, you should have parameters.
I think it's a standard (at least readable):
http://bbs.pediy.com/showthread.php?t=176477
To focus on detail, this is the process of writing code stability.
Just look for a previous hook . Filter function code, control WRK, the use of various parameters to perform the validation , write a stable filter function .
Example of a stable SSDT Hook code
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 modify SSDT tables//Because SSDT's virtual address paging property is read-only, we cannot modify it directly, otherwise it will produce a blue screen//We use the MDL to allocate a virtual address mapping to the physical address where SSDT resides,// Also, because our mapped MDL memory properties can be writable, SSDT can be modified to replace 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 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) According to MDL request,//Set Mdl_mapped_to_system_va identity to make this memory 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{// Determines whether the memory of the string can be accessed if (! Mmisaddressvalid (USSTR)) {return FALSE;} Determine 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;} Custom 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 ();//******************************* if non-kernel mode, It's time to start checking that the in parameters are not readable ****************************//each hook to a function, you must first control wrk:if (premode! = KernelMode) {__try{// Here, test the parameter ClientID with Probeforread, and then add try capture//check that 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 ();}} Execute here to explain that the parameters are accessible, then we also have to verify whether ClientId is Nullif (ClientId! = NULL && mmisaddressvalid (ClientId)) {//More secure access 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. Checks if the pointer is empty, and then whether it can be accessed. 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)) {//Now it is safe not to have a blue screen access to this bufferdbgprint ("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 can also get eprocess through handle, that is, handle->eprocess, and a bunch of conversions, such as 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 ()));//It is important here to eliminate the reference count Obdereferenceobject (Eprocess_process_object);} As long as the realzwopenprocess 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
Resources:
Modification and collation of AGP lecture materials.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Ssdthook example--writing a stable hook filter function