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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/959087/
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-06 04:16:40  来源:igfitidea点击:

Is it possible to execute an x86 assembly sequence from within C#?

c#assembly

提问by mmcdole

Continuing my reverse engineering education I've often wanted to be able to copy portions of x86 assembly code and call it from a high level language of my choice for testing.

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

Does anyone know of a method of calling a sequence of x86 instructions from within a C# method? I know that this can be done using C++ but I'm curious if it can be done in C#?

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

Note: I'm not talking about executing MSIL instructions. I'm talking about executing a series of raw x86 assembly instructions.

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

采纳答案by okutane

Just to counter Brian's claim, rewritten code from leppie's answer link:

只是为了反驳布赖恩的说法,从 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());
        }
    }
}

回答by okutane

I believe, you can add a managed C++ project to your solution and expose method with usage of asm instructions. You can reference that project from any .Net project (not just C#), so you can call that method from there.

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

回答by Brian

No, but you can write assembly in C++ and call it from C#. See this example.

不,但您可以用 C++ 编写程序集并从 C# 调用它。请参阅此示例

回答by Unknown

Yes.

是的。

Just use P/Invoke on winapi functions.

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

WriteProcessMemory or find the pointer to your buffer. Enable the execute bit on page (don't remember the function for this).

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

CreateThread on the pointer. WaitForObject (if you want it to be single threaded).

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

回答by unknown6656

Yes, see my detailed answer here
The main part is: (Without any P/Invoke or external reference)

是的,请在此处查看我的详细答案
主要部分是:(没有任何 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;
}

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