可以使用windows hooks或者其他方法用c#进行代码注入吗?我见过很多关于代码注入的东西,但它们都是用 C/C++ 完成的。我不懂这些语言,翻译起来非常困难。有人对如何做到这一点有任何想法吗?

有帮助吗?

解决方案

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

其他提示

迈克·斯托尔有 这个样本, ,使用 CreateRemoteThread。它的优点是不需要任何 C++。

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


我加入聚会的时间相当晚,但几周前我刚刚使用过这个:

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

  1. 创建一个包含要执行的汇编字节的数组
  2. 将委托的方法指针移动到有问题的字节
  3. 致电代表
  4. 利润 ???

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


我这里有一个工作代码示例,如果您愿意的话:

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;
}

可以如下使用:

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

当然,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();
    }
}

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

// 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-编译器开关.

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top