Injecting DLL into process on load
If you ever had the need to inject DLL into a process right before it starts executing, you should have experienced many headaches in the process.
You should have tried injecting the DLL by creating the process CREATE_SUSPENDED, and have failed miserably. There are a few reasons to this. When a process is CREATE_SUSPENDED, many process state and environment structures arent initialized yet. The process main thread is supposed to initialize them and by introducing your thread at this early stage, there are many things that can go wrong. You, or the Windows API youve called might be reading structures that doesnt exist yet. You might run into a deadlock as your thread and process main thread each trying to fight for the loader lock. But the end result is same, you cant successfully inject your DLL into the process.
There are quite a few others have came up with the solution, but I guess my workaround is much easier.
1. Create your target process CREATE_SUSPENDED.
2. Patch the process entry point with 0xEBFE (JMP $-2, infinite jump to itself). Dont forget to save the original bytes of course.
3. Resume the main thread.
4. Poll the main thread EIP and see if it reached the EP already. If not, wait for a while and poll again.
5. Inject your DLL.
6. Suspend the main thread, restore the original EP bytes, resume.
Here is a snippet from my unreleased injector.
void Inject_Loader( const DllPayload& Payload, const std::string& Path ) { STARTUPINFOA StartupInfo = {0}; PROCESS_INFORMATION ProcessInformation; // initialize the structures StartupInfo.cb = sizeof(StartupInfo); // attempt to load the specified target if ( CreateProcessA( Path.c_str(), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInformation ) ) { Handle hProcess( ProcessInformation.hProcess ); // wait for the process to done try { // locate the entry point OptionalHeader optionalheader = PortableExecutable::FromFile( Path.c_str() ).NtHeaders.OptionalHeader; LPVOID entry = (LPVOID)(optionalheader.ImageBase + optionalheader.AddressOfEntryPoint); // patch the entry point with infinite loop PageProtect protect( hProcess, entry, 2, PAGE_EXECUTE_READWRITE ); std::string oep = VMemory::Read( hProcess, entry, 2 ); VMemory::Write( hProcess, entry, "\xEB\xFE" ); // JMP $-2 // resume the main thread ResumeThread( ProcessInformation.hThread ); // wait until the thread stuck at entry point CONTEXT context; for ( unsigned int i = 0; i < 50 && context.Eip != (DWORD)entry; ++i ) { // patience. Sleep(100); // read the thread context context.ContextFlags = CONTEXT_CONTROL; GetThreadContext( ProcessInformation.hThread, &context ); } if ( context.Eip != (DWORD)entry ) { // wait timed out throw "entry point blockade timed out"; } // inject DLL payload into remote process Inject_CreateRemoteThread( Payload, hProcess ); // pause and restore original entry point SuspendThread( ProcessInformation.hThread ); VMemory::Write( hProcess, entry, oep ); // you are ready to go ResumeThread( ProcessInformation.hThread ); } catch ( ... ) { // terminate the newly spawned process TerminateProcess( hProcess, -1 ); // rethrow the exception to top-level handler throw; } } else { // are you sure this is a valid target ? throw "unable to load the specified executable"; } }
I wasnt the first one to figure this out, but Matt had gone AWOL for so long I had to suspect California actually passed a law banning all WEPs.
This looks like a great idea…
When are you going to release the full source code?
I’d be interested in the “VMemory” and “PortableExecutable” classes…
They are just glorified and overengineered (think RAII and CRTP :P) wrapper for usual stuff like ReadProcessMemory, WriteProcessMemory, and PE header parsing. π
It will be released when I clean them up a bit and migrate all my code to github.
You can inject your dll before anything else (before any other code being executed by the main thread) by injecting a shellcode and using LdrLoadDll (VirtualAllocEx / WriteProcessMemory / Get/SetThreadContext).
You can also hook ZwContinue to hook the process before the entry point (and the TLS callback) without having to deal with the PE (and ASLR, your code is not compatible with windows vista / 7 if the executable is ASLR compatible)
Hello,
I would also like to have a version of your code, even if it is not finished.
My purpose is to write 2 tools : memory leak checker and trace tool (like NTtrace)
Indeed, I tried to code your idea. Without patching the entry point, i succeed in injecting my DLL in the child process, but not in the dependencies of this child process (as these DLL are not available when the child process is suspended). It is necessary as I want to overload memory allocation functions in the child process and in its dependencies to find all the memory leaks
But when I patch the entry point, I get the dependencies of the child process, but the dll injection is not done anymore…
so having your full source code to see where the bug is would be very helpful for me
thank you very much
Vincent Torri
PS 1: on 64 bits, it’s Rip that should be used, instead of Eip in the context structure.
PS 2: my code without patch of the entry point : https://github.com/vtorri/examine/blob/master/src/bin/examine_memcheck.c, the entry point patch is on my computer
i have pushed the entry point patch code in my repo, just reload the page. It still doesn’t work, unfortunately
Hey, im currently working on project that suspends processes and injects a dll into them. And sure enough, i have issues with create_suspended on x64 bit platforms. id love to see the full code for your solution
https://github.com/vtorri/examine/tree/master/src/bin/memcheck
look at examine_memcheck.c, line 253, and in src/lib for the functions
wow thats a lot of extra features π that looks like a good starting point. trying to extract what i need form it π
you can even just compile the library, which does all the stuff, and mimic what is in examine_memcheck.c to inject your DLLin the process you want
thats probably what im going to do. thanks π ever try to use Reflective dll injection with this?
no, i didn’t. Maybe one day, but i’m currently more interested in using this framework to do a strace-like program
so my plan is comment out most everything below the process dependencies set, and then try a reflective dll inject at that point. then repatch.
hmm, i seem be having issues getting the process ID out of the process struct. Every time i reference process->id it yells at me about incomplete class types.
can you please open a issue on github, with as much informations as possible ?
thank you
Great info here ,
If the target process is spawned by someone else, you have to intercept its creation before it is initialized. There are some ways to do that, all of them are undocumented and therefore not future proof.Anyway the best injector i can found around is this : http://dll-injector.com