Directory
SSDT Hook is used to load the driver and Hook NtTerminateProcess function successfully: when the specified process is protected and the process is ended using the "Task Manager", the "Access Denied" window is displayed, note: Our goal has been achieved: SSDT Introduction The full name of SSDT is System Services Descriptor Table, System Service Descriptor Table.
This table associates Ring3's Win32 API with Ring0's kernel API.
SSDT not only contains a large address index table, but also contains some useful information, such as the base address of the address index and the number of service functions.
By modifying the function address of this table, you can Hook common Windows functions and APIs to filter and monitor system actions that you are concerned about.
Some HIPS, anti-virus software, system monitoring, and registry monitoring software often use this interface to implement their own monitoring modules.
The SSDT structure SSDT is the system service Descriptor Table. Its structure is as follows (see Chapter 2 of Undocument Windows 2000 Secretes ):
typedef PULONG ServiceCounterTableBase; ULONG NumberOfService; ULONG ParamTableBase; } KSYSTEM_SERVICE_TABLE, * KSYSTEM_SERVICE_TABLE win32k; *PKSERVICE_TABLE_DESCRIPTOR;
There are two System Service Identifier tables in the kernel, one is keservicedescriptortable(exported by ntoskrnl.exe) and the other is KeServieDescriptorTableShadow (not exported ). The difference between the two is that KeServiceDescriptorTable only has one ntoskrnel, and KeServieDescriptorTableShadow contains ntoskrnel and win32k. Generally, the service address of Native API is assigned by KeServiceDescriptorTable, and the kernel API call service address of gdi. dll/user. dll is assigned by KeServieDescriptorTableShadow. It is also worth noting that win32k. sys is loaded only in the GUI thread. In general, it is not loaded. Therefore, if you want to Hook the KeServieDescriptorTableShadow, it is generally triggered by a GUI program through IoControlCode (I do not want to understand this at the beginning, after the blue screen crashes for N times, I cannot understand what is going on ). The ssdt hook principle has many types of kernel hooks. The following illustration shows that SSDT Hook is only one of the HOOK technologies. This article describes how to use SSDT Hook. The ssdt hook schematic diagram uses the Kernel Detective tool. We can find that the current address of NtTerminateProcess changes before and after the SSDT Hook, where, the current address after the change: 0xF885A110 is the address of the custom Hook function (HookNtTerminateProcess. In this way, every time NtTerminateProcess is executed, the function directed to by the "current address" will be executed. This is the principle of SSDT Hook. In addition, reading the "fallen genius" of snow writes well. I directly reference the principle of SSDT HOOK, which is actually very simple. Let's take a look at what kind of KeServiceDescriptorTable is.
lkd>
As shown above, 80587691 805716ef 8057ab71 80581b5c is the address of the system service function. For example, when we call OpenProcess in ring3, the ID of the sysenter is 0x7A (XP SP2), and then the system checks the KeServiceDescriptorTable. This is probably the case of KeServiceDescriptorTable. ntoskrnel. serviceTableBase (804e3d20) + 0x7A * 4 = 804E3F08, then 804E3F08-> 8057559e. This is where the OpenProcess system service function is located. Let's track it again:
lkd>!!ObReferenceObjectByPointer+!InterlockedPushEntrySList+
8057559e is the starting address of the NtOpenProcess function.
Well, what if we change 8057559e to the address of our function? For example, if MyNtOpenProcess is used, the system will directly call MyNtOpenProcess instead of the original NtOpenProcess. This is the principle of ssdt hook. In addition, for details about how to transfer the Ring3 layer to the Ring0 layer, refer to my post to help you better understand the SSDT Hook Technology: before Ring3 is transferred to the Ring0 tracking Hook, we prepare to modify the SSDT table. First, this table must be writable, but it will be read-only in systems after xp, three methods to modify the Memory protection mechanism (1) modify the registry recovery page protection: HKLM \ SYSTEM \ CurrentControlset \ Control \ Session Manger \ Memory Management \ EnforceWriteProtection = 0 remove page protection: HKLM \ SYSTEM \ CurrentControlset \ Control \ Session Manger \ Memory Management \ DisablePagingExecutive = 1 (2) Change the 1st-bit Windows Memory Allocation for the CR0 register, which is paging Management. There is a CR0 register, such:
The 1st bits are called protection attribute spaces, which control the read or write attributes of pages. If it is 1, it can be read, written, or executed. If it is 0, it can only be read/executed. By default, SSDT and IDT page attributes are read-only and executable, but cannot be written. The Code is as follows:
(3) Use Memory Descriptor List (MDL)
For more information, see google.
How can I obtain the address of the function in SSDT?
Two macros are used here:
① Obtain the index number of the specified service: SYSCALL_INDEX
② Obtain the current address of the specified service: SYSCALL_FUNCTION
The two macros are defined as follows:
// Obtain the index number of the service corresponding to ZwServiceFunction in SSDT Based on ZwServiceFunction # define SYSCALL_INDEX (ServiceFunction) (* (PULONG) (PUCHAR) ServiceFunction + 1 )) // obtain the index number of the Service in SSDT Based on ZwServiceFunction, and then obtain the address of ntServiceFunction # define SYSCALL_FUNCTION (ServiceFunction) KeServiceDescriptorTable-> ntoskrnl. serviceTableBase [SYSCALL_INDEX (ServiceFunction)]
SSDT Hook Process
In the driver's entry function (DriverEntry), The SSDT table before SSDT Hook is backed up (saved in an array). During the backup, an index number corresponds to the current address, as shown in.
In this way, when the Hook is removed, you can obtain the current address of the service name before the Hook from the Global Array Based on the index number, so that the original address can be written back, this step is important.
When the user chooses to protect a process, an IO_INSERT_PROTECT_PROCESS control code is sent to the driver through DeviceIoControl. At this time, the driver generates an IRP_MJ_DEVICE_CONTROL, which is already in the driver
IRP_MJ_DEVICE_CONTROL specifies a dispatch function: SSDTHook_DispatchRoutine_CONTROL. In this dispatch letter: we obtain the control code (whether to protect the process or cancel the protection process). If we want to protect a process, the pid of the process to be protected is passed to the driver through the 3rd parameters of DeviceIoControl. Then, read the pid from the buffer in the dispatch function SSDTHook_DispatchRoutine_CONTROL. To protect the process, add the pid of the process to an array, if you want to "unprotect processes", remove the process PID to be unprotected from the array.
After Hook NtTermianteProcess function, we will execute our custom function: HookNtTerminateProcess. In the HookNtTerminateProcess function, we will determine whether the current process is in the process array to be protected, if the pid exists in the array, an exception with insufficient permissions is returned. If the pid does not exist in the process protection array, the NtTerminateProcess in the original SSDT is called directly to end the process.
With the above theoretical basis, SSDT Hook implements process protection. Next we can talk about the specific implementation of SSDT Hook to implement process protection. To implement process protection, you can Hook NtTermianteProcess or NtOpenProcess. Here, I am Hook NtTermianteProcess. As mentioned in the SSDT Hook principles section, the essence of SSDT Hook principles is: to customize a function (HookNtTerminateProcess) and direct the current address of the System Service NtTermianteProcess to the address of our custom function. This step is executed in the driver entry function. When the driver is loaded, write the address of the custom function to the current address of the NtTermianteProcess service in the SSDT table:
= KdPrint((,( SYSCALL_FUNCTION(oldService) = newService; DisableWrite();
Note that the page protection attribute of the memory needs to be removed before the Hook, and the page protection attribute of the memory needs to be replied after the Hook. The code for the HookNtTerminateProcess function is as follows:
rtStatus = ObReferenceObjectByHandle(ProcessHandle, FILE_READ_DATA, NULL, KernelMode, (PVOID*)& (! pOldNtTerminateProcess = uPID == _strupr((TCHAR *)PsGetProcessImageFileName(pEProcess)); RtlInitAnsiString(& (ValidateProcessNeedProtect(uPID) != - (uPID != rtStatus =
For details about the communication between Ring3 and Ring0, see Chapter 7th of Zhang Fan's Windows driver development technology: for details about how to install, start, stop, and uninstall the dispatch function, refer to my other blog post: NT driver loader (with source code) reference SSDT Hook-Vs ring0 inline hook: http://bbs.pediy.com/showthread.php? T = 40832 process hiding and process protection (SSDT Hook implementation): hidden
SSDT Hook implements kernel-level process protectionCopyright