Injector Based on Import Directory Modification menu

Shout-Out

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    GliderPro's Avatar Member
    Reputation
    -1
    Join Date
    Mar 2009
    Posts
    93
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Injector Based on Import Directory Modification

    CreateRemoteThread injectors can be found all over these forums but I wanted an injector that allowed me to hook API functions before any other code runs. The attached file contains the code for an injector DLL, a test DLL to be injected, a native sample application, and a managed sample application. The injector code comes straight from the Microsoft DetourCreateProcessWithDLL function. I just ripped out all the dependencies and collapsed all the necessary code into a single file.

    Note to mods: I posted in this section because I figured the audience here would be most interested in this code. Feel free to move it if you deem this an inappropriate place.
    Attached Files Attached Files

    Injector Based on Import Directory Modification
  2. #2
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Isn't this common knowledge? CreateProcess as suspended, inject, resume.

  3. #3
    amadmonk's Avatar Active Member
    Reputation
    124
    Join Date
    Apr 2008
    Posts
    772
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's a different method of injection than the usual CreateRemoteThread, I suppose. Not entirely sure what it buys you (unless you want to look at the client integrity scan or whatever).
    Don't believe everything you think.

  4. #4
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not quite sure I understand the target audience for this code.

    How is this any different to using a typical generic injector (like one of the ones I'lve posted -- which reminds me, I'll post my updated one which can call exports remotely) which creates the process as suspended, injects a dll, the dll then hooks all the functions and does whatever, then you resume the process.

    You still get to hook before the process runs any code, you just seemed to have moved the hooking code from the DLL to the injector.

    P.S. For the love of god learn C++, your code would be about 10x shorter and a lot less buggy than your current C based implementation.

  5. #5
    GliderPro's Avatar Member
    Reputation
    -1
    Join Date
    Mar 2009
    Posts
    93
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cypher the injectors you posted use CreateRemoteThread. As I understand it the ones that use CreateRemoteThread don't allow you to get control of a process before anything else runs. Also, as I mentioned this is not my code and I would rather spend time writing the injected code than rewriting the injector in C++.
    Last edited by GliderPro; 08-13-2009 at 04:15 PM.

  6. #6
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by GliderPro View Post
    Cypher the injectors you posted use CreateRemoteThread. As I understand it the ones that use CreateRemoteThread don't allow you to get control of a process before anything else runs. Also, as I mentioned this is not my code and I would rather spend time writing the injected code than rewriting the injector in C++.
    Wrong.

    You can control a process before anything runs using the CreateRemoteThread method. In fact, the method you use for injection has ZERO BEARING on process creation.

    All you need to do to control a process before any code runs is call CreateProcess with the CREATE_SUSPENDED flag. At that point the process has not run any code, and you can do whatever you want.

    Whether you inject with CreateRemoteThread, SetThreadContext, SetWindowsHookEx, RtlRemoteCall, etc etc doesn't make ANY DIFFERENCE. Why? Because the process IS ALREADY SUSPENDED.

  7. #7
    GliderPro's Avatar Member
    Reputation
    -1
    Join Date
    Mar 2009
    Posts
    93
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    According to CreateRemoteThread page on MSDN... "During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process."

    Granted Microsoft's documentation is often vague but I read that to mean that the DllMain function of every imported DLL will be called before your remote thread runs. The injector I posted ensures that your DllMain is called before any other one. Please correct me if I'm misinterpreting the documentation.

  8. #8
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by GliderPro View Post
    According to CreateRemoteThread page on MSDN... "During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process."

    Granted Microsoft's documentation is often vague but I read that to mean that the DllMain function of every imported DLL will be called before your remote thread runs. The injector I posted ensures that your DllMain is called before any other one. Please correct me if I'm misinterpreting the documentation.
    If you look at the code you've pasted you'll see that you're using CreateProcess with CREATE_SUSPENDED anyway. Hence, even if by the time the process is frozen (which I assume to be just before the entry point is run) all the DLL's initialization routines have been run, what you're currently doing does nothing to fix that problem.

    If you're saying that when CreateRemoteThread is called then that forces the imported DLL initialization routines to be run, then no, I'm almost certain that is false.

  9. #9
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, I've looked into it, and whether or not LdrInitializeThunk is called seems to depend on how the new remote thread is used.

    Scenario 1:
    Process created with CREATE_SUSPENDED, new remote thread created on LoadLibrary.

    Result 1:
    LdrInitializeThunk called.

    Scenario 2:
    Process created with CREATE_SUSPENDED, new remote thread created with CREATE_SUSPENDED, remote thread hijacked with RtlRemoteCall.

    Result 2:
    LdrInitializeThunk called.

    Scenario 3:
    Process created with CREATE_SUSPENDED, new remote thread created with CREATE_SUSPENDED, remote thread hijacked with custom RtlRemoteCall 'clone'.

    Result 3:
    LdrInitializeThunk NOT called???

    Result 3 is quite bizarre. Using my custom remote function calling API (Essentially it's like RtlRemoteCall except I've added extra functionality and removed the arbitrary restriction on the number of parameters) it seems that LdrInitializeThunk is not being called...

    Scenario 4:
    Process created with CREATE_SUSPENDED, process is PEB hooked (is it even possible at at this stage? obviously no modules are linked -- except possibly NTDLL -- but surely you could manually link in some), process is resumed.

    Result 4:
    Unknown. Needs testing.

  10. #10
    GliderPro's Avatar Member
    Reputation
    -1
    Join Date
    Mar 2009
    Posts
    93
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very good info Cypher. Thanks for clearing up my misconceptions about that injection method. Seems like there is no reason in my mind not to use CreateRemoteThread now.

  11. #11
    goderion's Avatar Active Member
    Reputation
    25
    Join Date
    Oct 2008
    Posts
    54
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello.

    Im currently working on a way to hook the WinAPI. At the moment i try it through an injected dll.

    I do the common way via CreateProcess, CreateRemoteThread.
    Now i get strange results, if i try to hook functions inside the Internet Explorer 8.

    I figured out, that if i inject a dll into the process of IE8, who is supended, IE8 is unable to load some controls after ResumeThread is called. The injected dll do nothing, only an empty DllMain. I dont get it!

    Here is the code, who let appear IE8 weird:
    Code:
    #include <windows.h>
    
    
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	return TRUE;
    }
    
    
    
    int main(void)
    {
    	DWORD rVal;
    	CHAR* pApplicationName;
    	CHAR* pDllName;
    	PROCESS_INFORMATION ProcessInfo;
    	STARTUPINFO StartupInfo;
    	VOID* pMemory;
    	DWORD Size;
    	DWORD NOB;
    	HANDLE hThread;
    	DWORD ThreadId;
    	DWORD Code;
    
    	pApplicationName = "C:\\Programme\\Internet Explorer\\iexplore.exe\0\0";
    	pDllName = "D:\\Projekte\\InjectDll\\DllTest\\Release\\DllTest.dll\0\0";
    	Size = strlen(pDllName) + 2;
    
    	ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    	rVal = CreateProcess(pApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo);
    
    	pMemory = VirtualAllocEx(ProcessInfo.hProcess, NULL, Size, MEM_COMMIT, PAGE_READWRITE);
    	rVal = WriteProcessMemory(ProcessInfo.hProcess, pMemory, pDllName, Size, &NOB);
    
    	hThread = CreateRemoteThread(ProcessInfo.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pMemory, 0, &ThreadId);
    	while(TRUE)
    	{
    		GetExitCodeThread(hThread, &Code);
    		if(STILL_ACTIVE != Code)
    		{
    			break;
    		}
    	}
    
    	rVal = VirtualFreeEx(ProcessInfo.hProcess, pMemory, 0, MEM_RELEASE);
    	rVal = ResumeThread(ProcessInfo.hThread);
    	rVal = CloseHandle(ProcessInfo.hThread);
    	rVal = CloseHandle(ProcessInfo.hProcess);
    
    	return 0;
    }
    I used the same main.cpp for the exe and dll. Do anyone know, whats going on? i tested this at home and at work, always the same result. Google & Co wasnt able to help me.

  12. #12
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Holy crap your loader code is awful.

    High probability of resource leaks.
    High probability of a deadlock.
    High probability of undefined behavior.
    High probability of failure without notice.
    Unnecessary use of CPU intensive infinite loops.
    etc.

    Not to mention some of it makes just plain zero sense. (Like adding two extra nulls to a string literal... String literals are null-terminated by default!!)

    Have you tried using something more 'standard' like I dunno, Winject or something?? I personally used to inject DLLs system-wide (including IE) for my usermode rootkit and I did not experience what you're describing.

    If you can provide exact steps to reproduce the error I'll give it a go on my end and see what I can come up with.

  13. #13
    goderion's Avatar Active Member
    Reputation
    25
    Join Date
    Oct 2008
    Posts
    54
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hehe, i got bashed by Cypher! ^^

    I wrote this code at work in 2 minutes to show an example code to reproduce the error. The code is minimized to the needed elements, to make it easy to understand.

    I would never use code like this in my own projects, like you said, no error handling, no timeout or sleep in the loop. normaly i use my framework where i wrapped all used winapi handles and use them only through smartpointers. (impossible to leave a handle unclosed)

    Here i rewrite it, now its safer, but still ugly.
    Code:
    #include <windows.h>
    
    
    void ExecuteAndInject(const char* pApplication, const char* pDllName)
    {
    	DWORD rVal;
    	STARTUPINFO StartupInfo;
    	PROCESS_INFORMATION ProcessInfo;
    	void* pMemory;
    	DWORD Size;
    	DWORD NOB;
    	HANDLE hThread;
    	DWORD ThreadId;
    	DWORD Code;
    	DWORD Timeout;
    
    	Size = strlen(pDllName) + 1;
    
    	ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    	ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
    
    	rVal = CreateProcess(pApplication, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo);
    	if(rVal)
    	{
    		pMemory = VirtualAllocEx(ProcessInfo.hProcess, NULL, Size, MEM_COMMIT, PAGE_READWRITE);
    		if(pMemory)
    		{
    			rVal = WriteProcessMemory(ProcessInfo.hProcess, pMemory, pDllName, Size, &NOB);
    			if(rVal && (NOB == Size))
    			{
    				hThread = CreateRemoteThread(ProcessInfo.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pMemory, 0, &ThreadId);
    				if(hThread)
    				{
    					Timeout = GetTickCount() + 10000;
    					Code = 0;
    
    					while(Timeout > GetTickCount())
    					{
    						GetExitCodeThread(hThread, &Code);
    						if(STILL_ACTIVE != Code)
    						{
    							break;
    						}
    
    						Sleep(10);
    					}
    
    					rVal = CloseHandle(hThread);
    				}
    
    			}
    
    			rVal = VirtualFreeEx(ProcessInfo.hProcess, pMemory, 0, MEM_RELEASE);
    		}
    
    		rVal = ResumeThread(ProcessInfo.hThread);
    		rVal = CloseHandle(ProcessInfo.hThread);
    		rVal = CloseHandle(ProcessInfo.hProcess);
    	}
    }
    
    
    int main(void)
    {
    	ExecuteAndInject(
    		"D:\\Programme\\Internet Explorer\\iexplore.exe",
    		"");
    
    	return 0;
    }
    Everyone can compile and run it, you dont need to pass a valid DllName. IE8 still looks weird, but why?

  14. #14
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1358
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Arrrghhh. The nesting... IT BURNS!

    This my friends is yet another bonus of RAII, you don't need to do all that ridiculous nesting in order to make sure cleanup is done at the appropriate time.

    Also, your use of a for loop is still epic ****ing fail. Use WaitForSingleObject. It's there for a reason. All you've done by putting the sleep and the timeout is slap a big fat ugly bandaid on the code, rather than actually fixing it.

    Lastly, why are you declaring all your variables at the top of the function? Seriously, what is this.. the 80s? That shit has been deprecated in C++ from the get-go, and afaik it's deprecated in the most recent C standards.

    Because I'm afraid my brain might explode when attempting to debug your code, how about this... Try my injector and tell me if the same thing happens:
    Ramblings++ » Blog Archive » Generic Dll Injector for x86 and x64 + Export Caller - Just another periodically updated, syndicated website

    If it does, upload your MODULE (source AND binaries) so I can test it on my machine. Kthx.


  15. #15
    ramey's Avatar Member
    Reputation
    45
    Join Date
    Jan 2008
    Posts
    320
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Cypher made a great points. There is no reason to declare all your variables at the start.

    Pickup a copy of Effective C++ by Scott Meyers and in it you will find him discussing the need to delay your declarations of variables as long as possible because it is pointless and also wasteful declaring your variables at the top. Also, start to use EnsureCleanup classes. Cypher has made a nice library on GD, afaik.

Page 1 of 2 12 LastLast

Similar Threads

  1. Awards Modification Added
    By Matt in forum Suggestions
    Replies: 17
    Last Post: 09-21-2006, 07:57 PM
  2. WSG flag hide spot,ally base! 1.12
    By TMK in forum World of Warcraft Exploits
    Replies: 22
    Last Post: 08-28-2006, 01:20 PM
  3. Warsong Gultch- Enemy base before game begins
    By Cloud in forum World of Warcraft Exploits
    Replies: 29
    Last Post: 08-21-2006, 02:27 PM
  4. Something very odd in AV on top of the alliance main base in
    By JoKeR` in forum World of Warcraft Exploits
    Replies: 11
    Last Post: 08-20-2006, 03:58 AM
  5. Mount in Enemy Base in WSG
    By Matt in forum World of Warcraft Exploits
    Replies: 6
    Last Post: 08-09-2006, 11:26 PM
All times are GMT -5. The time now is 07:36 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search