I am looking for a way to read the edx registry at a specific address, for example, given in this question: Read eax register
Although my solution should be in C #, and I tried to do this, what I got at the moment is:
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 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); } }
With a lot of Kernel32 methods:
[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;
But for some reason it never gets into evt.Exception.ExceptionRecord.ExceptionAddress == address
I am new to reading memory and have difficulty figuring out what is wrong with the code above.
EDIT: Also, if I uncomment context.Dr7 = 0x00000001; The application I'm trying to read is crashing.