Debug for cheat program

Posts 12 of 2 · Page 1 of 1
Debug for cheat program
Hi, here a source code to use a debugger to get any pointers in a game.

you can modify it and repost it here to share with us.
eg insert any unsafe methods to read and write in memory without use the Read/WriteMemory api
eg bypass any shield programs (GG, ...)

Please post here yours contributions :-)


here a using example:

Code:
private static uint addr_coords = 0;
public static void patch_coords(Process process,ref Int3.CONTEXT context)
{
    addr_coords = context.Eax;

   // we can do a jmp to a new adress if we want to simule a jne,je, ...
   context.Eip = 0x057A487C;
}

Process P = xxxx;
Int3.DetachProcess();
if (Int3.AttachProcess(P))
{
     byte[] buffer = { 0x8b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xf8, 0x8b, 0xcf, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x08, 0x89, 0x4e, 0x04, 0x8b, 0x50, 0x04, 0x83 };
     uint trouve = Pattern.FindPattern((Process)P, 0x00400000, 0x17fffff, buffer, "xx????x????xxxxx????xxxxxxxxx"); // extern source code
     if (trouve != 0)
    {
          //  coords = name of breakpoint
          //  trouve + 20 = breakpoint here
          // 2 = size of original instruction
          // INT3_VOLATILE = restore the original code after the first breakpoint
          Int3.AddBreakpoint("coords", trouve + 20, 2, Int3.BREAKPOINT_FLAGS.INT3_VOLATILE, new Int3.Callback(patch_coords));
    }
}

SOURCE CODE:
Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace Tools
{
    


    public static class Int3
    {
        public delegate void Callback(Process process, ref CONTEXT context);

        [Flags]
        private enum AllocationType
        {
            Commit = 0x1000,
            Reserve = 0x2000,
            Decommit = 0x4000,
            Release = 0x8000,
            Reset = 0x80000,
            Physical = 0x400000,
            TopDown = 0x100000,
            WriteWatch = 0x200000,
            LargePages = 0x20000000
        }

        [Flags]
        private enum MemoryProtection
        {
            Execute = 0x10,
            ExecuteRead = 0x20,
            ExecuteReadWrite = 0x40,
            ExecuteWriteCopy = 0x80,
            NoAccess = 0x01,
            ReadOnly = 0x02,
            ReadWrite = 0x04,
            WriteCopy = 0x08,
            GuardModifierflag = 0x100,
            NoCacheModifierflag = 0x200,
            WriteCombineModifierflag = 0x400
        }

        [Flags]
        private enum FreeType
        {
            Decommit = 0x4000,
            Release = 0x8000,
        }

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FreeType dwFreeType);

        private enum ThreadAccess : 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)
        }
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
        [DllImport("kernel32.dll")]
        static extern uint SuspendThread(IntPtr hThread);
        [DllImport("kernel32.dll")]
        static extern int ResumeThread(IntPtr hThread);

        [Flags]
        private enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }
        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, UIntPtr dwSize);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hProcess);


        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DebugActiveProcessStop([In] int Pid);
        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern bool DebugActiveProcess(int dwProcessId);
        

        [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;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
            public byte[] RegisterArea;
            public uint Cr0NpxState;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct CONTEXT
        {
            public uint ContextFlags; //set this to an appropriate value 
            // Retrieved by CONTEXT_DEBUG_REGISTERS 
            public uint Dr0;
            public uint Dr1;
            public uint Dr2;
            public uint Dr3;
            public uint Dr6;
            public uint Dr7;
            // Retrieved by CONTEXT_FLOATING_POINT 
            public FLOATING_SAVE_AREA FloatSave;
            // Retrieved by CONTEXT_SEGMENTS 
            public uint SegGs;
            public uint SegFs;
            public uint SegEs;
            public uint SegDs;
            // Retrieved by CONTEXT_INTEGER 
            public uint Edi;
            public uint Esi;
            public uint Ebx;
            public uint Edx;
            public uint Ecx;
            public uint Eax;
            // Retrieved by CONTEXT_CONTROL 
            public uint Ebp;
            public uint Eip;
            public uint SegCs;
            public uint EFlags;
            public uint Esp;
            public uint SegSs;
            // Retrieved by CONTEXT_EXTENDED_REGISTERS 
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] ExtendedRegisters;
        }
        [DllImport("kernel32.dll")]
        static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
        [DllImport("kernel32.dll")]
        public static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext);

        

        public enum CONTEXT_FLAGS : uint
        {
            CONTEXT_i386 = 0x10000,
            CONTEXT_i486 = 0x10000,   //  same as i386
            CONTEXT_CONTROL = CONTEXT_i386 | 0x01, // SS:SP, CS:IP, FLAGS, BP
            CONTEXT_INTEGER = CONTEXT_i386 | 0x02, // AX, BX, CX, DX, SI, DI
            CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, // DS, ES, FS, GS
            CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, // 387 state
            CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, // DB 0-3,6,7
            CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, // cpu specific extensions
            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
        }

        private enum ExceptionFlags
        {
            EXCEPTION_CONTINUABLE = 0,
            EXCEPTION_NONCONTINUABLE = 1
        }

        private enum ExceptionCodes
        {
            EXCEPTION_GUARD_PAGE_VIOLATION = -2147483647,
            EXCEPTION_DATATYPE_MISALIGNMENT = -2147483646,
            EXCEPTION_BREAKPOINT = -2147483645,
            EXCEPTION_SINGLE_STEP = -2147483644,
            EXCEPTION_ACCESS_VIOLATION = -1073741819,
            EXCEPTION_IN_PAGE_ERROR = -1073741818,
            EXCEPTION_INVALID_HANDLE = -1073741816,
            EXCEPTION_NO_MEMORY = -1073741801,
            EXCEPTION_ILLEGAL_INSTRUCTION = -1073741795,
            EXCEPTION_NONCONTINUABLE_EXCEPTION = -1073741787,
            EXCEPTION_INVALID_DISPOSITION = -1073741786,
            EXCEPTION_ARRAY_BOUNDS_EXCEEDED = -1073741684,
            EXCEPTION_FLOAT_DENORMAL_OPERAND = -1073741683,
            EXCEPTION_FLOAT_DIVIDE_BY_ZERO = -1073741682,
            EXCEPTION_FLOAT_INEXACT_RESULT = -1073741681,
            EXCEPTION_FLOAT_INVALID_OPERATION = -1073741680,
            EXCEPTION_FLOAT_OVERFLOW = -1073741679,
            EXCEPTION_FLOAT_STACK_CHECK = -1073741678,
            EXCEPTION_FLOAT_UNDERFLOW = -1073741677,
            EXCEPTION_INTEGER_DIVIDE_BY_ZERO = -1073741676,
            EXCEPTION_INTEGER_OVERFLOW = -1073741675,
            EXCEPTION_PRIVILEGED_INSTRUCTION = -1073741674,
            EXCEPTION_STACK_OVERFLOW = -1073741571,
            EXCEPTION_CONTROL_C_EXIT = -1073741510
        }

        const Int32 EXCEPTION_MAXIMUM_PARAMETERS = 15; // maximum number of exception parameters
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private struct EXCEPTION_RECORD
        {
            public ExceptionCodes ExceptionCode;
            public ExceptionFlags ExceptionFlags;
            public IntPtr pExceptionRecord; // Points to another EXCEPTION_RECORD structure.
            public IntPtr ExceptionAddress;
            public UInt32 NumberParameters;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = EXCEPTION_MAXIMUM_PARAMETERS)]
            public UInt32[] ExceptionInformation;
            public UInt32 dwFirstChance;
        }
        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)]
        private struct DEBUG_EVENT
        {
            [MarshalAs(UnmanagedType.I4)]
            public DebugEventType dwDebugEventCode;
            public int dwProcessId;
            public int dwThreadId;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
            public byte[] bytes;

        }
        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds);


        const int DBG_CONTINUE = 0x00010002;
        const int DBG_EXCEPTION_NOT_HANDLED = unchecked((int)0x80010001);
        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, int dwContinueStatus);

        public enum BREAKPOINT_FLAGS : uint
        {
            INT3_PERMANENT = 0x20000,
            INT3_VOLATILE  = 0x10000,

            // INT3_SOFTWARE = 0x00, // in future... or not
            // INT3_HARDWARE = 0x01 // in future... or not
        }

        private struct INT3
        {
            // public bool Enabled; // not use, future
            public UInt32 Counter;
            public uint Eip;
            public Callback Callback;
            public IntPtr AllocInProcess;
            public int SizeAlloc;
            [MarshalAs(UnmanagedType.ByValArray)]
            public byte[] Code;
        }

        static readonly object _locker = new object();
        private static bool _stop = false;
        private static Process _process;
        private static Thread _thread;
        private static Dictionary<string, INT3> _breakpoints; // list des addresses trouvées par les breakpoints


        // founded in the web, and modify by me
        private static byte[] ModifyShellcode(byte[] bytes, uint eip)
        {
            byte[] bytesEip = BitConverter.GetBytes(eip);
            byte[] start = new byte[] {
                0x60, // PUSHAD
                0x9C  // PUSHFD
            };

            byte[] end = new byte[] {
                0x9D, // POPFD
                0x61, // POPAD
            };

            IEnumerable<byte> result = Enumerable.Empty<byte>();

            result = result.Concat(start);
            result = result.Concat(bytes);
            result = result.Concat(end);
            result = result.Concat(new byte[] { 0x68 }); // PUSH
            result = result.Concat(bytesEip);            // EIP
            result = result.Concat(new byte[] { 0xC3 }); // RET
            
            return result.ToArray();
        }

        public static bool IsBreakpoint(uint eip)
        {
            if (_breakpoints == null) return false;
            lock (_locker)
            {
                int nb = _breakpoints.Count(x => (x.Value.Eip == eip));
                return (nb > 0);
            }
        }

        public static bool IsBreakpoint(string name)
        {
            if (_breakpoints == null) return false;
            lock (_locker)
            {
                return _breakpoints.ContainsKey(name);
            }
        }

        public static bool ClearAllBreakpoints()
        {
            bool ret = false;
            
            if (_breakpoints == null) return false;

            foreach (string key in _breakpoints.Keys.ToList<string>())
            {
                ret |= !RemoveBreakpoint(key);
            }
            
            if (_breakpoints == null) _breakpoints.Clear();

            return !ret;
        }

        public static List<String> GetBreakpoints()
        {
            if (_breakpoints == null) return new List<string>();
            lock (_locker)
            {
                return _breakpoints.Keys.ToList<string>();
            }
        }

        public static bool SetCallback(string name, Callback action)
        {
            if (_breakpoints == null) return false;
            lock (_locker)
            {
                if (!_breakpoints.ContainsKey(name)) return false;
                INT3 tmp = _breakpoints[name];
                tmp.Callback = action;
                _breakpoints[name] = tmp;
            }
            return true;
        }

        public static bool GetEip(string name,out uint eip)
        {
            eip = 0;
            if (_breakpoints == null) return false;
            lock (_locker)
            {
                if (!_breakpoints.ContainsKey(name)) return false;
                eip = _breakpoints[name].Eip;
            }
            return true;
        }

        public static int GetNumberActiveBreakpoints()
        {
            if (_breakpoints == null) return 0;
            lock (_locker)
            {
                return _breakpoints.Count();
            }
        }

        public static bool AddBreakpoint(string name, uint eip, int lengthcode, BREAKPOINT_FLAGS flags,Callback action)
        {
            IntPtr memoire = IntPtr.Zero;
            int sizealloc = 0;
            IntPtr hProc = IntPtr.Zero;
            byte[] buffer = new byte[lengthcode];

            bool ret = false;
            lock (_locker)
            {
                if (_breakpoints == null) return false;
                if (_breakpoints.ContainsKey(name)) return false;
                try
                {
                    if (_process == null) throw new ApplicationException("You must attach the process in first");

                    // old code
                    hProc = OpenProcess(ProcessAccessFlags.All, false, _process.Id);
                    if (hProc == IntPtr.Zero) throw new ApplicationException("Cannot open process. Maybe a shield (eg gameguard)");

                    int bytesRW;
                    if (!ReadProcessMemory(hProc, new IntPtr(eip), buffer, lengthcode, out bytesRW)) throw new ApplicationException("Cannot read into process memory. Maybe a shield (eg gameguard)");
                    if (bytesRW != lengthcode) throw new ApplicationException("Cannot read into process memory. Maybe a shield (eg gameguard)");



                    if ((flags & BREAKPOINT_FLAGS.INT3_PERMANENT) == BREAKPOINT_FLAGS.INT3_PERMANENT)
                    {
                        // new hook code
                        byte[] Code = ModifyShellcode(buffer, eip + (uint)buffer.Length);
                        sizealloc = Code.Length;
                        memoire = VirtualAllocEx(hProc, IntPtr.Zero, (uint)Code.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
                        if (memoire == IntPtr.Zero) throw new ApplicationException("Cannot allaocate memory in process. Maybe a shield (eg gameguard)");
                        if (!WriteProcessMemory(hProc, memoire, Code, (uint)Code.Length, out bytesRW)) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                        if (bytesRW != Code.LongLength) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                    }

                    // set breakpoint
                    byte[] breakpoint = { 0xCC };
                    if (!WriteProcessMemory(hProc, new IntPtr(eip), breakpoint, 1, out bytesRW)) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                    lengthcode = 0; // indicator for exception
                    if (bytesRW != 1) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");

                    if (!FlushInstructionCache(hProc, new IntPtr(eip), new UIntPtr((uint)bytesRW))) throw new ApplicationException("Cannot flush intruction cache. Maybe a shield (eg gameguard)");

                    INT3 tmp = new INT3();
                    tmp.Callback = action;
                    tmp.AllocInProcess = memoire;
                    tmp.SizeAlloc = sizealloc;
                    tmp.Counter = 0;
                    tmp.Eip = eip;
                    tmp.Code = new byte[buffer.Length];
                    buffer.CopyTo(tmp.Code, 0);
                    _breakpoints.Add(name, tmp);
                    ret = true;
                }
                catch (Exception ex)
                {
                    // if breakpoint already set
                    int bytesRW;
                    byte[] t = new byte[1];

                    // restore original code 
                    if (lengthcode == 0)
                    {
                        if (WriteProcessMemory(hProc, new IntPtr(eip), buffer, (uint)buffer.Length, out bytesRW))
                        {
                            if (bytesRW == buffer.Length)
                            {
                                FlushInstructionCache(hProc, new IntPtr(eip), new UIntPtr((uint)bytesRW));
                            }
                        }
                    }

                    if (memoire != IntPtr.Zero) VirtualFreeEx(hProc, memoire, sizealloc, FreeType.Release);
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    if (hProc != IntPtr.Zero) CloseHandle(hProc);
                }
            }
            return ret;
        }

        public static bool RemoveBreakpoint(string name)
        {

            IntPtr hProc = IntPtr.Zero;
            bool ret = false;

            lock (_locker)
            {

                if (_breakpoints == null) return false;
                if (!_breakpoints.ContainsKey(name)) return false;

                INT3 tmp = _breakpoints[name];

                if (_process == null) throw new ApplicationException("You must attach the process in first");
                try
                {
                    hProc = OpenProcess(ProcessAccessFlags.All, false, _process.Id);
                    if (hProc == IntPtr.Zero) throw new ApplicationException("Cannot open process. Maybe a shield (eg gameguard)");


                    int bytesRW;
                    byte[] buffer = new byte[1];
                    if (!ReadProcessMemory(hProc, new IntPtr(tmp.Eip), buffer, 1, out bytesRW)) throw new ApplicationException("Cannot read into process memory. Maybe a shield (eg gameguard)");
                    if (bytesRW != 1) throw new ApplicationException("Cannot read into process memory. Maybe a shield (eg gameguard)");

                    // if the code changed by the callback or anothers methods
                    if (buffer[0] == 0xCC)
                    {
                        // restore original code
                        if (!WriteProcessMemory(hProc, new IntPtr(tmp.Eip), tmp.Code, (uint)tmp.Code.Length, out bytesRW)) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                        if (bytesRW != tmp.Code.Length) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                        if (!FlushInstructionCache(hProc, new IntPtr(tmp.Eip), new UIntPtr((uint)bytesRW))) throw new ApplicationException("Cannot flush intruction cache. Maybe a shield (eg gameguard)");
                    }
                    ret = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {

                    if (tmp.AllocInProcess != IntPtr.Zero) VirtualFreeEx(hProc, tmp.AllocInProcess, tmp.SizeAlloc, FreeType.Release);
                    if (hProc != IntPtr.Zero) CloseHandle(hProc);

                    _breakpoints.Remove(name);
                }
            }
            return ret;
        }



        public static bool AttachProcess(Process process)
        {
            
            _process = process;
            
            lock (_locker)
            {
                if (_breakpoints == null) _breakpoints = new Dictionary<string, INT3>();
            }

            if (_thread == null)
            {
                _thread = new Thread(new ThreadStart(ThreadLoop));
                _stop = false;
                _thread.Start();
            }

            return true;
        }





        public static bool DetachProcess()
        {
            ClearAllBreakpoints();
            if (_thread != null)
            {
                //_thread.Abort();
                _stop = true;
                
                while (_thread.IsAlive) Thread.Sleep(100);
            }

            
            return true;
        }


        static void ThreadLoop()
        {
            if (_process != null) if (!DebugActiveProcess(_process.Id)) return;
            while (_stop == false && Thread.CurrentThread.IsAlive)
            {
                DEBUG_EVENT deBuffer;
                if (WaitForDebugEvent(out deBuffer, 100))
                {
                    int continueFlag = DBG_CONTINUE;

                    if (deBuffer.dwDebugEventCode == DebugEventType.EXCEPTION_DEBUG_EVENT)
                    {

                        continueFlag = DBG_EXCEPTION_NOT_HANDLED;

                        IntPtr ptPoit = Marshal.UnsafeAddrOfPinnedArrayElement(deBuffer.bytes, 0);
                        EXCEPTION_RECORD exc = (EXCEPTION_RECORD)Marshal.PtrToStructure(ptPoit, typeof(EXCEPTION_RECORD));

                        if ((exc.ExceptionCode & ExceptionCodes.EXCEPTION_BREAKPOINT) == ExceptionCodes.EXCEPTION_BREAKPOINT)
                        {

                            CONTEXT context = new CONTEXT();
                            context.ContextFlags = (uint)CONTEXT_FLAGS.CONTEXT_ALL;
                            IntPtr hThread = OpenThread(ThreadAccess.SUSPEND_RESUME | ThreadAccess.GET_CONTEXT | ThreadAccess.SET_CONTEXT, false, (uint)deBuffer.dwThreadId);
                            if (hThread != IntPtr.Zero)
                            {



                                if (SuspendThread(hThread) == -1) throw new ApplicationException("Cannot suspend thread.");
                                if (!GetThreadContext(hThread, ref context)) throw new ApplicationException("Cannot get thread context.");

                                if ((context.ContextFlags & (uint)CONTEXT_FLAGS.CONTEXT_INTEGER) == (uint)CONTEXT_FLAGS.CONTEXT_INTEGER)
                                {
                                    Console.WriteLine("Eip : {0:X}", context.Eip);

                                    foreach (KeyValuePair<string, INT3> pair in _breakpoints.ToDictionary(x => x.Key, x => x.Value))
                                    {
                                        if (context.Eip == (pair.Value.Eip + 1))
                                        {
                                            INT3 tmp = pair.Value;
                                            tmp.Counter++;
                                            _breakpoints[pair.Key] = tmp;

                                            continueFlag = DBG_CONTINUE;
                                            
                                            uint eip = context.Eip; // save if callback change it

                                            lock (_locker)
                                            {
                                                if (tmp.Callback != null) tmp.Callback(_process,ref context);
                                            }

                                            if (tmp.AllocInProcess == IntPtr.Zero) // volatile
                                            {
                                                if (eip == context.Eip) context.Eip--; // if eip not change

                                                int bytesRW;
                                                IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, _process.Id);
                                                if (hProc == IntPtr.Zero) throw new ApplicationException("Cannot get thread context.");
                                                if (!WriteProcessMemory(hProc, new IntPtr(pair.Value.Eip), pair.Value.Code, (uint)pair.Value.Code.Length, out bytesRW)) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                                                if (bytesRW != pair.Value.Code.Length) throw new ApplicationException("Cannot write into process memory. Maybe a shield (eg gameguard)");
                                                if (!FlushInstructionCache(hProc, new IntPtr(pair.Value.Eip), new UIntPtr((uint)bytesRW))) throw new ApplicationException("Cannot flush intruction cache. Maybe a shield (eg gameguard)");
                                                CloseHandle(hProc);
                                                lock (_locker)
                                                {
                                                    if (_breakpoints.ContainsKey(pair.Key)) _breakpoints.Remove(pair.Key); //remove the volatile breakpoint
                                                }
                                            }
                                            else // no volatile
                                            {
                                                if (eip == context.Eip) context.Eip = (uint)tmp.AllocInProcess.ToInt32(); // if eip not change
                                            }

                                            if (!SetThreadContext(hThread, ref context))
                                            {
                                                throw new ApplicationException("Cannot set thread context.");
                                            }
                                                                                        
                                            break;
                                        }
                                    }
                                }

                                if (ResumeThread(hThread) == -1) throw new ApplicationException("Cannot resume thread.");
                                if (CloseHandle(hThread) == 0) throw new ApplicationException("Cannot close thread handle.");

                            }
                        }
                    }

                    ContinueDebugEvent(deBuffer.dwProcessId, deBuffer.dwThreadId, continueFlag);
                }
            }
            if (_process != null) DebugActiveProcessStop(_process.Id);
        } 
    }
}
i find this very messy and not much help except for the tools.
Posts 12 of 2 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?