title: Automatically a debug process from C# code and read register values
body: <p>I'm looking for a way to read the edx registry at a certain address like asked in this question: <a href="https://stackoverflow.com/questions/16490906/read-eax-register/">Read eax register</a></p>
  
  <p>Although my solution needs to be in C# and I tried to make it, what I got at this moment is:</p>
  
  <pre><code>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);
          }
      }
  </code></pre>
  
  <p>With a whole lot of Kernel32 methods:</p>
  
  <pre><code>[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);
  </code></pre>
  
  <p>But for some reason it never hits the <code>evt.Exception.ExceptionRecord.ExceptionAddress == address</code></p>
  
  <p>I'm pretty new to memory reading and have a hard time figuring out what is wrong with the code above.</p>
  
  <p>EDIT: Also if I uncomment the <code>context.Dr7 = 0x00000001;</code> the application that I'm trying to read crashes.</p>