继续我的逆向工程教育我经常希望能够复制部分x86汇编代码并从我选择的高级语言中调用它进行测试.
有没有人知道从C#方法中调用x86指令序列的方法?我知道这可以使用C++完成,但我很好奇是否可以在C#中完成?
注意:我不是在谈论执行MSIL指令.我在谈论执行一系列原始x86汇编指令.
oku*_*ane 45
只是为了反驳Brian的说法,从leppie的回答链接重写了代码:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace DynamicX86
{
class Program
{
const uint PAGE_EXECUTE_READWRITE = 0x40;
const uint MEM_COMMIT = 0x1000;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
private delegate int IntReturner();
static void Main(string[] args)
{
List<byte> bodyBuilder = new List<byte>();
bodyBuilder.Add(0xb8);
bodyBuilder.AddRange(BitConverter.GetBytes(42));
bodyBuilder.Add(0xc3);
byte[] body = bodyBuilder.ToArray();
IntPtr buf = VirtualAlloc(IntPtr.Zero, (uint)body.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(body, 0, buf, body.Length);
IntReturner ptr = (IntReturner)Marshal.GetDelegateForFunctionPointer(buf, typeof(IntReturner));
Console.WriteLine(ptr());
}
}
}
Run Code Online (Sandbox Code Playgroud)
是的,请参阅我的详细答案这里
主要部分是:(没有任何P/Invoke或外部参考)
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;
}
Run Code Online (Sandbox Code Playgroud)
可以如下使用:
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
Run Code Online (Sandbox Code Playgroud)
编辑:最新版本的 C# (C#9) 引入了“委托指针”的概念,它允许您执行以下操作:
byte[] asm = {
0x8D, 0x04, 0x11, // lea eax, [rcx+rdx]
0xC3 // ret
};
void* buffer = VirtualAlloc(null, asm.Length, 0x1000, 4);
var func = (delegate*<int, int, int>)buffer;
int dummy;
Marshal.Copy(asm, 0, (nint)buffer, asm.Length);
VirtualProtect(buffer, asm.Length, 0x20, &dummy);
Console.WriteLine(func(42, 378)); // call 'func' with (42, 378), which computes '420'
VirtualFree(buffer, 0, 0x8000);
Run Code Online (Sandbox Code Playgroud)
您可以在这里找到完整的示例:https://gist.github.com/Unknown6656/a42a810d4283208c3c21c632fb16c3f9