/// <summary> /// Parse all RPC servers from a PE file. /// </summary> /// <param name="file">The PE file to parse.</param> /// <param name="dbghelp_path">Path to a DBGHELP DLL to resolve symbols.</param> /// <param name="symbol_path">Symbol path for DBGHELP</param> /// <param name="flags">Flags for the RPC parser.</param> /// <remarks>This only works for PE files with the same bitness as the current process.</remarks> /// <returns>A list of parsed RPC server.</returns> public static IEnumerable <RpcServer> ParsePeFile(string file, string dbghelp_path, string symbol_path, RpcServerParserFlags flags) { List <RpcServer> servers = new List <RpcServer>(); using (var result = SafeLoadLibraryHandle.LoadLibrary(file, LoadLibraryFlags.DontResolveDllReferences, false)) { if (!result.IsSuccess) { return(servers.AsReadOnly()); } var lib = result.Result; var sections = lib.GetImageSections(); var offsets = sections.SelectMany(s => FindRpcServerInterfaces(s, flags.HasFlagSet(RpcServerParserFlags.ParseClients))); if (offsets.Any()) { SymbolResolverFlags symbol_flags = flags.HasFlagSet(RpcServerParserFlags.SymSrvFallback) ? SymbolResolverFlags.SymSrvFallback : SymbolResolverFlags.None; using (var sym_resolver = !flags.HasFlagSet(RpcServerParserFlags.IgnoreSymbols) ? SymbolResolver.Create(NtProcess.Current, dbghelp_path, symbol_path, symbol_flags, null) : null) { NdrParserFlags parser_flags = NdrParserFlags.IgnoreUserMarshal; if (flags.HasFlagSet(RpcServerParserFlags.ResolveStructureNames)) { parser_flags |= NdrParserFlags.ResolveStructureNames; } foreach (var offset in offsets) { IMemoryReader reader = new CurrentProcessMemoryReader(sections.Select(s => Tuple.Create(s.Data.DangerousGetHandle().ToInt64(), (int)s.Data.ByteLength))); NdrParser parser = new NdrParser(reader, NtProcess.Current, sym_resolver, parser_flags); IntPtr ifspec = lib.DangerousGetHandle() + (int)offset.Offset; try { var rpc = parser.ReadFromRpcServerInterface(ifspec, lib.DangerousGetHandle()); servers.Add(new RpcServer(rpc, parser.ComplexTypes, file, offset.Offset, offset.Client)); } catch (NdrParserException) { } } } } } return(servers.AsReadOnly()); }
internal DbgHelpSymbolResolver(NtProcess process, string dbghelp_path, string symbol_path, SymbolResolverFlags flags, TextWriter trace_writer) { Process = process.Duplicate(); _dbghelp_lib = SafeLoadLibraryHandle.LoadLibrary(dbghelp_path); GetFunc(ref _sym_init); GetFunc(ref _sym_cleanup); GetFunc(ref _sym_from_name); GetFunc(ref _sym_set_options); GetFunc(ref _sym_enum_modules); GetFunc(ref _sym_from_addr); GetFunc(ref _sym_get_module_info); GetFunc(ref _sym_load_module); GetFunc(ref _sym_refresh_module_list); GetFunc(ref _sym_enum_types); GetFunc(ref _sym_get_type_from_name); GetFunc(ref _sym_enum_types_by_name); GetFunc(ref _sym_get_type_info); GetFunc(ref _sym_get_type_info_dword, "SymGetTypeInfo"); GetFunc(ref _sym_get_type_info_ptr, "SymGetTypeInfo"); GetFunc(ref _sym_get_type_info_var, "SymGetTypeInfo"); GetFunc(ref _sym_get_type_info_long, "SymGetTypeInfo"); GetFunc(ref _sym_from_index); GetFunc(ref _sym_enum_symbols); GetFunc(ref _sym_set_context); GetFunc(ref _sym_get_home_directory); _trace_writer = trace_writer ?? new TraceTextWriter(); SymOptions options = SymOptions.INCLUDE_32BIT_MODULES | SymOptions.UNDNAME | SymOptions.DEFERRED_LOADS; _enable_symsrv_fallback = flags.HasFlagSet(SymbolResolverFlags.SymSrvFallback) && !CheckForSymsrv(_dbghelp_lib.FullPath); _trace_symbol_loading = flags.HasFlagSet(SymbolResolverFlags.TraceSymbolLoading); if (_trace_symbol_loading) { options |= SymOptions.DEBUG; } if (_enable_symsrv_fallback) { var srv = GetFallbackSymbolPaths(symbol_path); _symbol_cache_path = srv.Item1; _symbol_server_path = srv.Item2; if (string.IsNullOrEmpty(_symbol_cache_path)) { throw new ArgumentException("Must specify an existing local path in the symbol path to store downloaded symbols."); } options |= SymOptions.DEBUG; } if (flags.HasFlagSet(SymbolResolverFlags.DisableExportSymbols)) { options |= SymOptions.EXACT_SYMBOLS; } _sym_set_options(options); if (!_sym_init(Handle, symbol_path, true)) { // If SymInitialize failed then we'll have to bootstrap modules manually. if (!_sym_init(Handle, symbol_path, false)) { throw new Win32Exception(); } IntPtr[] modules = new IntPtr[1024]; if (Win32NativeMethods.EnumProcessModulesEx(Handle, modules, modules.Length * IntPtr.Size, out int return_length, process.Is64Bit ? EnumProcessModulesFilter.LIST_MODULES_64BIT : EnumProcessModulesFilter.LIST_MODULES_32BIT)) { foreach (IntPtr module in modules.Take(return_length / IntPtr.Size)) { StringBuilder dllpath = new StringBuilder(260); if (Win32NativeMethods.GetModuleFileNameEx(Handle, module, dllpath, dllpath.Capacity) > 0) { if (_sym_load_module(Handle, IntPtr.Zero, dllpath.ToString(), Path.GetFileNameWithoutExtension(dllpath.ToString()), module.ToInt64(), GetImageSize(module)) == 0) { Debug.WriteLine($"Couldn't load {dllpath}"); } } } } } if (_trace_symbol_loading || _enable_symsrv_fallback) { _callback_handler = DbgHelpDebugCallbackHandler.GetInstance(_dbghelp_lib); _callback_handler.RegisterHandler(Handle, SymDebugCallback); } }
/// <summary> /// Create a new instance of a symbol resolver. /// </summary> /// <param name="process">The process in which the symbols should be resolved.</param> /// <param name="dbghelp_path">The path to dbghelp.dll, ideally should use the one which comes with Debugging Tools for Windows.</param> /// <param name="symbol_path">The symbol path.</param> /// <param name="flags">Flags for the symbol resolver.</param> /// <param name="trace_writer">A text writer for output when specifying the <see cref="SymbolResolverFlags.TraceSymbolLoading">TraceSymbolLoading</see> flag.</param> /// <returns>The instance of a symbol resolver. Should be disposed when finished.</returns> public static ISymbolResolver Create(NtProcess process, string dbghelp_path, string symbol_path, SymbolResolverFlags flags, TextWriter trace_writer) { return(new DbgHelpSymbolResolver(process, dbghelp_path, symbol_path, flags, trace_writer)); }