C# - Hardware breakpoint not working properly menu

Shout-Out

User Tag List

Results 1 to 2 of 2
  1. #1
    Pwnmanship's Avatar Member
    Reputation
    1
    Join Date
    Mar 2015
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    C# - Hardware breakpoint not working properly

    I'm looking for a way to read the edx registry at a certain address with a hardware debugger.
    The breakpoint needs to stay while the application is running and needs to keep returning the edx value.

    I've the following code (which isn't working for some reason)

    Code:
        public static IntPtr GetEdx(IntPtr address, Process process)
            {
                const int DBG_EXCEPTION_NOT_HANDLED = unchecked((int)0x80010001);
                const int EXCEPTION_SINGLE_STEP = unchecked((int)0x80000004);
    
                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 ctx = new CONTEXT();
                ctx.ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_DEBUG_REGISTERS | (uint)CONTEXT_FLAGS.CONTEXT_INTEGER;
                ctx.Dr0 = (uint)address;
                ctx.Dr7 = 0x00000001;
    
                SetThreadContext((IntPtr)process.Id, ref ctx); // hThread with enough permissions
    
                while (true)
                {
                    if (!WaitForDebugEvent(out evt, -1))
                        throw new Win32Exception();
    
                    if (evt.dwDebugEventCode == (uint)DebugEventType.EXCEPTION_DEBUG_EVENT && evt.Exception.ExceptionRecord.ExceptionCode ==  EXCEPTION_SINGLE_STEP)
                    {
                        if (evt.Exception.ExceptionRecord.ExceptionAddress == address)
                        {
                            GetThreadContext((IntPtr)process.Id, ref ctx);
                            return (IntPtr)ctx.Edx; // eax get
                        }
                    }
    
                    ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
                }
            }
    With a whole lot of Kernel32 methods:

    Code:
        [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, int 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;
        }
    But for some reason it never hits the `evt.Exception.ExceptionRecord.ExceptionAddress == address`

    I'm pretty new to memory reading and have a hard time figuring out what is wrong with the code above.

    C# - Hardware breakpoint not working properly
  2. #2
    enaf3n's Avatar Elite User i like game security stuff CoreCoins Purchaser
    Reputation
    496
    Join Date
    Nov 2013
    Posts
    356
    Thanks G/R
    26/353
    Trade Feedback
    0 (0%)
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    So you mention the address it is breaking on is not what you're expecting, but does that mean it is still throwing EXCEPTION_SINGLE_STEP like you are expecting?

    Something else to keep in mind is that you have to modify the context of the thread that actually runs the code you're hooking. In many games and applications, there are multiple threads, not all of which ever end up running the desired code. You can modify the context of all threads using CreateToolhelp32Snapshot with the TH32CS_SNAPTHREAD flag. You can then iterate through the threads in the snapshot, finding the ones that belong to your target process, and open them with OpenThread. Then you should modify each of the process's threads with SetThreadContext to administer your hook.

    It's also worth noting that before changing the context of any running thread, you should suspend it with SuspendThread, or you can get undefined behavior.

Similar Threads

  1. [ArcEmu] Custom Weapon - Not Working Properly?
    By ProphetWoW in forum WoW EMU Questions & Requests
    Replies: 5
    Last Post: 08-27-2010, 09:50 PM
  2. [ArcEmu] Creatures in Instances do not work properly
    By renfer in forum WoW EMU Questions & Requests
    Replies: 5
    Last Post: 04-11-2010, 11:48 PM
  3. Arrows/Projectiles not working properly HELP PLZ
    By BillyBob31 in forum World of Warcraft Emulator Servers
    Replies: 2
    Last Post: 03-13-2008, 07:49 AM
  4. itemcache not working properly
    By nasda in forum WoW ME Questions and Requests
    Replies: 4
    Last Post: 01-12-2008, 02:12 AM
  5. New thread not working properly?
    By Linkitch in forum Suggestions
    Replies: 8
    Last Post: 01-06-2007, 12:07 AM
All times are GMT -5. The time now is 10:49 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search