示例#1
0
 private static extern bool StackWalkEx(
     ImageFileMachine MachineType,
     IntPtr hProcess,
     IntPtr hThread,
     ref STACKFRAME_EX StackFrame,
     IntPtr ContextRecord,
     ReadProcessMemoryProc64 ReadMemoryRoutine,
     FunctionTableAccessProc64 FunctionTableAccessRoutine,
     GetModuleBaseProc64 GetModuleBaseRoutine,
     TranslateAddressProc64 TranslateAddress,
     uint Flags);
示例#2
0
 private static extern IntPtr SymFunctionTableAccess64AccessRoutines(
     IntPtr hProcess,
     ulong AddrBase,
     ReadProcessMemoryProc64 ReadMemoryRoutine,
     GetModuleBaseProc64 GetModuleBaseRoutine);
示例#3
0
        /// <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)
                    { }
                }
            }
        }