public static bool Hook(ProcessMemory memory, IntPtr funcAddr, TrampolineHeap heap) { var objectCode = _nops.ToArray(); var trampolineAddr = heap.Allocate((uint)objectCode.Length); var jmpToTrampoline = CreateJmpRel32((uint)funcAddr, (uint)trampolineAddr); var originalCode = memory.ReadBytes(funcAddr, 0x100); var dasm = IA32Disassembler.Disassemble(originalCode); var matches = dasm .TakeWhile(x => ((Opcode[])Enum.GetValues(typeof(Opcode))).Contains(x.Opcode.Opcode)) .ToArray(); var matchSum = matches.Sum(x => x.Size); var sum = 0; dasm.TakeWhile(x => (sum += x.Size) < jmpToTrampoline.Length).ToArray(); if (matchSum < sum) { return(false); } var originalCodeCopy = originalCode.ToArray(); Array.Resize(ref originalCode, sum); originalCodeCopy = originalCodeCopy.Skip(originalCode.Length).ToArray(); //0x10 8B 4C 24 14 8B 7C 24 0C 8B if (originalCodeCopy[0] == 0x10 && originalCodeCopy[1] == 0x8B && originalCodeCopy[2] == 0x4C && originalCodeCopy[3] == 0x24 && originalCodeCopy[4] == 0x14 && originalCodeCopy[5] == 0x8B && originalCodeCopy[6] == 0x7C && originalCodeCopy[7] == 0x24 && originalCodeCopy[8] == 0x0C && originalCodeCopy[9] == 0x8B) { Console.WriteLine(); } const int originalCodeOffset = 0x10; originalCode.CopyTo(objectCode, originalCodeOffset); var jmpToFuncOffset = (uint)originalCodeOffset + (uint)originalCode.Length + 0x4; //objectCode[(uint)originalCodeOffset + (uint)originalCode.Length + 1] = 0xCC; var jmpToFunc = CreateJmpRel32( (uint)trampolineAddr + jmpToFuncOffset, (uint)funcAddr + (uint)originalCode.Length); jmpToFunc.CopyTo(objectCode, jmpToFuncOffset); memory.Write(trampolineAddr, objectCode); memory.Write(funcAddr, jmpToTrampoline); return(true); }
public BreakpointManager(ProcessMemory memory) { BreakpointTable = new Dictionary <IntPtr, byte>(); HitTable = new Dictionary <IntPtr, uint>(); MaxHits = 0x1; ThreadCache = new Cache <uint, IntPtr>(x => Kernel32.OpenThread( ThreadAccess.THREAD_GET_CONTEXT | ThreadAccess.THREAD_SET_CONTEXT, false, x)); mem = memory; }
public ProcessMemory GetMemory(IntPtr processHandle) { lock (_readers) { if (!_readers.TryGetValue(processHandle, out var mem)) { _readers.Add(processHandle, mem = new ProcessMemory(processHandle)); } return(mem); } }
public List <uint> GetFunctionPointers(int count) { var pointers = new List <uint>(); var reader = new ProcessMemory(Process); var context = ProcessMemory.GetContext(ThreadId); //var pointers = new List<uint> { context.Eip }; uint[] stack = null; var ptr = IntPtr.Zero; try { ptr = (IntPtr)context.Esp; } catch { } if (ptr != IntPtr.Zero) { stack = reader.ReadUInt32s(ptr, count / 4); } if (stack == null) { return(null); } foreach (var p in GetIntPtrs(stack)) { var bytes = reader.ReadBytes(p, 0x20); if (bytes == null || //IsStackAddress(context, (uint)p) || !reader.IsExecutable(p)) { continue; } pointers.Add((uint)p); //var dasm = new DiStormWrapper().Disassemble(bytes); } return(pointers); }
public DebuggerEventArgs( IntPtr processHandle, byte[] faultingInstructions, string instructionHash, DEBUG_EVENT debugEvent, ProcessMemory memory #if FULL_DBG , BreakpointManager breakpoints, HookManager hooks #endif ) { ProcessHandle = processHandle; FaultingInstructions = faultingInstructions; InstructionHash = instructionHash; DebugEvent = debugEvent; Memory = memory; #if FULL_DBG Breakpoints = breakpoints; Hooks = hooks; #endif }
public void ProcessDebugEvents() { IsStarted = true; var debugEvent = new DEBUG_EVENT(); while (!_killProcesses && IsStarted && Processes.Count != 0) { if (!Kernel32.WaitForDebugEvent(ref debugEvent, 200)) { var error = Marshal.GetLastWin32Error(); //if (error == 121 || _killProcesses) /*if (_killProcesses) * { * KillCore(); * break; * } * else */if (error != 121) { throw new Win32Exception(error); } if (Timeout > 0 && (DateTime.Now - StartTime).TotalMilliseconds > Timeout) { Kill(); return; } continue; } Process p = null; LockProcesses(() => { if (_processTable.ContainsKey(debugEvent.dwProcessId)) { p = _processTable[debugEvent.dwProcessId]; } }); byte[] buffer = null; var hash = "[NO HASH]"; switch (debugEvent.dwDebugEventCode) { case DebugEventType.CREATE_PROCESS_DEBUG_EVENT: if (p != null) { var mem = new ProcessMemory(p.Handle); lock (_readers) { _readers.Add(p.Handle, mem); } #if FULL_DBG if (!_hookManagers.ContainsKey(p.Handle)) { _hookManagers.Add(p.Handle, new HookManager(mem)); _breakpointManagers.Add(p.Handle, new BreakpointManager(mem)); } #endif } lock (_loaderBreakpointTable) { if (!_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Add(debugEvent.dwProcessId, false); } } LockProcesses(() => { AddProcess(debugEvent.dwProcessId); p = _processTable[debugEvent.dwProcessId]; }); Kernel32.CloseHandle(debugEvent.CreateProcessInfo.hFile); break; case DebugEventType.EXIT_PROCESS_DEBUG_EVENT: lock (_loaderBreakpointTable) { if (_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Remove(debugEvent.dwProcessId); } } LockProcesses(() => RemoveProcess(debugEvent.dwProcessId)); if (p != null) { lock (_readers) { try { // Swallow exceptions caused by accessing Process.Handle after // process has exited. _readers.Remove(p.Handle); } catch { } } } break; case DebugEventType.LOAD_DLL_DEBUG_EVENT: Kernel32.CloseHandle(debugEvent.LoadDll.hFile); break; case DebugEventType.EXCEPTION_DEBUG_EVENT: lock (_loaderBreakpointTable) { if (debugEvent.Exception.ExceptionRecord.ExceptionCode == ExceptionCode.EXCEPTION_BREAKPOINT) { if (!_loaderBreakpointTable.ContainsKey(debugEvent.dwProcessId)) { _loaderBreakpointTable.Add(debugEvent.dwProcessId, false); } if (!_loaderBreakpointTable[debugEvent.dwProcessId]) { _loaderBreakpointTable[debugEvent.dwProcessId] = true; debugEvent.ContinueUnhandled(); continue; } } } if (p != null) { if (HashException) { hash = GetExceptionHash(p, debugEvent); } if (ReadFaultingInstructions) { buffer = new byte[32]; var exPtr = IntPtr.Zero; try { exPtr = (IntPtr)debugEvent.Exception.ExceptionRecord.ExceptionAddress; } catch (OverflowException) { } if (Kernel32.ReadProcessMemory( p.Handle, exPtr, buffer, new IntPtr(buffer.Length), out var bytesRead)) { if (bytesRead < buffer.Length) { Array.Resize(ref buffer, bytesRead); } } else { buffer = null; } //hash = CreateInstructionHash(buffer.Take(HashSize)); } } //elser //{ // throw new InvalidOperationException(); //} break; } if (DebugEventReceived != null) { IntPtr handle; try { handle = p != null ? p.Handle : IntPtr.Zero; } catch { handle = IntPtr.Zero; } #if FULL_DBG if (!_breakpointManagers.TryGetValue(handle, out var breakpoints)) { _breakpointManagers.Add(handle, breakpoints = new BreakpointManager(GetMemory(handle))); } if (!_hookManagers.TryGetValue(handle, out var hooks)) { _hookManagers.Add(handle, hooks = new HookManager(GetMemory(handle))); } #endif DebugEventReceived(this, new DebuggerEventArgs( handle, buffer, hash, debugEvent, GetMemory(handle) #if FULL_DBG , breakpoints, hooks #endif )); } if (Timeout > 0 && (DateTime.Now - StartTime).TotalMilliseconds > Timeout) { Kill(); return; } } //KillCore(); }
public HookManager(ProcessMemory memory) => _heap = new TrampolineHeap(_memory = memory);
public TrampolineHeap(ProcessMemory memory) { BlockSize = 0x1000; _memory = memory; }