Reminder, I am not advising people to make viruses. This should not be done with ill intention, this post is to educate people about hooking and how they can use this to their own purpose of monitoring their PC or just using it to learn windows internal or just having fun. This thread and a few others really got me very interested in hooking in general and how it works. Credits go to malwaretech on their amazing shares and articles, I will be posting the same articles with a few other hooking methods and such. Enjoy! Well, this is a post to educate anyone who wants to learn more about hooking. This can be really helpful when you are making a virus or just to monitor your computer or gain control of some parts. This post will tell you how to detect these hooks and how to bypass it. Hopefully, I help as many people as possible. Remember, this post is a combination of other posts here and on the internet. While learning about hooking and some other things, I came across soo many articles about hooking and it was extremely well explained. So, I guess I will explain some of them here. Comment below what you think and so on. Didn’t really find an article explaining everything here, so wanted to share what I read and what I learned along the way of researching hookings and so on. Enjoy!
Hooking into APIs will allow you to basically control what happens when that function, which is hooked, returns. This has been done by Anti Cheats as some of them hook onto Create Thread and see any threads which are created outside the module, which they can choose to close the thread or suspend it. This also are done by Anti Viruses, to not allow programs to use some APIs which can be used to exploit windows and such. By hooking onto an API, it allows you to gain control of how a software may work. Things like hooking onto functions which terminates programs to not allow programs to just terminate a program easily ( Anti Viruses ). There are two types of API hooks, global and local. Local hooks only work on a specific program and Global hooks work for the whole system. Anti Viruses usually does a global hook, or in the worst case, they inject into every process and do a local hook which really isn’t recommended, but if they have a strong enough injector such as a kernel injector, this can be quite useful.
Inline hooks allow you to gain control when a chosen function is called. Things such as calling your own functions and such can be done even before the function has done their job. This can be done by modifying the first 5 bytes or any of a target function. The most basic way of doing this is by changing the first byte of the function to call your own code which then does whatever the hijacked function does at the end. The problem is that, what if you call that same function that you hijacked in your own program. This can cause a infinite recursion. To avoid this, you can call the hijacked function but skipping the bytes you overwrote. You do have to execute the first 5 bytes that you have overwrote as well.
Avoid Hook / Detection ( User Mode )
In user-mode inline hooks are usually place inside functions that are exported by a DLL. The most accurate way to detect and bypass these hooks would be to compare each dll against the original code. First, a program would need to get a list of each dll that is loaded, find the original file and read it, align and load the sections into memory then perform base relocation. Once the new copy of the dll is loaded into memory, the application can walk the export address table and compare each function vs that in the original dll. In order to bypass hooks, an application can then either replace the overwritten code using the code from the newly loaded DLL, alternatively, it could resolve imports in the newly loaded dll and use it instead (be aware that some dlls will not work if more than 1 instance is loaded). This method of bypassing dll hooks practically involves writing your own implementation of LoadLibrary, it’s really not for the beginners or faint-hearted. As much as I would like to post the code to do this, I won’t, because it can (and will) be used by script kiddies to bypass user-mode antivirus sandboxes or fight with other rootkits.
(We can also use manual dll loading to detect / fix EAT hooks, I won’t go into this in detail as EAT hooks are very uncommon).
Bypass / Detection ( Kernel Mode )
In kernel mode, inter-modular jumps are a lot rarer. Hooks in ntoskrnl can usually be detected by disassembling each instruction in each function, then looking for jumps or calls that point outside of ntoskrnl (into driver bodies, etc). It is also possible to use the same method explained for user mode hook detection: a driver could read each ntoskrnl module from disk, load it into memory and compare the instructions against the original. For inline hooks within drivers, scanning for jmp / call instructions that point outside of the driver body is much more likely to result in false positives, however, non-standard drivers that are the target of jumps / calls inside standard kernel drivers should raise a red flag. It is also possible to read drivers from disk. As drivers generally do not export many functions and IRP major function pointers are only initialized at runtime, it would probably be required that you compare the entire code section of the original and new driver. It is important to note that relative calls / jumps are susceptible to changes during relocation, this means that there will naturally be some differences between the original and new driver, however, both relative calls / jumps should point to the same place.
This is used by User-mode programs ( ring 3 ) to move onto kernel mode and use / call a kernel functions, functions beginning with “Nt/Zw”. Usually, this would point to KiFastCallEntry, but you can replace this to make a global hook which affects any user-mode programs which are calling kernel functions.
Remember that hooking onto SYSENTER does not affect drivers ( ring 0 ) and this cannot be avoided from the user-mode ( ring 3 ). However, you can use a kernel mode driver to set SYSENTER_EIP to its original value which is KiFastCallEntry, this can be done by just using the WRMSR instruction, but because KiFastCallEntry is not really exported by ntoskrnl, getting the original address could be painful.
SSDT, also known as System Service Dispatch Table, is similar to IAT, it contains pointers to APIs in ntoskrnl.exe. Things such as NtOpenThread and NtOpenProcess. A hook in this table consists to replace the original pointer value of an entry by the address of a function with the same prototype in any kernel mode loaded module. Usually, This hook is only made to deny access or just to filter the parameters / arguments and return to the original pointer value at the very end of filtering to call the original function. This can be used in the same way as IAT to call your own code whenever the hijacked function is called. Viruses usually try to detour functions such as NtTerminateProcess and NtOpenProcess to either get rid of handles. Remember that handles which have enough permissions can really screw up the virus by allowing termination of the virus. A virus can use this to either hide from an anti-virus or just be hidden.
The most simple way of avoiding malicious programs or viruses from gaining control is by finding the original SDDT and addresses by loading ntoskrnl.exe, this can be done by just using LoadLibrary in user-mode ( ring 3 ) then finding the export named “KeServiceDescriptorTable” and using it to find out the address of KiServiceTable within the disk image. For user-mode programs, you can use NtQuerySystemInformation to get back the kernel base address. Do note to yourself that you do need a driver to replace the SSDT.
Detection (Ring 0)
To find such hooks, you need to have a driver which scans the SSDT and compares each pointer of the addresses to the range of the ntoskrnl module. If one is outside the range, it is most likely due to it being hooked by a virus or a program. This isn’t that hard to detect compared to the rest. But, there are ways which exist to hook the SSDT and not change the address in the SSDT but change the assembly instruction in ntoskrnl, this is known as the inline hook, covered on top.
To remove such hook, you need to get the original addresses of the hijacked API and replace the bad address with the original address in the SSDT. This could remove some filters that windows has and just leave the kernel space in a bad space, meaning BSOD could happen with bad arguments.
IRP Major Function Hooks
A driver object for each driver contains a table which has 28 function pointers, these pointers are called by other drivers by using IoCallDriver or any other ways. The pointers go along operations such as IRP_MJ_READ/IRP_MJ_WRITE. These pointers can be replaced by making your own driver. This can be very useful to some and just wasteful to others.
Detection / Avoid Hook
Usually, every IRP Major Function pointers for a kernel driver would point to code which is within a driver’s address space, there is a reason why I used “usually” as this isn’t always the case. However, you can try to find drivers which are or have already tried to redirect IRP Major Functions from a verified driver to their own code. IRP Major Function pointers are initialized at runtime, so there is no real original address to replace like the hooks before. There are also problems with trying to load the same driver twice due to collisions, so it is not really possible to get an address to replace or a real way to find a hook like this. One possible way of avoiding these hooks can be done by calling the driver which are loaded before you, due to drivers being stacked on top of each other, the top driver passes data to the driver below and so on, so a program can just send a request to the lowest driver checking if it’s hooked or not.
IAT, also known as Import Address Table, is a table which has jump. Due to functions in DLLs change address and places, programs cannot call them directly but they can call a relevant jump to its own jump table. Whenever a program is running, it’s loader would put a pointer to each dll function at the right places in the IAT. If a virus were to inject itself to a program and modify the addresses in the import table, the virus will be able to execute its own code whenever the program calls the function of which the address is changed.
A program can easily avoid or just bypass this hook by getting the original address using the EAT, also known as Export Address Table, which stays the same. A function such as GetProcAddress and LdrGetProcedureAddress can return the original addresses. If a virus would still like to bypass this, they can simply hook onto LdrGetProcedureAddress /GetProcAddress and use it to return fake addresses. You can also write your own GetProcAddress function and use it to get the real functions addresses.
To detect IAT hooks, simply parse the PE structure of all modules of the targeted process. Then look at the import tables, and check if their addresses are inside the owning module.
To remove an IAT hook, you can look at the EAT (Export Address Table) of the original module, and restore the IAT address with the entry of the EAT.
Everyone who wants to redo or make their own program using this knowledge must remember that windows do have things such as PatchGuard ( for kernel hooking ) and DSE ( for unsigned drivers ). PatchGuard is only presented in x64 bit computers and not x32 bit, same for DSE. Meaning, if you are doing this in a x64, you might get BSOD if you do something which triggers a bug check. Make sure to do this all in a virtual machine and not on your own PC.
Well, there are many more hooks that I missed, but these are the main hooks that can be used to exploit windows, make a virus ( for fun ) or just to play around. Hopefully, you walk away knowing more than when you came, that was my goal. If you have any question, be sure to leave them in the comments. Credits are also shown below.