The source files depend a lot on function pointers. Overview is recommended.
DLL Injection is similar to 'Injecting' code into an already running process. Many things have been taken from Matt Pietrek's book 'Secrets of Windows 95'.
Function interception means 'intercepting' an API function that was loaded by a statically linked DLL by modifying the address of the beginning of the function's code, resulting in the application to call your 'intercepting' function instead of the original 'intercepted' function. This is similar to the idea in "APIHijack - A Library for easy DLL function hooking" article posted by Wade Brainerd.
"DLL Injection" is not an accurate name for what my content will actually be. My code will 'inject' a series of assembled assembly language instructions [Code] into some available space in the running process and alters the registers to point at the offset of the 'injected' [code]. The process will of course execute the instructions which will load a certain DLL, which is the DLL that is being injected. Note that this code 'Injects' [code]. The code can be anything, it doesn't necessarily have to load a DLL. Hence, the inaccurate title.
There are two ways to 'Inject' a series of bytes into an already running process.
VirtualAllocEx() - which isn't supported in Win9x/ME - will allow a process to reserve or commit a region of memory within the virtual address space of a separate specified process. Use
WriteProcessMemory() to write the data in the reserved/committed area of the target process' memory. The other way is to directly use
WriteProcessMemory() - which is supported in all versions of Windows - to search for some accessible area of the target process' memory and replace the bytes within the area size equal to the size of the code. Of course, you will be saving a backup of the replaced bytes in order to put them all back later on.
(Of course, you can use
CreateRemoteThread() instead of all this, but it's not supported in all versions of Windows.)
One good yet slow method of injecting the code is using Windows' debugging functions. Suspend the threads of the running process (using the debugging functions) and use
SetThreadContext() to save a backup of all the registers and then modify the
EIP register, which is the register that contains the offset of the current to-be-executed code, to point it to the 'Injected' code. The injected code block will have a breakpoint set at the end of it (Interrupt 3h -int 3h-). Again, use the debugging functions to resume the threads, which will then continue executing till the first breakpoint is reached. Once your application receives the notification, all you have to do is restore the modified bytes and/or un-allocate any allocated space in memory, and finally restore the registers (
SetThreadContext()). That's all there is to it. The application has no idea of what has happened! The code was executed, and probably loaded a DLL. As you know, loaded DLLs are in an application's address space, therefore, the DLLs can access all memory and control the whole application. Very interesting.
Lookup the MSDN library for more information (MSDN).
Useful points to lookup:
- Memory management...you need to know how Windows manages its memory.
- How DLLs tick - MSDN - I suggest you read it. Might help in inspirations. Revising isn't bad.
- PE/COFF Headers specifications... The most important thing if you're doing this in Win9x/ME - MSDN.
- Basic debugging APIs...those are some APIs that allow you to debug certain applications. Lookup the section "Debugging and Error Handling" in MSDN.
- Enough knowledge of ASM is required of course...and OPCODES of instructions.
Have a look at the accompanied files: Injector_src.zip.
Google Groups - A Message board thread on
Notice the DLL project in the zip file. This function is in HookApi.h.
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue))
PROC WINAPI HookImportedFunction(HMODULE hModule,
if ( IsBadCodePtr(pfnNewProc) ) return 0;
pfnOriginalProc = GetProcAddress(GetModuleHandle(FunctionModule),
if(!pfnOriginalProc) return 0;
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) )
if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew);
if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) )
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR,
if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader )
while ( pImportDesc->Name )
PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name);
if ( stricmp(pszModName, FunctionModule) == 0 )
if ( pImportDesc->Name == 0 )
pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk);
while ( pThunk->u1.Function )
if ( (DWORD)pThunk->u1.Function == (DWORD)pfnOriginalProc )
pThunk->u1.Function = (PDWORD)pfnNewProc;
HANDLE OpenLog(char *Filename)
BOOL CloseLog(HANDLE h)
DWORD AppendLog(char *str, DWORD uSize, HANDLE h)
They are the functions to write to the LOG file. What the whole project does is inject a DLL into an already running process (mIRC.exe - mIRC chatting program (mIRC)) [in my case]. It then creates a Log file of all the intercepted Winsock functions. Have a look at Successlog.txt. It is highly recommended that you apply the program on mIRC only, since it has been created for it. Have fun coding your own :)
I think you got the idea. I hope this is useful.
Nasser R. Rowhani - email@example.com