C#代码注入

C#代码注入

Code Injection With C#

可以使用Windows挂钩或其他方法通过c#进行代码注入吗? 我已经看到了很多有关代码注入的内容,但是所有这些都是在C / C ++中完成的。 我不知道这些语言中的任何一种,而且翻译时很难。 有人对如何执行此操作有任何想法吗?


凯文
有可能的。您可以使用托管C ++使用窗口挂钩proc创建库。您需要做的就是使用标准WinAPI(SetWindowsHookEx等)将此钩子注入到某些应用程序中。在此挂钩内,您可以调用System :: AppDomain :: CurrentDomain-> Load方法将程序集加载到目标应用程序的AppDomain中。然后,您可以使用反射调用程序集中定义的方法。例如,Snoop使用此方法。


编辑:我似乎误解了这个问题....我给人的印象是,问题是关于将代码注入当前进程的。


我参加晚会很晚,但几周前我刚使用了这个:

委托包含专用字段IntPtr _methodPtrIntPtr _methodPtrAux,它们表示正文的内存地址。通过将字段(通过反射)设置为特定值,可以更改EIP指向的内存地址。

使用此信息,可以执行以下操作:

  • 创建一个带有要执行的汇编字节的数组
  • 将委托的方法指针移到有问题的字节
  • 致电代表
  • 利润???
  • (当然,即使在内核空间中,您也可以将_methodPtr -value更改为任何内存地址,但这可能需要适当的执行特权)。


    如果需要,我在这里有一个工作代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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;
    }

    可以如下使用:

    1
    2
    3
    4
    5
    6
    7
    8
    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

    当然,上还可以编写以下方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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();
        }
    }

    可以通过反射对现有方法(非委托)执行相同的操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 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);


    使用任何代码后果自负。该代码示例必须使用/unsafe -compiler开关进行编译。


    Mike Stall有此示例,该示例使用CreateRemoteThread。它的优点是不需要任何C ++。


    您可以在CodePlex网站http://codeinject.codeplex.com/上检出CInject以将代码注入到.NET程序集中。使用CInject时,不需要任何有关代码注入的知识即可注入任何代码。


    推荐阅读