void IFunctionTracer.OnExitBreakpointHit(DkmRuntimeBreakpoint bp, DkmThread thread, bool hasException) { FunctionTraceEntryDataItem traceDataItem = bp.GetDataItem <FunctionTraceEntryDataItem>(); if (OnFunctionExited != null) { DkmStackWalkFrame frame = thread.GetTopStackWalkFrame(bp.RuntimeInstance); StackFrameAnalyzer exitAnalyzer = null; if (traceDataItem != null) { DkmSystemInformationFlags systemInformationFlags = frame.ModuleInstance.Process.SystemInformation.Flags; bool isTarget64Bit = systemInformationFlags.HasFlag(DkmSystemInformationFlags.Is64Bit); int pointerSize = (isTarget64Bit) ? 8 : 4; exitAnalyzer = new CachedFrameAnalyzer( frameAnalyzer.Parameters, traceDataItem.EntryArgumentValues, pointerSize); } OnFunctionExited(frame, exitAnalyzer); } // Since this was a one-shot breakpoint, it is unconditionally closed. bp.Close(); }
public FunctionTracer(DkmNativeInstructionAddress address, StackFrameAnalyzer analyzer) { this.frameAnalyzer = analyzer; DkmProcess process = address.ModuleInstance.Process; entryAddress = address; }
void createProcessTracer_OnFunctionEntered( DkmStackWalkFrame frame, StackFrameAnalyzer functionAnalyzer, out bool suppressExitBreakpoint) { // If this was not created with CREATE_SUSPENDED, then we can't automatically attach to this // child process. // TODO(zturner): OR in CREATE_SUSPENDED using WriteProcessMemory, then when the exit bp // hits, check if we OR'ed in CREATE_SUSPENDED, and if so, resume the process after the // attach. ProcessCreationFlags flags = (ProcessCreationFlags) Convert.ToUInt32(functionAnalyzer.GetArgumentValue(frame, "dwCreationFlags")); suppressExitBreakpoint = !flags.HasFlag(ProcessCreationFlags.CREATE_SUSPENDED); }
void createProcessTracer_OnFunctionExited( DkmStackWalkFrame frame, StackFrameAnalyzer frameAnalyzer) { try { ulong processInfoAddr = Convert.ToUInt64( frameAnalyzer.GetArgumentValue(frame, "lpProcessInformation")); // Check the return address first, it should be in EAX. CreateProcessAsUser and // CreateProcess both return 0 on failure. If the function failed, there is no child to // attach to. if (0 == frame.VscxGetRegisterValue32(CpuRegister.Eax)) { return; } // The process was successfully created. Extract the PID from the PROCESS_INFORMATION // output param. An attachment request must happend through the EnvDTE, which can only // be accessed from the VsPackage, so a request must be sent via a component message. DkmProcess process = frame.Process; int size = Marshal.SizeOf(typeof(PROCESS_INFORMATION)); byte[] buffer = new byte[size]; process.ReadMemory(processInfoAddr, DkmReadMemoryFlags.None, buffer); PROCESS_INFORMATION info = MarshalUtility.ByteArrayToStructure <PROCESS_INFORMATION>(buffer); DkmCustomMessage attachRequest = DkmCustomMessage.Create( process.Connection, process, PackageServices.VsPackageMessageGuid, (int)VsPackageMessage.AttachToChild, process.LivePart.Id, info.dwProcessId); attachRequest.SendToVsService(PackageServices.DkmComponentEventHandler, false); } catch (Exception exception) { Logger.LogError( exception, "An error occured handling the exit breakpoint. HR = 0x{0:X}", exception.HResult); } }
private void HookCreateProcess(DkmNativeModuleInstance module, string export, StackFrameAnalyzer frameAnalyzer) { try { FunctionTracer tracer = new FunctionTracer( module.FindExportName(export, true), frameAnalyzer); tracer.OnFunctionEntered += createProcessTracer_OnFunctionEntered; tracer.OnFunctionExited += createProcessTracer_OnFunctionExited; tracer.Enable(); _functionTracers.Add(tracer); } catch (DkmException) { // For some reason, sandboxed processes act strangely (e.g. FindExportName throws an // exception with E_FAIL. It's not clear why this happens, but these processes can't // create child processes anyway, so just handle this failure gracefully. return; } }