Question

Can you use windows hooks or other methods to do code injection with c#? I've seen lots of things about code injection but all of them are done in C/C++. I don't know either of those languages and have a really hard time translating. Does anyone have any ideas on how to do this?

Was it helpful?

Solution

Kevin, it is possible. You can create library with window hook proc using managed C++. All you need to do is to inject this hook into some application using standard WinAPI (SetWindowsHookEx etc.). Inside this hook you can call System::AppDomain::CurrentDomain->Load method to load your assembly into target application's AppDomain. Then you can call methods defined in your assembly using reflection. For example, Snoop uses this method.

OTHER TIPS

Mike Stall has this sample, that uses CreateRemoteThread. It has the advantage of not requiring any C++.

EDIT: I seem to have misinterpreted the question .... I was under the impression that the question was about code injection into the current process.


I am joining the party rather late, but I have just used exactly this a few weeks ago:

A delegate contains the private fields IntPtr _methodPtr and IntPtr _methodPtrAux, which represent the body's memory address. By setting the field (via reflection) to specific values, one can alter the memory address, to which the EIP will be pointing.
Using this information, one can do the following:

  1. Create an array with assembly bytes, which are to be executed
  2. Move the delegate's method pointer to the bytes in question
  3. Call the delegate
  4. Profit ???

(Of course, you can change the _methodPtr-value to any memory address -- even in the kernel space, but this might require appropriate execution privileges).


I have a working code example here, if you want:

public static unsafe int? InjectAndRunX86ASM(this Func<int> del, byte[] asm)
{
    if (del != null)
        fixed (byte* ptr = &asm[0])
        {
            FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
            FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);

            _methodPtr.SetValue(del, ptr);
            _methodPtrAux.SetValue(del, ptr);

            return del();
        }
    else
        return null;
}

Which can be used as follows:

Func<int> del = () => 0;
byte[] asm_bytes = new byte[] { 0xb8, 0x15, 0x03, 0x00, 0x00, 0xbb, 0x42, 0x00, 0x00, 0x00, 0x03, 0xc3 };
// mov eax, 315h
// mov ebx, 42h
// add eax, ebx
// ret

int res = del.InjectAndRunX86ASM(asm_bytes); // should be 789 + 66 = 855

Of course, on could also write the following method:

public static unsafe int RunX86ASM(byte[] asm)
{
    Func<int> del = () => 0; // create a delegate variable
    Array.Resize(ref asm, asm.Length + 1);

    // add a return instruction at the end to prevent any memory leaks
    asm[asm.Length - 1] = 0xC3;

    fixed (byte* ptr = &asm[0])
    {
        FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
        FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);

        _methodPtr.SetValue(del, ptr);
        _methodPtrAux.SetValue(del, ptr);

        return del();
    }
}

The same could probably be done to existing methods (not delegates) via reflection:

// UNTESTED //

Action new_method_body = () => { };
MethodInfo nfo = typeof(MyType).GetMethod( ..... );
IntPtr ptr = nfo.MethodHandle.Value; // ptr is a pointer to the method in question

InjectX86ASM(new_method_body, new byte[] { ......., 0xC3 }); // assembly bytes to be injected

int target = new_method_body.Method.MethodHandle.Value.ToInt32();

byte[] redirector = new byte[] {
    0xE8,   // CALL INSTRUCTION + TARGET ADDRESS IN LITTLE ENDIAN
    (byte)(target & 0xff),
    (byte)((target >> 8) & 0xff),
    (byte)((target >> 16) & 0xff),
    (byte)((target >> 24) & 0xff),
    0xC3,   // RETURN INSTRUCTION
};
Marshal.Copy(redirector, 0, ptr, redirector.Length);


Use any code at your own risk. The code examples must be compiled with the /unsafe-compiler switch.

You can check out CInject for code injection into .NET assemblies at CodePlex site http://codeinject.codeplex.com/. You don't need to have any knowledge about code injection to inject any code when you are using CInject.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top