Video tutorial also available here: Created by Camtasia Studio 5
2. Creating our workspace
5. Tips & Tricks
6. Full Source
Wikipedia: Hooking in programming is a technique employing so called hooks to make a chain of procedures as an event handler.
I will try to explain this for the people new to programming, you can skip this if you already understand what Wikipedia is saying. In programming you use functions to order your code and make it easier to call the same chunk of code multiple times from different places. Example function:
Let's pretend that this function is part of a big project, a game. When a NPC attacks you this function gets called. What it does is it receives the arguments it needs "iHP" and "iDamage" where iHP is your hit points left and iDamage is the damage done by the NPC. The function will calculate the hit points that remain after the attack and return the value. In a game there are hundreds/thousands of these functions.
int Attacked(int iHp, int iDamage)
iHp = iHp - iDamage;
With hooking we can do a couple things with this function. We can call it whenever we want, prevent it from happening or make it do something else.
Now, what I'm going to try to explain with this tutorial is how you find these functions in a executable and how to hook them. And I will give some helpful tips in the end.
2. Creating our workspace
Stuff you need to for this tutorial:
Let's start with preparing our workspace:
- Create a new folder on your desktop and call it 'hooking'
- Copy notepad.exe from the Windows folder and paste it in folder hooking
- Download and install IDA Pro
- If you don't already have it, download and install Visual C++ Express Edition 2008 for free or download and install the trial version of Visual Studio 2008.
- Now create a new folder in your hooking folder and call it 'detours'
- Download detours.h and detours.lib and place them in the detours folder
Creating our project in Visual C++:
- Start Visual Studio 2008
- Go to: File > New > Project (or press CTRL + Shift + N)
- Click on 'Empty Project'
- Fill in 'SampleHook' as name and your hooking folder as path
- Make sure 'Create directory for solution' is ticked on and click OK
- Go to: View > Solution Explorer (or press CTRL + Alt + L)
- Right-click on 'SampleHook' and choose properties
- In this window change 'Application(.exe)' to Dynamic Library(.dll)
- Click on 'C/C++' and add the detours folder as directory in 'Additional Include Directories'
- Click on Linker and add the detours folder as directory in 'Additional Library Directories'
- Choose OK when done.
Our workspace is ready. Lets start with analyzing our target (notepad).
First of all, start IDA Pro. First you get an "About" screen, press OK. Then you get to the 'Welcome to IDA!" form. Here you can decide what you want to do. You can start on a new file (New), Work on your own (Go), or open an existing/old project. I'm going to guide you so you can choose the 'Go' option.
Now go to your hooking folder and from their you drag notepad.exe into IDA.
On the 'Load a new file' form you tick on "load resources" on click OK.
When IDA Pro asks you if you want to load the corresponding PDB file you choose 'Yes' and IDA Pro will start analyzing notepad.
When its done analyzing open the 'Functions' tab and search for "InsertDateTime(x)".
Right-click on the function and choose 'Edit function...' from the menu.
A new form will pop-up with more information about the function. What we want to know is the value of the 'Start address'. For me its ".text:01006F10" where .text is the section and 01006F10 is the address. Write this down somewhere.
Now press 'cancel' in this form and double click on the function. Scroll up A LITTLE! until you see something like: '; __stdcall InsertDateTime(x)'. Right-click on this spot and choose 'Set function type...' from this menu. This will give us more information about the function and parameter types. For me its: "int __stdcall InsertDateTime(int)" where the first int is the function type, __stdcall is the calling convention and the second int is the parameter type. Again, write this down somewhere.
We found all the information we need for this function. This is what I, and hopefully you got:
- int __stdcall InsertDateTime(int)
Let's move on to the next chapter to find out how to hook this function. Close IDA Pro.
Okay, the interesting part. The type of hook I'm going to show you is called 'detours'.
Go to: Project > Add New Item... (or press Ctrl + Shift + A)
In this form, click on 'C++ file(.cpp)' and name it 'main'.
Lets start with the Entry Point of our DLL. First include Windows so we can use the API's:
And include the detours header and library so we can use it:
Now I recommend you to copy/paste the following code because I'm not going to fully explain everything because this is basic C++ and not the point I'm trying to make with this tutorial. I did comment it a little though. Here it is:
#pragma comment(lib, "detours.lib")
Okay, what we need to do now is creating a prototype of the function we found so the compiler knows what we are talking about. Add this code between the includes and the entry point:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
switch (ul_reason_for_call) //Decide what to do
case DLL_PROCESS_ATTACH: //On dll attach
case DLL_THREAD_ATTACH: //On thread attach
case DLL_THREAD_DETACH: //On thread detach
case DLL_PROCESS_DETACH: //on process detach
Now that the compiler knows the function we are going to create our own. We are going to call it MyInsertDateTime and place it below the prototype and above the entry point. This is what we are going to place:
int (__stdcall* InsertDateTime)(int x); //Function prototype
As you can see, the value that our function returns is the value of the original function. So what we just did is expanded the function. It will do the same as it always did with a little extra, showing a messagebox.
int MyInsertDateTime(int x) //Our function
MessageBox(NULL, "InsertDateTime Just Got Called", "InsertDateTime", MB_OK);
return InsertDateTime(x); //Return the origional function
But, before we can test this we first need to define the address so the DLL knows where to look for the function. In order to do this we need to add 2 chunks of code. 1 part in DLL Attach and 1 part in DLL Detach.
The following part needs to be placed in the entry point between "case DLL_PROCESS_ATTACH:" and "break;". Here it is:
This will set the hook. And because we are clean coders we are going to unset the hook when the DLL detaches. This detachment also happens when the program closes so its the best place to put your cleaning code in. Add the following code between "case DLL_PROCESS_DETACH:" and "break;".
InsertDateTime = (int (__stdcall*)(int))DetourFunction((PBYTE)0x01006F10, (PBYTE)MyInsertDateTime);
Now go to: Build > Rebuild SampleHook.
Download Winject from the attachments and place it into your hooking folder.
Click on the button that says '...' in the DLL to Inject groupbox.
Select your DLL: .../hooking/SampleHook/Debug/SampleHook.dll
Open notepad.exe from your hooking folder
Go back to Winject and select notepad from the combobox in the Target Process groupbox.
Now in notepad go to: Edit > Time/Date (or press F5) and Tada!
Congratulations, you managed to create your first hook!
5. Tips & Tricks
- The reason Notepad.exe is so easy is because the program debug database files are available. These files contain information about the executables like the exact function names. If you want to analyze your target you can try to contact the developers for the .pdb file or look into debugging in order to find out how to find functions in an environment that ain't got the .pdb file.
- You can call InsertDateTime from your code whenever you want to execute the function.
6. Full Source
Use this source as example basehook for future projects. I included the full source and the whole hooking folder you are building while following this tutorial.