/// <summary> /// Gets the thread's context. /// </summary> /// <returns>A CONTEXT struct.</returns> public ContextAmd64 GetContext(ContextFlagsAmd64 flags) { ContextAmd64 context = new ContextAmd64(); context.ContextFlags = flags; this.GetContext(ref context); return(context); }
/// <summary> /// Sets the thread's context. /// </summary> /// <param name="context">A CONTEXT struct.</param> public void SetContext(ContextAmd64 context) { // HACK: To avoid a datatype misalignment error, allocate // some aligned memory. using (AlignedMemoryAlloc data = new AlignedMemoryAlloc(Utils.SizeOf(16, ContextAmd64.SizeOf), 16)) { data.WriteStruct(context); Win32.NtSetContextThread(this, data).ThrowIf(); } }
/// <summary> /// Sets the thread's context. /// </summary> /// <param name="context">A CONTEXT struct.</param> public void SetContext(ContextAmd64 context) { NtStatus status; // HACK: To avoid a datatype misalignment error, allocate // some aligned memory. using (var data = new AlignedMemoryAlloc(Utils.SizeOf <ContextAmd64>(16), 16)) { data.WriteStruct <ContextAmd64>(context); if ((status = Win32.NtSetContextThread(this, data)) >= NtStatus.Error) { Win32.Throw(status); } } }
public static extern bool StackWalk64( [In] MachineType MachineType, [In] IntPtr ProcessHandle, [In] IntPtr ThreadHandle, ref StackFrame64 StackFrame, ref ContextAmd64 ContextRecord, [In] [Optional] ReadProcessMemoryProc64 ReadMemoryRoutine, [In] [Optional] FunctionTableAccessProc64 FunctionTableAccessRoutine, [In] [Optional] GetModuleBaseProc64 GetModuleBaseRoutine, [In] [Optional] IntPtr TranslateAddress );
public static extern NtStatus NtGetContextThread( [In] IntPtr ThreadHandle, ref ContextAmd64 ThreadContext );
/// <summary> /// Walks the call stack for the thread. /// </summary> /// <param name="parentProcess">A handle to the thread's parent process.</param> /// <param name="walkStackCallback">A callback to execute.</param> /// <param name="architecture"> /// The type of stack walk. On 32-bit systems, this value is ignored. /// On 64-bit systems, this value can be set to I386 to walk the /// 32-bit stack. /// </param> public unsafe void WalkStack(ProcessHandle parentProcess, WalkStackDelegate walkStackCallback, OSArch architecture) { bool suspended = false; // Suspend the thread to avoid inaccurate thread stacks. try { this.Suspend(); suspended = true; } catch (WindowsException) { suspended = false; } // Use KPH for reading memory if we can. ReadProcessMemoryProc64 readMemoryProc = null; if (KProcessHacker.Instance != null) { readMemoryProc = new ReadProcessMemoryProc64( delegate(IntPtr processHandle, ulong baseAddress, IntPtr buffer, int size, out int bytesRead) { return(KProcessHacker.Instance.KphReadVirtualMemorySafe( ProcessHandle.FromHandle(processHandle), (int)baseAddress, buffer, size, out bytesRead).IsSuccess()); }); } try { // x86/WOW64 stack walk. if (OSVersion.Architecture == OSArch.I386 || (OSVersion.Architecture == OSArch.Amd64 && architecture == OSArch.I386)) { Context context = new Context(); context.ContextFlags = ContextFlags.All; if (OSVersion.Architecture == OSArch.I386) { // Get the context. this.GetContext(ref context); } else { // Get the WOW64 x86 context. this.GetContextWow64(ref context); } // Set up the initial stack frame structure. var stackFrame = new StackFrame64(); stackFrame.AddrPC.Mode = AddressMode.AddrModeFlat; stackFrame.AddrPC.Offset = (ulong)context.Eip; stackFrame.AddrStack.Mode = AddressMode.AddrModeFlat; stackFrame.AddrStack.Offset = (ulong)context.Esp; stackFrame.AddrFrame.Mode = AddressMode.AddrModeFlat; stackFrame.AddrFrame.Offset = (ulong)context.Ebp; while (true) { using (Win32.DbgHelpLock.AcquireContext()) { if (!Win32.StackWalk64( MachineType.I386, parentProcess, this, ref stackFrame, ref context, readMemoryProc, Win32.SymFunctionTableAccess64, Win32.SymGetModuleBase64, IntPtr.Zero )) { break; } } // If we got an invalid eip, break. if (stackFrame.AddrPC.Offset == 0) { break; } // Execute the callback. if (!walkStackCallback(new ThreadStackFrame(ref stackFrame))) { break; } } } // x64 stack walk. else if (OSVersion.Architecture == OSArch.Amd64) { ContextAmd64 context = new ContextAmd64(); context.ContextFlags = ContextFlagsAmd64.All; // Get the context. this.GetContext(ref context); // Set up the initial stack frame structure. var stackFrame = new StackFrame64(); stackFrame.AddrPC.Mode = AddressMode.AddrModeFlat; stackFrame.AddrPC.Offset = (ulong)context.Rip; stackFrame.AddrStack.Mode = AddressMode.AddrModeFlat; stackFrame.AddrStack.Offset = (ulong)context.Rsp; stackFrame.AddrFrame.Mode = AddressMode.AddrModeFlat; stackFrame.AddrFrame.Offset = (ulong)context.Rbp; while (true) { using (Win32.DbgHelpLock.AcquireContext()) { if (!Win32.StackWalk64( MachineType.Amd64, parentProcess, this, ref stackFrame, ref context, readMemoryProc, Win32.SymFunctionTableAccess64, Win32.SymGetModuleBase64, IntPtr.Zero )) { break; } } // If we got an invalid rip, break. if (stackFrame.AddrPC.Offset == 0) { break; } // Execute the callback. if (!walkStackCallback(new ThreadStackFrame(ref stackFrame))) { break; } } } } finally { // If we suspended the thread before, resume it. if (suspended) { try { this.Resume(); } catch (WindowsException) { } } } }