-1

I'm trying to find the memory address of what the (EIP) Instruction Pointer is executing. I have a very simple program:

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 I'm trying to obtain the address of the GenericMethod<T> but generic methods aren't stored conventionally in the method tables, they're built at runtime.
So I figured I if I could print out the address of one of the current lines being executed I would be a lot closer to figuring it out.

How can I obtain the memory address of the instructions at a specific line?

johnny 5
  • 19,893
  • 50
  • 121
  • 195
  • "I'm trying to obtain the address of the `GenericMethod`" then why not ask **that**, which is your actual question, instead of an X-Y question? Or even better, a question that explains why you (think) you need the address of that generic method. – Ian Kemp Feb 14 '20 at 16:06
  • Does this answer your question? [How to print Address of a method in c#?](https://stackoverflow.com/questions/25464493/how-to-print-address-of-a-method-in-c) – canton7 Feb 14 '20 at 16:15
  • @IanKemp I originally asked a [question](https://stackoverflow.com/questions/59778004/memory-violation-dynamically-appending-to-methods-at-runtime) with a bounty, in which I've received no replies. I decided to try a different approach, and I figured I'd ask this question to educate myself and improve my debugging techniques – johnny 5 Feb 14 '20 at 16:23

1 Answers1

1

The GetNativeOffset method of stackframe does it. With the somewhat surprising result that values for string and integer specializations are the same, and different for Guid.

enter image description here

Here is a better method, which retrieves the actual EIP register value. I found the assembly bits here, and adjusted it for the question at hand.

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

To compile and run, you can use a simple Console project, and add the FuncGenerator class by afish from here: https://gist.github.com/afish/8fd6cf8f8c196901b5e1a5ee1000ee68

Result: three different values for EIP, which should be expected.

enter image description here

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
  • Thanks, I think this will do the trick, but just for clarification purposes, Does this get the current line? or does this get the memory address of the method (from the stack frame) – johnny 5 Feb 14 '20 at 16:27
  • 1
    as far as I can see it gets a meaningless offset. I searched for a way to get the same EIP value that the visual studio debugger's disassembly pane would show, and found something - edit pending. – Cee McSharpface Feb 14 '20 at 17:19
  • Thanks that would be a great help! – johnny 5 Feb 14 '20 at 17:25
  • Wow thanks for the edit, very thorough – johnny 5 Feb 14 '20 at 18:35