Network snoop introduces the basics of building a network sniffer to pick up all information being sent using TCP socket via
recv API, obviously, these will be the two APIs to hook to get information about data being sent/received. This code is more about introducing the readers to API hooking using Network snoop as an example. The reader can modify the code to hook APIs related to socket using UDP (which is why readers require knowledge of sockets, networking).
Before we start, reader will require basic knowledge of socket programming, windows hooks and a tad bit of assembly level programming.
Using the Code
The attached code is built using VS2010 express edition. The code must be referred to while going through this article. Also 64-bit API hooking code has been attached, but not tested.
We will start with the introduction of sockets APIs used to send and receive information, these are
recv. The attached code will try to hook/Hijack these APIs and attempt to log all information passed through them.
The following code is mentioned in the DLL module:
Notice the variable
g_NetSnoop declared globally, this object will be created (and its constructor will be called which will call
recvThread) every time the DLL is loaded into a new/different process. To get the DLL to load in a different process, we use Windows hook API (mentioned in the code: NetSnoop.cpp).
Here the variable
h holds the module handle of the DLL mentioned earlier. Calling
SetWindowsHookEx will cause all threads that belong to the caller's desktop to load the DLL whose module is passed to it, in this case:
Reader will have to be aware of Windows hook.
Another way is to call (without using hook)
CreateRemoteThread, you can call the above function
recvThread, please read up
CreateRemoteThread on MSDN. (This method is not used in code.)
Now comes the best part: API hooking (APIHook.cpp).
We will discuss API hooking for
send API, the rest are all the same, refer to the code at all times, this is important.
void sendThread(void*) will perform API hack, notice that this function is called from constructor of
struct NetSnoop (via different thread) or via API
Follow the code.
We first start by getting the address of the function and use
Be sure to use
VirtualProtect to alter the protection of a committed page, else you will get an exception (386 memory segment protection!). Look up MSDN for
The code after that is self explanatory.
Do use disassembly of function call to better understand how it works, you will notice the following code added at the function address:
MOV EAX,function adressJMP EAX
We are injecting the following code at the function call address using opcodes:
64 bit code is mentioned in attachment. Before we tamper with the instructions at the function address, we first store the original instructions so as to restore them when needed.
Remember: 32-bit DLL cannot be loaded/injected in 64-bit process space and vice-versa which is why you would require a separate 64-bit APP/DLL to snoop network traffic for 64-bit processes.
How It Works
When the hooked function (in this case
send) is called, the instruction pointer (EIP) is taken to the function address and will start executing from there (well...this how any function call works).
We have decisively placed a
JMP instruction at that very location. This will cause the
EIP to move to the function
Mysend, notice that this function has the very same signature, calling convection as the original function, this is to avoid any stack corruption.
EIP is routed to function
Mysend (as done in attached code):
- Log whatever is needed
- Restore the function's original instruction
- Call the original function to complete the functionality
In API hooking of
send function, please note that
send function is called twice by the application:
- Called by the application, through the
EIP is routed to
Mysend, after restoring the original instructions (shown below)
Code snippet from
APIHook.cpp, int WSAAPI Mysend(...)...
memcpy(send,StoreOriginal_Send,sizeof(StoreOriginal_Send)); int ret=send(s,buf,len,flags);
memcpy(send, Trap_Send, sizeof(Trap_Send)); }
Hence to maintain the stack,
RET instruction is also called twice:
- After it returns from the original
send function called from inside
- After it returns from
Restore (done in destructor)
Another important thing is to restore everything when the application exits.
This is important, when the application (
NetworkSnoop) exits, the Hook will be released by code (or by OS if hook is active when application is closed/terminated).
When applications are being unhooked, the injected DLL is removed, if code is not restored, the
JMP instruction will cause the
EIP to jump to an invalid memory location (since DLL is removed) causing a crash.
The application restores all in a destructor of a global object, the destructor is called during DLL unload, refer to the code.
bExit=true; while(uiInUse!=0) Sleep(500);
Debug the Call
The reader will have to write a simple console based application mentioned below and debug the send call via disassembly to better understand the introduction of a
MessageBoxA(0,"","",0); int z=send(0,0,0,0); return z;
Points of Interest
The best part is that
NetworkSnoop introduces API hooking using Windows Hook. This allows you to hook any function in any process provided your hook injects the DLL into it, for the hook to work, the targeted thread must have a message loop. I do hope you enjoy this short article on Network snoop. API hook technique is widely used, most famous is FRAPS (www.fraps.com), it uses the technique to hook DirectX calls to get information about game performance.
- 11th March, 2011: Initial post
- 2nd May, 2011: Correction in code to perform logging after recv API is called