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
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));
}
}
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 = resul*****ncat(start);
result = resul*****ncat(bytes);
result = resul*****ncat(end);
result = resul*****ncat(new byte[] { 0x68 }); // PUSH
result = resul*****ncat(bytesEip); // EIP
result = resul*****ncat(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, _proces*****);
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, _proces*****);
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(_proces*****)) 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();
contex*****ntextFlags = (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 ((contex*****ntextFlags & (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, _proces*****);
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(_proces*****);
}
}
}