С# Получить EIP адрес памяти

Я пытаюсь найти адрес памяти того, что выполняет указатель инструкций (EIP). У меня есть очень простая программа:

internal class Program
{
    private static void Main(string[] args)
    {
        var sample = new Sample();
        var val = sample.GenericMethod("Nippies");
        Console.ReadLine();
    }
}

public class Sample
{
    public int GenericMethod<T>(T input)
    {
        //How can I get the current memory address
        var currentMemoryAddress = "";
        Console.WriteLine(currentMemoryAddress );
        return 5;
    }
}

TBH Я пытаюсь получить адрес GenericMethod<T>, но общие методы не хранятся в таблицах методов обычным образом, они создаются во время выполнения.
Итак, я решил, что если бы я мог распечатать адрес одного из текущие строки выполняются, я был бы намного ближе к выяснению этого.

Как я могу получить адрес памяти инструкций в определенной строке?


person johnny 5    schedule 14.02.2020    source источник
comment
Я пытаюсь получить адрес GenericMethod<T>, тогда почему бы не задать это, что является вашим фактическим вопросом, а не вопросом X-Y? Или, что еще лучше, вопрос, который объясняет, почему вы (думаете) вам нужен адрес этого универсального метода.   -  person Ian Kemp    schedule 14.02.2020
comment
Отвечает ли это на ваш вопрос? Как напечатать адрес метода в С#?   -  person canton7    schedule 14.02.2020
comment
@IanKemp Изначально я задал вопрос с вознаграждением в на который я не получил ответов. Я решил попробовать другой подход и решил задать этот вопрос, чтобы обучить себя и улучшить свои методы отладки.   -  person johnny 5    schedule 14.02.2020


Ответы (1)


Это делает метод GetNativeOffset stackframe. С несколько неожиданным результатом, что значения для строковых и целочисленных специализаций одинаковы, а для Guid разные.

введите здесь описание изображения

Вот лучший метод, который извлекает фактическое значение регистра EIP. Я нашел биты сборки здесь и скорректировал его для заданного вопроса.

using ByteToFunc;
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace eip
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var vals = Sample.GenericMethod("Nibbles");
            var valg = Sample.GenericMethod(Guid.NewGuid());
            var vali = Sample.GenericMethod(42);
            Console.ReadLine();
        }
    }

    public class Sample
    {
        /* trap values: bad beef is bad food */
        public static int[] EipEspEbpEsiEdiEbxHolder = new[] { 0xBADF00D, 0xBADBEEF, 0xBADF00D, 0xBADBEEF, 0xBADF00D, 0xBADBEEF };

        public static int GenericMethod<T>(T input)
        {
            //How can I get the current memory address
            var subjectAddress = GetAddress(nameof(Sample.SubjectMethod));
            var holderAddress = GetEipEspEbpEsiEdiEbxHolder();
            var captureRegisters = FuncGenerator.Generate<Action<int>, ActionInt>(
                new byte[0].Concat(new byte[]
                {
                    0xE8, 0x1C, 0x00, 0x00, 0x00  // call 28
                })
                .Concat(new byte[]
                {
                    // save EIP, ESP, EBP, ESI, EDI to temp array
                    0x83, 0xC0, 0x1B, // add eax,0x1B (27 bytes)
                    0x89, 0x02,       // mov DWORD PTR [edx],eax
                    0x89, 0x62, 0x04, // mov DWORD PTR [edx+0x4],esp
                    0x89, 0x6A, 0x08, // mov DWORD PTR [edx+0x8],ebp
                    0x89, 0x72, 0x0C, // mov DWORD PTR [edx+0xc],esi
                    0x89, 0x7A, 0x10, // mov DWORD PTR [edx+0x10],edi
                    0x89, 0x5A, 0x14, // mov DWORD PTR [edx+0x14],ebx
                })
                .Concat(new byte[]
                {
                    0xB8, // mov eax
                })
                .Concat(subjectAddress)
                .Concat(new byte[]
                {
                    0xFF, 0xD0 // call eax
                })
                .Concat(new byte[]
                {
                    0xC3 //retn
                })
                .Concat(new byte[]
                {
                    // Helper function for getting EIP as it is inaccessible directly on x86_32
                    0x8B, 0x04, 0x24, // mov eax,DWORD PTR [esp]
                    0xC3 //retn
                })
                .ToArray()
            );

            captureRegisters(holderAddress);
            Console.WriteLine($"EIP = { EipEspEbpEsiEdiEbxHolder[0].ToString("X") }");
            return 5;
        }

        public static int SubjectMethod()
        {
            return 5;
        }

        private static int GetEipEspEbpEsiEdiEbxHolder()
        {
            unsafe
            {
                var typedReference = __makeref(EipEspEbpEsiEdiEbxHolder);
                int* fieldAddress = (int*)*(int*)*(int*)&typedReference;
                return (int)fieldAddress + 8;
            }
        }

        private static byte[] GetAddress(string name)
        {
            return BitConverter.GetBytes((int)GetRawAddress(name)).ToArray();
        }

        private static IntPtr GetRawAddress(string name)
        {
            var methodHandle = typeof(Sample).GetMethod(name, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).MethodHandle;
            RuntimeHelpers.PrepareMethod(methodHandle);
            return methodHandle.GetFunctionPointer();
        }
    }
}

Для компиляции и запуска вы можете использовать простой консольный проект и добавить класс FuncGenerator от afish отсюда: ://gist.github.com/afish/8fd6cf8f8c196901b5e1a5ee1000ee68

Результат: три разных значения EIP, чего и следовало ожидать.

введите здесь описание изображения

person Cee McSharpface    schedule 14.02.2020
comment
Спасибо, я думаю, что это поможет, но просто для уточнения, получает ли это текущую строку? или это получает адрес памяти метода (из кадра стека) - person johnny 5; 14.02.2020
comment
насколько я вижу, он получает бессмысленное смещение. Я искал способ получить то же значение EIP, которое будет отображаться на панели разборки отладчика Visual Studio, и нашел кое-что - ожидание редактирования. - person Cee McSharpface; 14.02.2020
comment
Спасибо, это было бы большим подспорьем! - person johnny 5; 14.02.2020
comment
Вау, спасибо за редактуру, очень тщательно - person johnny 5; 14.02.2020