Возможно ли выполнить последовательность сборки x86 из С#?

Продолжая мое обратное инженерное образование, я часто хотел иметь возможность копировать часть ассемблерного кода x86 и вызывать его с языка высокого уровня по своему выбору для тестирования.

Кто-нибудь знает о способе вызова последовательности инструкций x86 из метода С#? Я знаю, что это можно сделать с помощью С++, но мне любопытно, можно ли это сделать на С#?

Примечание. Я не говорю о выполнении инструкций MSIL. Я говорю о выполнении ряда инструкций сборки raw x86.

Ответ 1

Просто чтобы ответить на требование Брайана, переписан код из ответа 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());
        }
    }
}

Ответ 2

Да, см. мой подробный ответ здесь
Основная часть: (без каких-либо 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

Ответ 3

Я полагаю, вы можете добавить управляемый проект на С++ в свое решение и выставить метод с использованием инструкций asm. Вы можете ссылаться на этот проект из любого проекта .Net(а не только на С#), поэтому вы можете вызвать этот метод оттуда.

Ответ 4

Да.

Просто используйте P/Invoke для функций winapi.

WriteProcessMemory или найдите указатель на свой буфер. Включите бит выполнения на странице (не помните эту функцию).

CreateThread на указателе. WaitForObject (если вы хотите, чтобы он был однопоточным).

Ответ 5

Нет, но вы можете написать сборку на С++ и вызвать ее из С#. См. этот пример.