C#代码注入
你可以使用Windows钩子或其他方法用c#进行代码注入吗? 我已经看到很多关于代码注入的事情,但所有这些都是用C / C ++完成的。 我不知道这些语言中的任何一种,并且很难翻译。 有没有人对如何做到这一点有任何想法?
凯文,这是有可能的。 您可以使用托管C ++使用window hook proc创建库。 您需要做的就是使用标准WinAPI(SetWindowsHookEx等)将此挂钩注入到某个应用程序中。 在这个钩子里面你可以调用System :: AppDomain :: CurrentDomain-> Load方法将你的程序集加载到目标应用程序的AppDomain中。 然后,您可以使用reflection调用程序集中定义的方法。 例如, Snoop使用此方法。
Mike Stall有这个使用CreateRemoteThread的示例 。 它的优点是不需要任何C ++。
编辑:我似乎误解了这个问题….我的印象是问题是关于代码注入到当前进程中。
我很晚才参加聚会,但几周前我刚刚使用过这个:
委托包含私有字段IntPtr _methodPtr
和IntPtr _methodPtrAux
,它们表示正文的内存地址。 通过将字段(通过reflection)设置为特定值,可以改变EIP将指向的存储器地址。
使用此信息,可以执行以下操作:
- 创建一个包含要执行的汇编字节的数组
- 将委托的方法指针移动到相关字节
- 打电话给代表
- 利润???
(当然,您可以将_methodPtr
更改为任何内存地址 – 即使在内核空间中,但这可能需要适当的执行权限)。
我有一个工作代码示例,如果你想:
public static unsafe int? InjectAndRunX86ASM(this Func 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 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
当然,也可以编写以下方法:
public static unsafe int RunX86ASM(byte[] asm) { Func 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(); } }
可以通过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);
使用任何代码需要您自担风险。 必须使用/unsafe
-compiler开关编译代码示例。
您可以在CodePlex站点http://codeinject.codeplex.com/上查看CInject代码注入.NET程序集。 在使用CInject时,您无需了解代码注入以注入任何代码。