What is a Hook? In software development, Hooking is a concept that allows modifying the behavior of a program. It’s the chance that code gives you to change the original behavior of something without changing your code of the corresponding class. This is done by overwriting the hook methods.
This type of implementation is very useful in the case of adding new functionalities to applications, also facilitating the communication between the other processes and messages of the system. Hooks tend to decrease system performance by increasing the processing load that the system needs to perform for each message. It should be installed only when needed and removed as soon as possible.
Imagine that you are using a Customer Management System (CMS) from a third party and you would like a super administrator to be warned by email every time a new post was published and that this behavior is not the default of the tool. There would be a few ways forward:
- Change the CMS source code is not a good idea, after all in the next update of the tool you will face the dilemma of losing your change or not be able to keep everything updated;
- Create your own CMS is another bad idea, after all, you do not have the time or resources enough to create new things or even maintain what to build;
- Investigate the possibility of using a hook, that is, check if the CMS looks in external modules or plugins for functions of a given name to be executed at the desired moment, in this case, the publication of new posts.
The extensibility is another advantage of using hook methods that allow the application to extend its stable interfaces. Hook methods decouple stable interfaces and behavior of a variation domain that can arise from the instantiation of an application for a particular context.
Hooks as Design Patterns
It is interesting to note that many (almost all) design patterns typify semantics for hooks. They represent how to implement sub-systems of hot spots. Some are based on the principle of separation construction: Abstract, Factory, Builder, Command, Interpreter, Observer, Prototype, State, and Strategy.
Others in both patterns of unification and separation construction: Template Method and Bridge.
Semantics is typically expressed in the hook method name (for example, in the Command, the method is called execute()).
Virtual Method Table hooking
Virtual methods are called in the same way as static methods, but because virtual methods can be modified, the compiler does not know the address of a particular virtual function when you call it in your code. The compiler, for this reason, builds a Virtual Method Table (VMT), which provides a means to search for function addresses in runtime. All virtual methods are triggered at runtime through the VMT. The VMT of an object contains all the virtual methods of its ancestors, as well as those it declares. For this reason, virtual methods use more memory than dynamic methods, although they run faster.
Since VMT is a table that contains the pointers with memory addresses for the interface functions, what needs to be done is to replace the original memory address with an address of a valid hook function. In this way, the called method will be overwritten, and the new desired behavior of the function will be executed.
API means the Application Programming Interface. The Hooking API technique literally allows you to reprogram the functions of the operating system. With the power to intercept such commands, you can change their parameters by changing the action that would be performed originally.
It is possible, for example, to block deletion of a particular file, prevent an application from running, and request a user confirmation to save a document to the disk, and so on.
Without a doubt, the biggest slice of choice is in the area of security, such as antivirus and antispyware. But there are situations in our everyday development where the Hooking API, can be possibly being the only way out.
API Hooking, in our context, means catching an API from the OS, or from any DLL, and change its normal execution to another place, more precisely, to another function. There are basically two ways to do this:
- EAT and IAT: all EXE / DLL contains API to import and export tables. These tables contain pointers that indicate the API Entry Point. By changing these pointers, making them point to our callback, we have a hook. However, if this EXE / DLL does not import API’s, this method will not work;
- Simple Code Overwriting: As previously mentioned, if it were possible to add a call to our callback at the beginning of the API code, we could “hook it”, making our function run whenever the API was called. But there is a problem: if after our code was processed, we wanted to call the original API, we would fall back on our callback, and a stack overflow would be generated. One solution would be to undo the hook to be able to call the API, redoing it once it is executed. However, during this middle ground, several API calls can be made and would not execute our callback;
- Inline Hook is when we get the first instructions of a function, and we exchange for a Jump, Push or a Call for our function.
Recommended read: Windows operating system also supports hooking API. Let’s know how Windows API hooking works?
As hook methods decouple stable interfaces and behavior of a variation domain that can arise from the instantiation of an application for a specific context occurs an inversion of control. Objects event handlers customize processing steps. In other words, when an event occurs, the handler reacts invoking hook methods on pre-registered objects that execute specific event processing actions. Examples of events: window messages, packets arriving from communication ports.
Internal IAT Hooking
Each process in Windows has a table called Import Address Table (IAT), which stores pointers to the functions exported by the DLLs of each process. This table is populated dynamically with the address of the functions of the DLLs at run time.
Through the use of specific functions, we can make the IAT table writable, being possible to change its address by an address of a custom function, re-marking the table as read-only after this change. When the process tries to call the function, its address is fetched in the IAT table, and a pointer is returned. As the IAT table has been modified, the custom function is called in place of the original function and the code injected into the process is obtained.
Netfilter is a Linux kernel subsystem greater than 2.4. It is responsible for packet filtering, NAT, firewall, redirection, among others. Netfilter is very extensible, and its documentation is very well done. It leaves the possibility of using Hooks in the Kernel code, making its use very malleable and widely adopted by the community. These Hooks leave several possibilities and can serve as triggers for certain events.
The hooking programming techniques are powerful and open up a range of possibilities for programmers, but it should be used with caution since they add greater complexity in the flow of processes and change the original behavior of the OS, applications or other software components, making it difficult to understand the logic of software. Besides that, as mentioned earlier in this article, the use of these techniques without criterion may degrade the performance of the applications.