Infopulse - Expert Software Engineering, Infrastructure Management Services
Send message Request a call
Send message Please fill in this quick form and we will send you a free quote shortly.
* Required fields
Request a call Please fill in this quick form and we will call you back shortly.
* Required fields
Subscribe to Infopulse Newsletter Please fill in this quick form to be among the first to receive our updates.
* Required fields
Send an email to Volodymyr Korniichuk Please fill in this quick form to contact our expert directly.
* Required fields
Read the rest of the Case Study Don't miss the most interesting part of the story!
Submit this quick form to see the rest and to freely access all case studies on our website.
* Required fields

Hooking is Simple

Hooking is a technology for intercepting function calls in other processes. Hooking, as any other sufficiently powerful technology, can be used for both good (sniffers, audio/video grabbers, extension of the closed software functionality, logging and bug fixing) and bad deeds (Trojans, cracks, and keyloggers). Hooking has been described many times. But the trouble is that, somehow, each article on hooking starts telling in its second paragraph about the virtual functions table and memory architecture and asks to study huge junks of assembly code. Each formula in a text is known to reduce the number of readers by 50%, and such things — by 100%. That’s why there is a need in the article that will tell about hooking in a simple language. There is no assembler, no complicated terms, and only a score of a simple code in С++. If you wanted to learn hooking and didn’t know where to start, start with this article.

Real Task

To better understand what we are doing, let’s set a real task. Say, let’s make Firefox write in its header Hi, Infopulse! instead of current text (now it’s Nearshore, Offshore software development Eastern Europe. IT outsourcing Ukraine. — Mozilla Firefox) when opening Infopulse site. Yes, I know that it can be done by editing the Firefox source codes, with browser plug-ins, user scripts and what not, but for the sake of learning we will hook it.

Small Bit of Theory

With an application being started, the OS creates its process. Roughly speaking, an .exe file is copied into the memory, then the libraries (.dll) required for running are determined (it’s written at the beginning of each .exe file), these libraries are searched (in the application or system folders) and uploaded into the process memory. Then it is determined which functions from the libraries are used by the application and where they are located (which library and place in it). A table like SomeFunction1() — SomeLibrary1.dll — %SomeFunction1()_address% is built. When the application wants to use the function, it finds the required library in its memory, finds the required address and passes control there.

Hooking 1st example

The essence of hooking is to make the application believe that the required function is at a different address.

Hooking 2nd example

It’s done as follows: write your own library SomeLibrary2.dll with your own function (SomeFunction2). Then upload the library into the memory of the foreign process (Windows has a special function for it) and edit the table mentioned above so that it may contain the SomeFunction1() — SomeLibrary2.dll — %your_SomeFunction2()_address% line. To understand how to do all this manually, you should know loads of different stuff: Windows memory structure, functions naming, etc. It’s difficult but not really, you can simply do without it. If you need it, just read some advanced article. We’ll take a different route: we’ll use a ready-made library (Microsoft Detours) that will do all the dirty work for us.

Something about Microsoft Detours

Pros:

  • easy to learn and use
  • rather efficient
  • good documentation
  • many examples in source codes
  • developed by Microsoft: “OS-friendly”
  • free for research and non-profit use
  • does not require to know the assembler

Cons:

  • proprietary
  • rather costly for commercial use or х64 architecture

In general, I’d recommend to start learning hooking with Detours — if it’s just for fun, then it will suffice: you will progress quickly and will like it. If hooking is needed for a serious project though, you’ll easily switch to free and open (but a bit more complicated) libraries like mhook, will buy Detours or will invent your own wheel (the last two cases require rather serious reasons).

Cunning Plan

  1. Understand which function to hook.
  2. Create your own library with the function to replace the original one and to do what is needed.
  3. Mount the hook (upload the library into the required process memory and index the required function).
  4. PROFIT!

Where to Hook

MSDN rather broadly hints that the window header can be set with the SendMessage function, at the same time the second attribute should set WM_SETTEXT, and the last should set the text itself. Yet, there are some “buts”:

  1. Instead of SendMessage, PostMessage or something else can be used.
  2. SendMessage can be anything but a function: a macros referring to some other function (later on we’ll see that this is the case).
  3. Firefox, like some other cross-platform application, can run without any Windows functions for creating window standard elements using instead its own cross-platform GUI (fortunately, it’s not so, but who knows!)

So, all needs to be properly checked. A marvelous free application API Monitor will come in handy. It allows peeping into a process to see the functions it calls and their attributes. You might have guessed that it’s also done with the help of hooking. So, start Firefox and API Monitor. To begin with, define filter settings in API Monitor: the group of functions to be monitored. With absolutely all functions chosen, the monitored application will run very slowly (and can completely hang up), and with too few chosen, the needed ones may be missed. That’s why, think and select only the group that may contain the functions working with GUI Windows. Let’s select Graphics and Windows Application UI Development and double click Firefox in the Running Processes toolbar. Now API Monitor will show calls to all API functions and their attributes in the right-hand panel.

Switch to Firefox, open infopulse.com, wait till the heading changes to the required one and then return to Api Monitor to stop monitoring. You will most probably be surprised at the number of functions called — they can count literally hundreds of thousands in a few seconds of monitoring, and we are not even close to monitoring all the functions. Oh yes, all this really happens when a simple web-page is opened in a browser! And you dare to complain that these few seconds last too long. :)

Where to hook

The required function can be found with the help of Search in the Monitoring Results tab. Enter WM_SETTEXT to find out that the SendMessageW function has really been called with this attribute — it is highly probable that this is the window heading setting function. (Note: if you need to use Unicode version, set the W at the end of the name SendMessageW). To set the hooks, the exact name of the substituted function is needed. After that change the name.

Create Your Own Library

    1. Start Visual Studio.
    2. Create a new project: File->New->Project. Type: Visual C++ -> Win32 -> Win32 Project. Select the Dll type in the New Project window.
    3. Open dllmain.cpp and enter such code:
      #include 
      #include "C:\Program Files\Microsoft Research\Detours Express 3.0\src\detours.h"
      LRESULT (WINAPI * TrueSendMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = SendMessageW;
      __declspec(dllexport) LRESULT WINAPI MySendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
      {
          if (Msg == WM_SETTEXT && wcsstr((LPCTSTR)lParam, L"/ Nearshore, Offshore software development Eastern Europe. IT outsourcing Ukraine — Mozilla Firefox ") != NULL)
              return TrueSendMessageW(hWnd, Msg, wParam, (LPARAM)L"Hello, Habr");
          return TrueSendMessageW(hWnd, Msg, wParam, lParam);
      }
      BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
      {
          if (dwReason == DLL_PROCESS_ATTACH) 
          {
              DetourRestoreAfterWith();
              DetourTransactionBegin();
              DetourUpdateThread(GetCurrentThread());
              DetourAttach(&(PVOID&)TrueSendMessageW, MySendMessageW);
              DetourTransactionCommit();
          }
          else if (dwReason == DLL_PROCESS_DETACH)
          {
              DetourTransactionBegin();
              DetourUpdateThread(GetCurrentThread());
              DetourDetach(&(PVOID&)TrueSendMessageW, MySendMessageW);
              DetourTransactionCommit();
          }
          return TRUE;
      }
      
    4. Open project properties and add the C:\Program Files\Microsoft Research\Detours Express 3.0\lib.X86\detours.lib value in the Additional Dependencies field of the linker settings tab. Attention! your path can be different depending on where you have set your Detours library.How to create a library
    5. Compile the project: Build -> Build Solution. At the end, we have a .dll (let’s name it hooktest.dll)Let’s decompose the original. Firstly, connect the heading Windows files (to use the SendMessageW function) and Detours (to be able to mount/dismount the hooks). In seemingly complicated line 3 we only save the real SendMessageW function indicator in the TrueSendMessageW variable. It is needed for:
      1. Calling the real SendMessageW function from our “fake” one
      2. Resetting the real function indicator when we want to dismount the hook.

Then goes the fake MySendMessageW function. It’s absolutely simple. In any WM_SETTEXT message containing Infopulse, the text will be replaced with our text. Otherwise, it works as a transparent proxy. Note the __declspec(dllexport) prefix, it is needed to enable other processes to be able to use this function.

The DllMain function is called by the OS in certain cases, e.g. when a library is attached to/detached from the process. All this is also simple. We need to mount hooks at the moment of attaching and dismount them when detaching. The Detour library requires it to be done in transactions, and it makes sense as you can imagine what would happen if a bunch of people wanted to hook one but the same process at the same time. The most important in this code is line

DetourAttach(&(PVOID&)TrueSendMessageW, MySendMessageW);

It is this line that makes the process “believe” that instead of the real SendMessageW function, our MySendMessageW function must be called. It is this function for which all this fuss was kicked up. If you ask, I once wrote a similar function manually. With all possible combinations of function types and architecture, it took me a couple of weeks. So, you have just saved them — congrats.

Setting the Hook

Microsoft Detours offers different hook setting options — we’ll use the simplest one. The samples set, complementary to the library, contains a withdll.exe application. It takes for attributes the path to the application and the library that can be uploaded into the memory of this application after it has been launched. All this is launched, say, in this way:

withdll.exe -d:hooktest.dll "C:\Program Files\Mozilla Firefox\firefox.exe"

PROFIT!

Now we can open infopulse.com:

Hurrah! It works!

I wish you good luck in mastering hooks.

Share this blog article:
Subscribe to our Newsletter