C# .NET Dll Injector menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Release] C# .NET Dll Injector

    This is a Dll Injector I have been working on as part of my personal projects. It's entirely written in C# .NET (excepting the Dll to be injected - but the one included is just for demonstration) using pinvokes obviously.

    It injects a dll into a target process using the CreateRemoteThread / LoadLibrary method. I've also added the functionality to call exports from the injected Dll. Credits go to Cypher for the idea behind how to find the address of the exported function, by loading module into this process as data and finding address locally, then calculating etc. .Net implementation is rather different than his code in post here: Ramblings++ Blog Archive Calling Exports in an Injected DLL - Just another periodically updated, syndicated website

    The ThreadFunc called by CreateRemoteThread can take one parameter. I've added the ability to call an export and pass it a parameter as well (rather than just calling an export with no parameters). It only supports structs (C# value types like int, short, char etc or structs such as struct MyStruct). I wrote some custom marshalling code to deal with structs containing variable length strings as well (string members need to be decorated with CustomMarshalAsAttribute).

    The injector should work on x64 or x86 platforms. It's been tested to work on XP x86, Win 7 x64 as x86 and x64 and Vista x86 (not tested very thoroughly). If UAC is turned on I think it causes some problems, haven't tested that yet. On an x64 machine, compiling the launcher/tester program as Any Cpu will make it an x64 injector - it can only inject into x64 processes, and only inject x64 dlls. Compile as x86 to make it a 32bit injector. The included demo Stub.dll is x86 compiled.

    Comments, criticisms, whatever are appreciated. Source code here: http://dl.getdropbox.com/u/2660220/Injector.rar
    Last edited by adaephon; 10-24-2009 at 09:44 PM.

    C# .NET Dll Injector
  2. #2
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm, nobody is responding.
    So I ll do, thanks for sharing and take my rep

  3. #3
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I'm going to update it in the next day or so with a platform independent one, assuming I can get it working.

  4. #4
    Akk's Avatar Member
    Reputation
    1
    Join Date
    Mar 2008
    Posts
    11
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hm interesting

  5. #5
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very, very clean code.

    Haven't tested it yet (I trust Cypher's code more than yours, no offense ), but I don't see any issues with it.

    Also mind you, compiling as Any CPU means 'Any CPU'. JIT will compile differently depending on the current architecture. If you want to specifically compile for x64 or x86, you need to specifically build for either one. (I'm assuming you're on an x64 PC, hence why it 'only works on x64 when compiled as Any CPU')

    Great job though. I may steal a few things from it

    Edit; I'd rep you, but it seems I can't. Can others confirm? (Hoping it's just a permissions issue :O)

  6. #6
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks apoc no offense taken I generall trust cyphers code more than mine too :-p. As for the any CPU thing I got a version working where I could inject from x64 (ie any CPU) into an x86 process but calling exports with custom structs didn't work due to the pointer rebasing being 8bytes per pointer and I never got round to trying to fix that - would be lots more messy conversion work for questionable gain

  7. #7
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by adaephon View Post
    Thanks apoc no offense taken I generall trust cyphers code more than mine too :-p. As for the any CPU thing I got a version working where I could inject from x64 (ie any CPU) into an x86 process but calling exports with custom structs didn't work due to the pointer rebasing being 8bytes per pointer and I never got round to trying to fix that - would be lots more messy conversion work for questionable gain
    Keep using IntPtr's (they're there for a reason!)

    Just compile specifically for x86 or x64. Don't use AnyCPU since JIT will change, and your code will have issues.

  8. #8
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Haha yeh I know - it was that feature of the CLR I was trying to leverage in an 'academic' exercise to see if I could have a single (x64) process able to inject into x86 and x64 rather than having two compiled versions depending on target.

    Like I said I have a solution that can do the ejection fine, and call an export with no parameters. What it can't do is rebase a custom
    structure with strings like the one posted here does. If that wasn't required, then I had working dll injection from x64 into x86 target

  9. #9
    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)
    Modify your csproj file to target "x86" instead of "AnyCpu", and you won't have to worry about rebasing your pointers. Just use IntPtr's as Apoc suggests, and treat everything as if it's 4 bytes.
    Don't believe everything you think.

  10. #10
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @amadmonk: Yeh, I'm aware of that indeed, when actually using this in other projects that's what I do (or have it loaded by an x86/x64 assembly depending on the situation). However, what I was talking about with the rebasing was purely out of personal interest.

    General information indicated that an x64 process couldn't inject a DLL into an x86 process, and I was interested to find out what the specific limitations were and whether it was possible to actually get around that using a .NET Any Cpu project.

    For those who are interested, I managed to successfully do that. I had an Any Cpu project (running on x64) able to inject an x86 dll into an x86 target process. However, if you have a look at the injector posted here, one of the features I included was the ability to call an export in the remote function passing a struct as a parameter - this functionality I wasn't able to get working (or more to the point, I couldn't be bothered writing all the conversion code that would've been necessary). Despite this, I was still able to inject a DLL into an x86 process from an x64 injector, and call any function that had no parameters (i.e. a function such as void Initialise( void ); )

    But like you and Apoc have both said, for practical use it is much simpler to just force the assembly to be x86 (or x64 depending on application) and assume appropriate native size for IntPtr of 4 bytes. My other exploration was purely out of curiosity, and although it worked the code was hardly elegant.

  11. #11
    adaephon's Avatar Active Member
    Reputation
    76
    Join Date
    May 2009
    Posts
    167
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Apoc out of curiosity what part(s) were you possibly going to steal? I assumed with your onyx project you would already have
    your own solution for injection?

  12. #12
    Apoc's Avatar Angry Penguin
    Reputation
    1388
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by adaephon View Post
    @Apoc out of curiosity what part(s) were you possibly going to steal? I assumed with your onyx project you would already have
    your own solution for injection?
    Exports resolving mostly. And not for use in Onyx either.

  13. #13
    hesha_56's Avatar Private
    Reputation
    1
    Join Date
    Mar 2010
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thank you really helped

  14. #14
    FenixTX2's Avatar Active Member
    Reputation
    23
    Join Date
    Mar 2009
    Posts
    125
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the excellent contribution. I've been looking at your injector library this evening. I've noticed however that whilst using .net 4.0 the following code throws a SEH Exception.
    Code:
                /**
                 * Actual function to find export - loosely modelled off Cypher's idea/code for loading module into this
                 * process to find address. Loads module as data, finds RVA of function and uses to find address in target 
                 * process
                 */
                private IntPtr FindExport(string func)
                {
                    IntPtr hModule = IntPtr.Zero;
                    try
                    {
                        // Load module into local process address space
                        hModule = Imports.LoadLibraryEx(Module.FileName, IntPtr.Zero, LoadLibraryExFlags.DontResolveDllReferences);
                        if (hModule == IntPtr.Zero)
                            throw new Win32Exception(Marshal.GetLastWin32Error());
    
                        // Call GetProcAddress to get the address of the function in the module locally
                        IntPtr pFunc = Imports.GetProcAddress(hModule, func);
                        if (pFunc == IntPtr.Zero)
                            throw new Win32Exception(Marshal.GetLastWin32Error());
    
                        // Get RVA of export and add to base address of injected module
                        // hack at the moment to deal with x64
                        bool x64 = IntPtr.Size == 8;
                        IntPtr pExportAddr;
                        if (x64)
                            pExportAddr = new IntPtr(Module.BaseAddress.ToInt64() + (pFunc.ToInt64() - hModule.ToInt64()));
                        else
                            pExportAddr = new IntPtr(Module.BaseAddress.ToInt32() + (pFunc.ToInt32() - hModule.ToInt32()));
    
                        return pExportAddr;
                    }
                    finally
                    {
                        Imports.CloseHandle(hModule);
                    }
                }


    Looking into a fix at the moment.

  15. #15
    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)
    The fix would probably be (inside the finally block):

    Code:
    if (hModule)
    {
      Imports.FreeLibrary(hModule);
    }
    First off, module handles obtained via LoadLibrary(Ex) should be freed with FreeLibrary, also, you should only call it on a valid (non-zero) handle.

    Note: The above code obviously assumes that you have 'FreeLibrary' in your 'Imports' class.

Page 1 of 2 12 LastLast

Similar Threads

  1. Generic Dll Injector for x86 and x64 + Export Caller
    By Cypher in forum WoW Memory Editing
    Replies: 14
    Last Post: 03-31-2013, 05:45 PM
  2. exit/unload injected .net dll
    By YetiHunter in forum Programming
    Replies: 5
    Last Post: 02-28-2010, 06:57 AM
  3. Destructor's Tutorial: Managed .NET DLL Injection
    By ugkbunb in forum Programming
    Replies: 1
    Last Post: 07-30-2009, 05:15 PM
  4. DLL Injector (x86 + x64, Unicode + MBCS)
    By Cypher in forum WoW Memory Editing
    Replies: 4
    Last Post: 04-23-2009, 02:07 PM
  5. .DLL Injector & Language Hack
    By tehshadow in forum World of Warcraft Bots and Programs
    Replies: 18
    Last Post: 11-07-2006, 10:38 PM
All times are GMT -5. The time now is 03:34 PM. 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