使用 C# 进行代码注入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 09:13:04  来源:igfitidea点击:

Code Injection With C#

提问by The.Anti.9

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?

可以用windows hooks或者其他方法用c#做代码注入吗?我见过很多关于代码注入的事情,但所有这些都是用 C/C++ 完成的。我不会这两种语言中的任何一种,而且翻译起来真的很困难。有没有人对如何做到这一点有任何想法?

采纳答案by aku

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, Snoopuses this method.

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

回答by Sam Saffron

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

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

回答by Puneet Ghanshani

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.

您可以在 CodePlex 站点http://codeinject.codeplex.com/ 上查看 CInject 以将代码注入到 .NET 程序集中。使用 CInject 时,您无需了解代码注入知识即可注入任何代码。

回答by unknown6656

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 _methodPtrand 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:

委托包含私有字段IntPtr _methodPtrIntPtr _methodPtrAux,代表主体的内存地址。通过将字段(通过反射)设置为特定值,可以更改 EIP 将指向的内存地址。
使用此信息,您可以执行以下操作:

  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 ???
  1. 创建一个包含要执行的程序集字节的数组
  2. 将委托的方法指针移动到相关字节
  3. 打电话给代表
  4. 利润 ???

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

(当然,您可以将_methodPtr-value更改为任何内存地址——即使在内核空间中,但这可能需要适当的执行权限)。



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

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:

当然,on也可以写如下方法:

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.使用任何代码风险自负。代码示例必须使用/unsafe-compiler switch/unsafe-编译器开关