Автоматически процесс отладки из кода C # и чтения значений регистра

Я ищу способ прочитать реестр edx по определенному адресу, как задано в этом вопросе:Чтение регистра eax

Хотя мое решение должно быть в C #, и я попытался сделать это, то, что я получил в этот момент:

public static IntPtr GetEdx(IntPtr address, Process process)
    {
        const uint DBG_EXCEPTION_NOT_HANDLED = 0x80010001;
        const uint EXCEPTION_SINGLE_STEP = 0x80000004;
        const int DBG_CONTINUE = 0x00010002; // Seems to work better than DBG_EXCEPTION_NOT_HANDLED

        //DebugSetProcessKillOnExit(0);
        DEBUG_EVENT evt = new DEBUG_EVENT();
        // Attach to the process we provided the thread as an argument
        if (!DebugActiveProcess(process.Id))
            throw new Win32Exception();

        CONTEXT context = new CONTEXT();

        foreach (ProcessThread thread in process.Threads)
        {
            uint iThreadId = (uint)thread.Id;
            IntPtr hThread =
                OpenThread(
                    ThreadAccessFlags.SUSPEND_RESUME | ThreadAccessFlags.SET_CONTEXT |
                    ThreadAccessFlags.GET_CONTEXT, false, iThreadId);

            // Suspent the thread
            if (SuspendThread(hThread) == -1) throw new ApplicationException("Cannot suspend thread.");

            context = new CONTEXT
            {
                ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS |
                               (uint)CONTEXT_FLAGS.CONTEXT_INTEGER
            };

            // Get the context
            if (!GetThreadContext(hThread, ref context))
                throw new Win32Exception();

            // Change the context

            context.Dr0 = (uint)address;
            context.Dr7 = 0x00000001;

            // Set the changed context back
            if (!SetThreadContext(hThread, ref context))
                throw new Win32Exception();

            // Check if setting the context give any errors
            var error = Marshal.GetLastWin32Error();
            if (error != 0)
            {
                throw new ApplicationException("Error is setting context.");
            }

            // Resume the thread
            if (ResumeThread(hThread) == -1) throw new ApplicationException("Cannot resume thread.");
        }

        while (true)
        {
            if (!WaitForDebugEvent(out evt, -1))
                throw new Win32Exception();

            // Multiple if's for easier debugging at this moment
            if (evt.dwDebugEventCode == (uint)DebugEventType.EXCEPTION_DEBUG_EVENT)
            {
                if (evt.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
                {
                    if (evt.Exception.ExceptionRecord.ExceptionAddress == address)
                    {
                        context = new CONTEXT
                        {
                            ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS |
                                           (uint)CONTEXT_FLAGS.CONTEXT_INTEGER
                        };
                        GetThreadContext((IntPtr)evt.dwThreadId, ref context);
                        return (IntPtr)context.Ebx; // ebx get
                    }
                }
            }

            ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, DBG_CONTINUE);//DBG_EXCEPTION_NOT_HANDLED);
        }
    }

С большим количеством методов Kernel32:

[DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    public static extern IntPtr OpenThread(ThreadAccessFlags dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("Kernel32.dll", SetLastError = true)]
    static extern bool DebugActiveProcess(int dwProcessId);
    [DllImport("Kernel32.dll", SetLastError = true)]
    static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds);
    [DllImport("Kernel32.dll", SetLastError = true)]
    static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, uint dwContinueStatus);
    [DllImport("Kernel32.dll", SetLastError = true)]
    public static extern bool IsDebuggerPresent();
    [DllImport("kernel32.dll")]
    private static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
    [DllImport("kernel32.dll")]
    public static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext);

    [StructLayout(LayoutKind.Sequential)]
    public unsafe struct DEBUG_EVENT
    {
        public readonly uint dwDebugEventCode;
        public readonly int dwProcessId;
        public readonly int dwThreadId;


        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 86, ArraySubType = UnmanagedType.U1)]
        private readonly byte[] debugInfo;


        public EXCEPTION_DEBUG_INFO Exception
        {
            get
            {
                if (debugInfo == null)
                    return new EXCEPTION_DEBUG_INFO();


                fixed (byte* ptr = debugInfo)
                {
                    return *(EXCEPTION_DEBUG_INFO*)ptr;
                }
            }
        }


        public LOAD_DLL_DEBUG_INFO LoadDll
        {
            get
            {
                if (debugInfo == null)
                    return new LOAD_DLL_DEBUG_INFO();


                fixed (byte* ptr = debugInfo)
                {
                    return *(LOAD_DLL_DEBUG_INFO*)ptr;
                }
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LOAD_DLL_DEBUG_INFO
    {
        public readonly IntPtr hFile;
        public readonly IntPtr lpBaseOfDll;
        public readonly uint dwDebugInfoFileOffset;
        public readonly uint nDebugInfoSize;
        public readonly IntPtr lpImageName;
        public readonly ushort fUnicode;
    }


    [StructLayout(LayoutKind.Sequential)]
    public struct EXCEPTION_DEBUG_INFO
    {
        public EXCEPTION_RECORD ExceptionRecord;
        public readonly uint dwFirstChance;
    }


    [StructLayout(LayoutKind.Sequential)]
    public struct EXCEPTION_RECORD
    {
        public readonly uint ExceptionCode;
        public readonly uint ExceptionFlags;
        public readonly IntPtr ExceptionRecord;
        public readonly IntPtr ExceptionAddress;
        public readonly uint NumberParameters;


        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15, ArraySubType = UnmanagedType.U4)]
        //public readonly uint[] ExceptionInformation;


        public unsafe fixed uint ExceptionInformation[15];
    }


    public enum DebugEventType : int
    {
        CREATE_PROCESS_DEBUG_EVENT = 3, //Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure.
        CREATE_THREAD_DEBUG_EVENT = 2, //Reports a create-thread debugging event. The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure.
        EXCEPTION_DEBUG_EVENT = 1, //Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure.
        EXIT_PROCESS_DEBUG_EVENT = 5, //Reports an exit-process debugging event. The value of u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure.
        EXIT_THREAD_DEBUG_EVENT = 4, //Reports an exit-thread debugging event. The value of u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure.
        LOAD_DLL_DEBUG_EVENT = 6, //Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure.
        OUTPUT_DEBUG_STRING_EVENT = 8, //Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure.
        RIP_EVENT = 9, //Reports a RIP-debugging event (system debugging error). The value of u.RipInfo specifies a RIP_INFO structure.
        UNLOAD_DLL_DEBUG_EVENT = 7, //Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure.
    }

    [StructLayout,(LayoutKind.Sequential)]
    public struct CONTEXT
    {
        public uint ContextFlags;
        public uint Dr0;
        public uint Dr1;
        public uint Dr2;
        public uint Dr3;
        public uint Dr6;
        public uint Dr7;
        public FLOATING_SAVE_AREA FloatSave;
        public uint SegGs;
        public uint SegFs;
        public uint SegEs;
        public uint SegDs;
        public uint Edi;
        public uint Esi;
        public uint Ebx;
        public uint Edx;
        public uint Ecx;
        public uint Eax;
        public uint Ebp;
        public uint Eip;
        public uint SegCs;
        public uint EFlags;
        public uint Esp;
        public uint SegSs;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] ExtendedRegisters;
    }

    public enum CONTEXT_FLAGS : uint
    {
        CONTEXT_i386 = 0x10000,
        CONTEXT_i486 = 0x10000,
        CONTEXT_CONTROL = CONTEXT_i386 | 0x01,
        CONTEXT_INTEGER = CONTEXT_i386 | 0x02,
        CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04,
        CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08,
        CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10,
        CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20,
        CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS,
        CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS
    }

    [Flags]
    public enum ThreadAccessFlags : int
    {
        TERMINATE = 0x0001,
        SUSPEND_RESUME = 0x0002,
        GET_CONTEXT = 0x0008,
        SET_CONTEXT = 0x0010,
        SET_INFORMATION = 0x0020,
        QUERY_INFORMATION = 0x0040,
        SET_THREAD_TOKEN = 0x0080,
        IMPERSONATE = 0x0100,
        DIRECT_IMPERSONATION = 0x0200
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct FLOATING_SAVE_AREA
    {
        public uint ControlWord;
        public uint StatusWord;
        public uint TagWord;
        public uint ErrorOffset;
        public uint ErrorSelector;
        public uint DataOffset;
        public uint DataSelector;

        // missing some stuff
        public uint Cr0NpxState;
    }

    [DllImport("kernel32.dll")]
    private static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);

    [DllImport("kernel32.dll")]
    public static extern bool ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, byte[] buffer, int size,
        int lpNumberOfBytesRead);

Но по какой-то причине это никогда не поражаетevt.Exception.ExceptionRecord.ExceptionAddress == address

Я довольно новичок в чтении памяти, и мне трудно понять, что не так с кодом выше.

РЕДАКТИРОВАТЬ: Также, если я раскомментируюcontext.Dr7 = 0x00000001; приложение, которое я пытаюсь прочитать, вылетает.

Ответы на вопрос(0)

Ваш ответ на вопрос