public FunctionTracer(DkmNativeInstructionAddress address, StackFrameAnalyzer analyzer) { this.frameAnalyzer = analyzer; DkmProcess process = address.ModuleInstance.Process; entryAddress = address; }
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; } }
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.LogException( exception, "An error occured handling the exit breakpoint. HR = 0x{0:X}", exception.HResult); } }
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); }