Можно ли выполнить последовательность сборки x86 из C #? - PullRequest
25 голосов
/ 06 июня 2009

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

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

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

Ответы [ 5 ]

42 голосов
/ 06 июня 2009

Просто чтобы противостоять заявлению Брайана, переписайте код из ответа Леппи ссылка :

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());
        }
    }
}
3 голосов
/ 21 сентября 2016

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

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

0 голосов
/ 06 июня 2009

Да.

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

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

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

0 голосов
/ 06 июня 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...