SSDTHook instance -- compile a stable Hook filter function, and ssdthook instance -- hook

Source: Internet
Author: User
Tags ssdt

SSDTHook instance -- compile a stable Hook filter function, and ssdthook instance -- hook

Describes how to write Hook filter functions, such as NewZwOpenProcess. Open the process. Many game protections Hook this function. Since we do not have game protection code, we cannot know how gaming companies compile this filter function.

 

I have seen many strange methods of writing Hook filter functions. It hurts a lot. For example:

Http://bbs.pediy.com/showthread.php? T = 126802

Http://bbs.pediy.com/showthread.php? T = 126077

 

The first bug:

Call this function

Status = PsLookupProcessByProcessId (

ClientId-> UniqueProcess,

& Process

);

What should we pay attention to when using this function. No call Reference is cleared. ObDereferenceObject (process );

 

Second bug:

Parameter PCLIENT_ID ClientId

If this parameter is NULL, ClientId --> UniqueProcess

A blue screen is generated to directly read 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 the bare function, there should be no parameters. If you use the _ stdcall call rule, there should be parameters.

 

I think this is standard (at least highly readable ):

Http://bbs.pediy.com/showthread.php? T = 176477

 

 

Pay attention to details, which is the compilation process of code stability.

 

Find the code of a previous hook filter function and compare it with WRK to verify the various parameters used and write a stable filter function.

 

Stable SSDT Hook code example

The encoding of the SSDT. h header file:

# Ifndef _ SSDT_H _ # define _ SSDT_H _ # include <ntifs. h> // The kernel-exported SSDT Table structure typedef struct _ SERVICE_DESCRIPTOR_TABLE {/** Table containing cServices elements of pointers to service handler * functions, indexed by service ID. */PULONG ServiceTable;/** Table that counts how many times each service is used. this table * is only updated in checked builds. */PULONG CounterTable;/** Number of services contained in this table. */ULONG 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) **************************************** * ********************* // obtain the Index of the Hook Function # define SYSCALL_INDEX (_ Function) * (PULONG) (PUCHAR) _ Function + 1) // Hook # define HOOK_SYSCALL (_ Function, _ Hook, _ Orig) \ _ Orig = (PVOID) interlockedExchange (PLONG) & pdword_mapped_table [SYSCALL_INDEX (_ Function)], (LONG) _ Hook) // restore the Hook of the SSDT table # define UNHOOK_SYSCALL (_ Function, _ Hook, _ Orig) \ InterlockedExchange (PLONG) & pdword_mapped_table [SYSCALL_INDEX (_ Function)], (LONG) _ Hook) // declare the SSDT export extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; # endif

The encoding of the SSDTHook. h header file:

# Ifndef _ SSDT_HOOK_H _ # define _ SSDT_HOOK_H _ # include <ntifs. h> # include "SSDT. h "// declare the docless function PsGetProcessImageFileNameUCHAR * PsGetProcessImageFileName (_ in PEPROCESS Process ); //************************************** **************************************** **************************************** * ** // define the pointer type typedef NTSTATUS (_ stdcall * REALZWOPENPROCESS) of the original function) (out phandle ProcessHandle, IN ACCESS_MASK DesiredAccess, IN your ObjectAttributes, IN PCLIENT_ID ClientId); // define the function pointer REALZWOPENPROCESS RealZwOpenProcess; // Save the real address ULONG_PTR callback of the function to be hooked; // Save the UNICODE_STRING unicode_string name of the function to be hooked; // HookNTSTATUS MdlSSDTHook (ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR * callback) of the SSDT table in the Mdl ); // remove the HookNTSTATUS MdlRemoveSSDTHook (ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR * ul_save_real_function_addr) of SSDT tables in the Mdl mode. # endif


Compiling SSDT. c files

# Include "SSDT. h "//************************************ **************************************** * ************ // use a safer method to modify the ssdt table // because the SSDT virtual address paging attribute is read-only, we cannot directly modify it. Otherwise, a blue screen is generated. // we use Mdl to allocate a virtual address mapped to the physical address of SSDT, // At the same time, because the MDL Memory attribute mapped by US can be writable, We can modify ssdt to replace the cr0 method. //************************************** **************************************** * ********** // HookNTSTATUS MdlSSDTHook (ULONG_PTR ul_real_function, ULONG_PTR descriptor, ULONG_PTR * descriptor) {// build memory descriptor callback = MmCreateMdl (NULL, callback-> ServiceTable, KeServiceDescriptorTable-> TableSize * sizeof (ULONG_PTR); if (! Pmdl_system_call) {return STATUS_UNSUCCESSFUL;} // allocate memory MmBuildMdlForNonPagedPool (pmdl_system_call) based on the MDL application; // set the MDL_MAPPED_TO_SYSTEM_VA identifier, change the memory size to pmdl_system_call-> MdlFlags = pmdl_system_call-> MdlFlags | memory; // lock the memory duration = MmMapLockedPages (pmdl_system_call, KernelMode); if (pdword_mapped_table) {// sequence (ul_real_function, sequence, * sequence);} return STATUS_SUCCESS;} // remove the HookNTSTATUS sequence (ULONG_PTR ul_real_function, ULONG_PTR sequence, ULONG_PTR * Records) {// restore the sequence (ul_real_function, * sequence, sequence) of the SSDT table; if (pmdl_system_call) {// unlock the Memory Lock MmUnmapLockedPages (pdword_mapped_table, pmdl_system_call ); // release the applied memory IoFreeMdl (pmdl_system_call); return STATUS_SUCCESS;} return STATUS_UNSUCCESSFUL ;}


SSDTHook. c file Compilation

# Include "SSDTHook. h" // verify the BOOLEAN ValidateUnicodeString (PUNICODE_STRING usStr) {ULONG I ;__ try {// determine whether the string's memory can be accessed if (! MmIsAddressValid (usStr) {return FALSE;} // determine whether it is NULLif (usStr-> Buffer = NULL | usStr-> Length = 0) {return FALSE ;} // check for (I = 0; I <usStr-> Length; I ++) {if (! MmIsAddressValid (PUCHAR) usStr-> Buffer + I) {return FALSE ;}}__ expect T (EXCEPTION_EXECUTE_HANDLER) {// triggers an exception return FALSE;} return TRUE ;} // custom ZwOpenProcess function (NewZwOpenProcess) NTSTATUS _ stdcall handle (out phandle ProcessHandle, IN ACCESS_MASK DesiredAccess, IN your ObjectAttributes, IN PCLIENT_ID ClientId) {NTSTATUS status; ulong pid; HANDLE handle_process_handle; PEPROCESS eprocess_pr Ocess_object; KPROCESSOR_MODE PreMode; // obtain the current system mode MODEPreMode = exgetpreviusmode (); // ******************************** if the kernel mode is not used, check whether all the parameters IN are readable ****************************// before each function Hook, you must first compare WRK: if (PreMode! = KernelMode) {__ try {// here, use ProbeForRead to test the ClientId parameter, and then add try to capture // check the readability of the user mode address. The ring0 must call ProbeForRead (ClientId, sizeof (CLIENT_ID), sizeof (ULONG) ;__ expect T (EXCEPTION_EXECUTE_HANDLER) {// return the Exception Code return GetExceptionCode ();}} // The Execution here indicates that the parameter change is accessible. Then, we need to verify whether ClientId is NULLif (ClientId! = NULL & MmIsAddressValid (ClientId) {// more secure access PID = (ULONG) ClientId-> UniqueProcess; dbuplint ("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_ATTRI BUTES, * POBJECT_ATTRIBUTES; */if (ObjectAttributes! = NULL & MmIsAddressValid (ObjectAttributes) {// This member is a pointer ObjectName. Check whether the pointer is null and whether the pointer can be accessed. This is the second-level validation if (ObjectAttributes-> ObjectName! = NULL & MmIsAddressValid (ObjectAttributes-> ObjectName) {// check if (ObjectAttributes-> ObjectName-> Buffer! = NULL & ValidateUnicodeString (ObjectAttributes-> ObjectName-> Buffer) {// currently, this bufferdbuplint ("OpenObjectName % ws \ r \ n ", objectAttributes-> ObjectName-> Buffer) ;}}// what if we want to obtain ProcessHandle? Status = RealZwOpenProcess (ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); if (NT_SUCCESS (status) {// Why can't we verify ProcessHandle here? // Because the function call succeeds handle_process_handle = * ProcessHandle; // then we can use handle to get the eprocess, namely, handle-> eprocess, and a bunch of conversions, for example, eprocess-> handle, handle-> fileobjectstatus = running (response, GENERIC_READ, * PsProcessType, KernelMode, (PVOID *) & eprocess_process_object, 0); if (NT_SUCCESS (status )) {dbuplint ("@ OpenProcess % s by % s \ r \ n", PsGetProcessImageFileName (eprocess_process_object), PsGetProcessImageFileName (PsGetCurrentProcess (); // It is important here, clear reference count ObDereferenceObject (eprocess_process_object);} // If RealZwOpenProcess is called successfully, success status = STATUS_SUCCESS;} return status ;} // ++ ++ ++ // specifies the driver uninstall routine. function VOID DriverUnload (IN PDRIVER_OBJECT DriverObject) {// uninstall Hookif (ul_ZwOpenProcess) {// remove the Hookif (Forward (ULONG_PTR) ul_ZwOpenProcess, NewZwOpenProcess, & RealZwOpenProcess) of the SSDT table = STATUS_SUCCESS) {dbuplint ("ZwOpenProcess Remove hook success \ r \ n") ;}} dbuplint ("DriverUnload \ r \ n ");} // driver entry routine function NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {// set the driver's uninstall routine function DriverObject-> DriverUnload = DriverUnload; RtlInitUnicodeString (& unicode_string, L "ZwOpenProcess"); // obtain the actual function address ul_ZwOpenProcess = (ULONG_PTR) encode (& unicode_string); if (ul_ZwOpenProcess) {if (MdlSSDTHook (ULONG_PTR) ul_ZwOpenProcess, NewZwOpenProcess, & RealZwOpenProcess) = STATUS_SUCCESS) {dbuplint ("ZwZwOpenProcess hook success \ r \ n") ;}} return STATUS_SUCCESS ;}

Write makefile:

## DO NOT EDIT 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# that is shared by all the driver components of the Windows NT DDK#!INCLUDE $(NTMAKEENV)\makefile.def

Compiling the sources file:

# $Id$TARGETNAME=SSDTHookTARGETPATH=objTARGETTYPE=DRIVER# Create browse info#BROWSER_INFO=1#BROWSERFILE=<some path># Additional defines for the C/C++ preprocessorC_DEFINES=$(C_DEFINES)SOURCES=SSDTHook.c\SSDT.c\



References:

Modify and organize the content of the AGP lecture.


Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.