public static DkmNativeInstructionAddress GetExportedFunctionAddress(this DkmNativeModuleInstance moduleInstance, string name) { var addr = moduleInstance.FindExportName(name, true); if (addr == null) { Debug.Fail("Couldn't find dllexport function " + name + " in module " + moduleInstance.Name); throw new ArgumentException(); } return(addr); }
private void AddStepInGate(StepInGateHandler handler, DkmNativeModuleInstance module, string funcName, bool hasMultipleExitPoints) { var gate = new StepInGate { Handler = handler, HasMultipleExitPoints = hasMultipleExitPoints, Breakpoint = LocalComponent.CreateRuntimeDllFunctionBreakpoint(module, funcName, (thread, frameBase, vframe) => handler(thread, frameBase, vframe, useRegisters: thread.Process.Is64Bit())) }; _stepInGates.Add(gate); }
public static ulong GetExportedStaticVariableAddress(this DkmNativeModuleInstance moduleInstance, string name) { var addr = moduleInstance.FindExportName(name, false); if (addr == null) { Debug.Fail("Couldn't find dllexport variable " + name + " in module " + moduleInstance.Name); throw new ArgumentException(); } return(moduleInstance.BaseAddress + addr.RVA); }
public void Enable() { DkmNativeModuleInstance module = entryAddress.ModuleInstance; FunctionTraceDataItem traceDataItem = new FunctionTraceDataItem { Tracer = this }; entryBp = DkmRuntimeInstructionBreakpoint.Create( Guids.Source.FunctionTraceEnter, null, entryAddress, false, null); entryBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, traceDataItem); entryBp.Enable(); }
private StackFrameAnalyzer CreateFrameAnalyzer( DkmNativeModuleInstance module, FunctionParameter[] parameters) { DkmSystemInformationFlags systemInformationFlags = module.Process.SystemInformation.Flags; bool isTarget64Bit = systemInformationFlags.HasFlag(DkmSystemInformationFlags.Is64Bit); int pointerSize = (isTarget64Bit) ? 8 : 4; if (isTarget64Bit) return new X64FrameAnalyzer(parameters); else return new StdcallFrameAnalyzer(parameters); }
public static PythonLanguageVersion GetPythonLanguageVersion(DkmNativeModuleInstance moduleInstance) { var m = pythonName.Match(moduleInstance.Name); if (!m.Success) { return PythonLanguageVersion.None; } var ver = m.Groups[1].Value; switch (ver) { case "27": return PythonLanguageVersion.V27; case "33": return PythonLanguageVersion.V33; case "34": return PythonLanguageVersion.V34; case "35": return PythonLanguageVersion.V35; default: return PythonLanguageVersion.None; } }
internal static ulong?TryGetFunctionAddress(DkmNativeModuleInstance moduleInstance, string name, out string error) { var functionSymbol = TryGetDiaFunctionSymbol(moduleInstance, name, out error); if (functionSymbol == null) { return(null); } uint rva = functionSymbol.relativeVirtualAddress; ReleaseComObject(functionSymbol); return(moduleInstance.BaseAddress + rva); }
public static DkmNativeInstructionAddress GetFunctionAddress(DkmNativeModuleInstance moduleInstance, string name) { uint rva = 0; using (var rootSymbol = GetRootSymbol(moduleInstance.Module)) { if (rootSymbol.Ptr == null) return null; using (var funcSymbol = FindChildSymbol(rootSymbol, SymTagEnum.SymTagFunction, name)) { if (funcSymbol.Ptr == null) return null; rva = funcSymbol.Ptr.relativeVirtualAddress; } } return (DkmNativeInstructionAddress)moduleInstance.Process.CreateNativeInstructionAddress(moduleInstance.BaseAddress + rva); }
internal static ulong FindVariableAddress(DkmNativeModuleInstance nativeModuleInstance, string variableName) { var address = nativeModuleInstance.FindExportName(variableName, IgnoreDataExports: false); if (address != null) { LocalComponent.log.Debug($"Found helper library '{variableName}' variable at 0x{address.CPUInstructionPart.InstructionPointer:x}"); return(address.CPUInstructionPart.InstructionPointer); } LocalComponent.log.Warning($"Failed to find helper library '{variableName}' variable"); return(0); }
public SourceLocation(ReadOnlyCollection <byte> encodedLocation, DkmProcess process = null) { var buffer = encodedLocation.ToArray(); using (var stream = new MemoryStream(buffer)) using (var reader = new BinaryReader(stream)) { FileName = reader.ReadString(); bool hasFunctionName = reader.ReadBoolean(); if (hasFunctionName) { FunctionName = reader.ReadString(); } LineNumber = reader.ReadInt32(); bool hasNativeAddress = reader.ReadBoolean(); if (hasNativeAddress && process != null) { var ip = reader.ReadUInt64(); var rva = reader.ReadUInt32(); PythonDLLs dlls = process.GetPythonRuntimeInfo().DLLs; DkmNativeModuleInstance dll = null; switch (reader.ReadInt32()) { case 0: dll = dlls.Python; break; case 1: dll = dlls.DebuggerHelper; break; } if (dll != null) { NativeAddress = DkmNativeInstructionAddress.Create( process.GetNativeRuntimeInstance(), dll, rva, new DkmNativeInstructionAddress.CPUInstruction(ip)); } } else { NativeAddress = null; } } }
public static DkmRuntimeBreakpoint[] CreateRuntimeDllFunctionExitBreakpoints(DkmNativeModuleInstance moduleInstance, string funcName, RuntimeDllBreakpointHandler handler, bool enable = false) { var process = moduleInstance.Process; T runtimeBreakpoints = process.GetOrCreateDataItem(() => new RuntimeDllBreakpoints()); using (var moduleSym = moduleInstance.GetSymbols()) using (ComPtr <IDiaSymbol> funcSym = moduleSym.Object.GetSymbol(SymTagEnum.SymTagFunction, funcName)) { var funcEnds = funcSym.Object.GetSymbols(SymTagEnum.SymTagFuncDebugStart, null); try { if (funcEnds.Length == 0) { Debug.Fail("Cannot set exit breakpoint for function " + funcName + " because it has no FuncDebugEnd symbols."); throw new NotSupportedException(); } var bps = new List <DkmRuntimeBreakpoint>(); foreach (var funcEnd in funcEnds) { if (funcEnd.Object.locationType != (uint)DiaLocationType.LocIsStatic) { Debug.Fail("Cannot set exit breakpoint for function " + funcName + " because it has a non-static FuncDebugEnd symbol."); throw new NotSupportedException(); } ulong addr = moduleInstance.BaseAddress + funcEnd.Object.relativeVirtualAddress; var bp = process.CreateBreakpoint(Guids.LocalComponentGuid, addr); if (enable) { bp.Enable(); } bps.Add(bp); runtimeBreakpoints.Handlers.Add(bp.UniqueId, new FunctionExitBreakpointHandler(handler).Handle); } return(bps.ToArray()); } finally { foreach (var funcEnd in funcEnds) { funcEnd.Dispose(); } } } }
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; } }
private StackFrameAnalyzer CreateFrameAnalyzer( DkmNativeModuleInstance module, FunctionParameter[] parameters) { DkmSystemInformationFlags systemInformationFlags = module.Process.SystemInformation.Flags; bool isTarget64Bit = systemInformationFlags.HasFlag(DkmSystemInformationFlags.Is64Bit); int pointerSize = (isTarget64Bit) ? 8 : 4; if (isTarget64Bit) { return(new X64FrameAnalyzer(parameters)); } else { return(new StdcallFrameAnalyzer(parameters)); } }
public void OnModuleInstanceLoad(DkmNativeModuleInstance module, DkmWorkList workList) { bool isKernel32 = module.Name.Equals( "Kernel32.dll", StringComparison.CurrentCultureIgnoreCase); bool isAdvapi32 = module.Name.Equals( "Advapi32.dll", StringComparison.CurrentCultureIgnoreCase); // For historical reasons, Kernel32.dll contains CreateProcess and Advapi32.dll contains // CreateProcessAsUser. if (isKernel32) { HookCreateProcess(module, "CreateProcessW", CreateFrameAnalyzer(module, _createProcessParams)); } else if (isAdvapi32) { HookCreateProcess(module, "CreateProcessAsUserW", CreateFrameAnalyzer(module, _createProcessAsUserParams)); } }
private static void OnHelperDllInitialized(DkmNativeModuleInstance moduleInstance) { var process = moduleInstance.Process; var pyrtInfo = process.GetPythonRuntimeInfo(); pyrtInfo.DLLs.DebuggerHelper = moduleInstance; if (pyrtInfo.DLLs.Python != null && pyrtInfo.DLLs.Python.HasSymbols()) { CreatePythonRuntimeInstance(process); } // If there was a suspended thread, resume it. var injectionData = process.GetDataItem <HelperDllInjectionDataHolder>(); if (injectionData != null && injectionData.SuspendedThread != null) { injectionData.SuspendedThread.Resume(true); } }
public static ulong GetFunctionAddress(this DkmNativeModuleInstance moduleInstance, string name, bool debugStart = false) { uint rva; using (var moduleSym = moduleInstance.GetSymbols()) { using (var funcSym = moduleSym.Object.GetSymbol(SymTagEnum.SymTagFunction, name)) { if (debugStart) { using (var startSym = funcSym.Object.GetSymbol(SymTagEnum.SymTagFuncDebugStart, null)) { rva = startSym.Object.relativeVirtualAddress; } } else { rva = funcSym.Object.relativeVirtualAddress; } } } return(moduleInstance.BaseAddress + rva); }
public static DkmNativeInstructionAddress GetFunctionAddress(DkmNativeModuleInstance moduleInstance, string name) { uint rva = 0; using (var rootSymbol = GetRootSymbol(moduleInstance.Module)) { if (rootSymbol.Ptr == null) { return(null); } using (var funcSymbol = FindChildSymbol(rootSymbol, SymTagEnum.SymTagFunction, name)) { if (funcSymbol.Ptr == null) { return(null); } rva = funcSymbol.Ptr.relativeVirtualAddress; } } return((DkmNativeInstructionAddress)moduleInstance.Process.CreateNativeInstructionAddress(moduleInstance.BaseAddress + rva)); }
public static ulong GetStaticVariableAddress(this DkmNativeModuleInstance moduleInstance, string name, string objFileName = null) { uint rva; using (var moduleSym = moduleInstance.GetSymbols()) { if (objFileName != null) { using (var compiland = moduleSym.Object.GetSymbol(SymTagEnum.SymTagCompiland, null, cmp => cmp.name.EndsWith(objFileName))) using (var varSym = compiland.Object.GetSymbol(SymTagEnum.SymTagData, name)) { rva = varSym.Object.relativeVirtualAddress; } } else { using (var varSym = moduleSym.Object.GetSymbol(SymTagEnum.SymTagData, name)) { rva = varSym.Object.relativeVirtualAddress; } } } return(moduleInstance.BaseAddress + rva); }
internal static Guid?CreateHelperFunctionBreakpoint(DkmNativeModuleInstance nativeModuleInstance, string functionName) { var functionAddress = TryGetFunctionAddressAtDebugStart(nativeModuleInstance, functionName, out string error); if (functionAddress != null) { LocalComponent.log.Debug($"Creating breakpoint in '{functionName}'"); var nativeAddress = nativeModuleInstance.Process.CreateNativeInstructionAddress(functionAddress.Value); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); return(breakpoint.UniqueId); } else { var nativeFunctionAddress = FindFunctionAddress(nativeModuleInstance, functionName); if (nativeFunctionAddress != 0) { LocalComponent.log.Debug($"Creating 'native' breakpoint in '{functionName}'"); var nativeAddress = nativeModuleInstance.Process.CreateNativeInstructionAddress(nativeFunctionAddress); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); return(breakpoint.UniqueId); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{functionName}' with {error}"); } } return(null); }
public static PythonLanguageVersion GetPythonLanguageVersion(DkmNativeModuleInstance moduleInstance) { var m = pythonName.Match(moduleInstance.Name); if (!m.Success) { return(PythonLanguageVersion.None); } var ver = m.Groups[1].Value; switch (ver) { case "27": return(PythonLanguageVersion.V27); case "33": return(PythonLanguageVersion.V33); case "34": return(PythonLanguageVersion.V34); default: return(PythonLanguageVersion.None); } }
internal static IDiaSymbol TryGetDiaFunctionSymbol(DkmNativeModuleInstance moduleInstance, string name, out string error) { var moduleSymbols = TryGetDiaSymbols(moduleInstance, out error); if (moduleSymbols == null) { return(null); } var functionSymbol = TryGetDiaSymbol(moduleSymbols, SymTagEnum.SymTagFunction, name, out error); if (functionSymbol == null) { ReleaseComObject(moduleSymbols); return(null); } ReleaseComObject(moduleSymbols); return(functionSymbol); }
internal static ulong?TryGetFunctionAddress(DkmNativeModuleInstance moduleInstance, string name, out string error) { try { var functionSymbol = TryGetDiaFunctionSymbol(moduleInstance, name, out error); if (functionSymbol == null) { return(null); } uint rva = functionSymbol.relativeVirtualAddress; ReleaseComObject(functionSymbol); return(moduleInstance.BaseAddress + rva); } catch (Exception ex) { error = "TryGetFunctionAddress() Unexpected error: " + ex.ToString(); } return(null); }
public void OnCTypesLoaded(DkmNativeModuleInstance moduleInstance) { AddStepInGate(_handlers._call_function_pointer, moduleInstance, "_call_function_pointer", hasMultipleExitPoints: false); }
public static DkmRuntimeBreakpoint CreateRuntimeDllExportedFunctionBreakpoint(DkmNativeModuleInstance moduleInstance, string funcName, RuntimeDllBreakpointHandler handler, bool enable = false) { var process = moduleInstance.Process; var runtimeBreakpoints = process.GetOrCreateDataItem(() => new RuntimeDllBreakpoints()); var addr = moduleInstance.GetExportedFunctionAddress(funcName); var bp = DkmRuntimeInstructionBreakpoint.Create(Guids.LocalComponentGuid, null, addr, false, null); if (enable) { bp.Enable(); } runtimeBreakpoints.Handlers.Add(bp.UniqueId, handler); return(bp); }
public static DkmRuntimeInstructionBreakpoint CreateRuntimeDllFunctionBreakpoint(DkmNativeModuleInstance moduleInstance, string funcName, RuntimeDllBreakpointHandler handler, bool enable = false, bool debugStart = false) { var addr = moduleInstance.GetFunctionAddress(funcName, debugStart); return(CreateBreakpoint(moduleInstance.Process, addr, handler, enable)); }
public static DkmNativeInstructionAddress GetFunctionAddress(this IDiaSymbol moduleSym, string name, DkmNativeModuleInstance moduleInstance) { using (var funSym = moduleSym.GetSymbol(SymTagEnum.SymTagFunction, name)) { return DkmNativeInstructionAddress.Create(moduleInstance.Process.GetNativeRuntimeInstance(), moduleInstance, funSym.Object.relativeVirtualAddress, null); } }
internal static Guid?CreateTargetFunctionBreakpointAtDebugEnd(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, out ulong breakAddress) { var address = TryGetFunctionAddressAtDebugEnd(moduleWithLoadedLua, name, out string error); if (address != null) { LocalComponent.log.Debug($"Hooking Lua '{desc}' ({name}) function (address 0x{address.Value:x})"); var nativeAddress = process.CreateNativeInstructionAddress(address.Value); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); breakAddress = address.Value; return(breakpoint.UniqueId); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{name}' with {error}"); } breakAddress = 0; return(null); }
internal static Guid?CreateTargetFunctionBreakpointAtDebugStart(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, out ulong breakAddress) { DkmRuntimeInstructionBreakpoint breakpoint = CreateTargetFunctionBreakpointObjectAtDebugStart(process, moduleWithLoadedLua, name, desc, out breakAddress, true); if (breakpoint != null) { return(breakpoint.UniqueId); } return(null); }
internal static DkmRuntimeInstructionBreakpoint CreateTargetFunctionBreakpointObjectAtAddress(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, ulong address, bool enabled) { if (address != 0) { LocalComponent.log.Debug($"Hooking Lua '{desc}' ({name}) function (address 0x{address:x})"); var nativeAddress = process.CreateNativeInstructionAddress(address); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); if (enabled) { breakpoint.Enable(); } return(breakpoint); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{name}' with missing address"); } return(null); }
void IDkmProcessExecutionNotification.OnProcessPause(DkmProcess process, DkmProcessExecutionCounters processCounters) { try { ulong?moduleBaseOpt = DebugHelpers.ReadPointerVariable(process, "nullcModuleStartAddress"); // Check if nullc is available if (moduleBaseOpt == null) { return; } var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(process); if (processData.language == null) { processData.compilerId = new DkmCompilerId(DebugHelpers.NullcCompilerGuid, DebugHelpers.NullcLanguageGuid); processData.language = DkmLanguage.Create("nullc", processData.compilerId); } // Create VM runtime and module if (processData.vmRuntimeInstance == null) { DkmRuntimeInstanceId runtimeId = new DkmRuntimeInstanceId(DebugHelpers.NullcVmRuntimeGuid, 0); processData.vmRuntimeInstance = DkmCustomRuntimeInstance.Create(process, runtimeId, null); } if (processData.vmModule == null) { DkmModuleId moduleId = new DkmModuleId(Guid.NewGuid(), DebugHelpers.NullcSymbolProviderGuid); processData.vmModule = DkmModule.Create(moduleId, "nullc.vm.code", processData.compilerId, process.Connection, null); } if (processData.vmModuleInstance == null) { DkmDynamicSymbolFileId symbolFileId = DkmDynamicSymbolFileId.Create(DebugHelpers.NullcSymbolProviderGuid); processData.vmModuleInstance = DkmCustomModuleInstance.Create("nullc_vm", "nullc.vm.code", 0, processData.vmRuntimeInstance, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, 0, 1, 0, "nullc vm code", false, null, null, null); processData.vmModuleInstance.SetModule(processData.vmModule, true); // Can use reload? } ulong moduleBase = moduleBaseOpt.GetValueOrDefault(0); uint moduleSize = (uint)(DebugHelpers.ReadPointerVariable(process, "nullcModuleEndAddress").GetValueOrDefault(0) - moduleBase); // Create JiT runtime and module if (moduleBase != 0 && moduleSize != 0) { if (processData.runtimeInstance == null && processData.nativeRuntimeInstance == null) { DkmRuntimeInstanceId runtimeId = new DkmRuntimeInstanceId(DebugHelpers.NullcRuntimeGuid, 0); if (DebugHelpers.useNativeInterfaces) { processData.nativeRuntimeInstance = DebugHelpers.useDefaultRuntimeInstance ? process.GetNativeRuntimeInstance() : DkmNativeRuntimeInstance.Create(process, runtimeId, DkmRuntimeCapabilities.None, process.GetNativeRuntimeInstance(), null); } else { processData.runtimeInstance = DkmCustomRuntimeInstance.Create(process, runtimeId, null); } } if (processData.module == null) { DkmModuleId moduleId = new DkmModuleId(Guid.NewGuid(), DebugHelpers.NullcSymbolProviderGuid); processData.module = DkmModule.Create(moduleId, "nullc.embedded.code", processData.compilerId, process.Connection, null); } if (processData.moduleInstance == null && processData.nativeModuleInstance == null) { DkmDynamicSymbolFileId symbolFileId = DkmDynamicSymbolFileId.Create(DebugHelpers.NullcSymbolProviderGuid); if (DebugHelpers.useNativeInterfaces) { processData.nativeModuleInstance = DkmNativeModuleInstance.Create("nullc", "nullc.embedded.code", 0, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, 1, "nullc embedded code", processData.nativeRuntimeInstance, moduleBase, moduleSize, Microsoft.VisualStudio.Debugger.Clr.DkmClrHeaderStatus.NativeBinary, false, null, null, null); processData.nativeModuleInstance.SetModule(processData.module, true); // Can use reload? } else { processData.moduleInstance = DkmCustomModuleInstance.Create("nullc", "nullc.embedded.code", 0, processData.runtimeInstance, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, moduleBase, 1, moduleSize, "nullc embedded code", false, null, null, null); processData.moduleInstance.SetModule(processData.module, true); // Can use reload? } } } // Update bytecode var moduleBytecodeVersion = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeVersion").GetValueOrDefault(0); if (processData.moduleBytecodeLocation != 0 && moduleBytecodeVersion != processData.moduleBytecodeVersion) { processData.moduleBytecodeLocation = 0; processData.moduleBytecodeSize = 0; processData.moduleBytecodeRaw = null; processData.bytecode = null; } if (processData.moduleBytecodeLocation == 0) { processData.moduleBytecodeLocation = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeLocation").GetValueOrDefault(0); processData.moduleBytecodeSize = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeSize").GetValueOrDefault(0); processData.moduleBytecodeVersion = moduleBytecodeVersion; if (processData.moduleBytecodeLocation != 0) { processData.moduleBytecodeRaw = new byte[processData.moduleBytecodeSize]; process.ReadMemory(processData.moduleBytecodeLocation, DkmReadMemoryFlags.None, processData.moduleBytecodeRaw); processData.bytecode = new NullcBytecode(); processData.bytecode.ReadFrom(processData.moduleBytecodeRaw, DebugHelpers.Is64Bit(process)); // Notify local component about bytecode update var message = DkmCustomMessage.Create(process.Connection, process, DebugHelpers.NullcReloadSymbolsMessageGuid, 1, null, null); message.SendHigher(); } } } catch (Exception ex) { Console.WriteLine("OnProcessPause failed with: " + ex.ToString()); } }
public static DkmNativeInstructionAddress GetFunctionAddress(this IDiaSymbol moduleSym, string name, DkmNativeModuleInstance moduleInstance) { using (var funSym = moduleSym.GetSymbol(SymTagEnum.SymTagFunction, name)) { return(DkmNativeInstructionAddress.Create(moduleInstance.Process.GetNativeRuntimeInstance(), moduleInstance, funSym.Object.relativeVirtualAddress, null)); } }