是否可以在C#中执行x86汇编序列?

时间:2009-06-06 05:48:52

标签: c# assembly

继续我的逆向工程教育我经常希望能够复制部分x86汇编代码,并从我选择的高级语言中调用它进行测试。

有没有人知道从C#方法中调用x86指令序列的方法?我知道这可以使用C ++完成,但我很好奇是否可以在C#中完成?

注意:我不是在谈论执行MSIL指令。我正在谈论执行一系列原始x86汇编指令。

5 个答案:

答案 0 :(得分:42)

只是为了反驳Brian的说法,重写代码来自leppie的回答link

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

答案 1 :(得分:3)

是的,请参阅我的详细答案here
主要部分是:(没有任何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;
}

可以使用如下:

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

答案 2 :(得分:0)

我相信,您可以向您的解决方案添加托管C ++项目,并使用asm指令公开方法。您可以从任何.Net项目(不仅仅是C#)引用该项目,因此您可以从那里调用该方法。

答案 3 :(得分:0)

只需在winapi函数上使用P / Invoke。

WriteProcessMemory或找到指向缓冲区的指针。 启用页面上的执行位(不记得此功能)。

指针上的CreateThread。 WaitForObject(如果您希望它是单线程的)。

答案 4 :(得分:-1)

不,但你可以用C ++编写程序集并从C#中调用它。请参阅this example