/// <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="parse_clients">True to parse client RPC interfaces.</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, bool parse_clients) { List <RpcServer> servers = new List <RpcServer>(); using (var lib = SafeLoadLibraryHandle.LoadLibrary(file, LoadLibraryFlags.DontResolveDllReferences)) { var sections = lib.GetImageSections(); var offsets = sections.SelectMany(s => FindRpcServerInterfaces(s, parse_clients)); if (offsets.Any()) { using (var sym_resolver = SymbolResolver.Create(NtProcess.Current, dbghelp_path, symbol_path)) { 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, NdrParserFlags.IgnoreUserMarshal); IntPtr ifspec = lib.DangerousGetHandle() + (int)offset.Offset; var rpc = parser.ReadFromRpcServerInterface(ifspec); servers.Add(new RpcServer(rpc, parser.ComplexTypes, file, offset.Offset, offset.Client)); } } } } return(servers.AsReadOnly()); }
/// <summary> /// Get the manifests from a file. /// </summary> /// <param name="filename">The file to extract the manifests from.</param> /// <returns>The list of manifests.</returns> public static IEnumerable <ExecutableManifest> GetManifests(string filename) { string fullpath = Path.GetFullPath(filename); using (SafeLoadLibraryHandle library = SafeLoadLibraryHandle.LoadLibrary(fullpath, LoadLibraryFlags.LoadLibraryAsImageResource | LoadLibraryFlags.LoadLibraryAsDataFile)) { List <ExecutableManifest> manifests = new List <ExecutableManifest>(); Win32NativeMethods.EnumResourceNames(library, new IntPtr((int)ResType.MANIFEST), (a, b, c, d) => { try { manifests.Add(new ExecutableManifest(library, fullpath, c)); } catch (Win32Exception) { } catch (ArgumentException) { } return(true); }, IntPtr.Zero); return(manifests); } }
/// <summary> /// Load a library into memory. /// </summary> /// <param name="name">The path to the library.</param> /// <param name="flags">Additonal flags to pass to LoadLibraryEx</param> /// <returns></returns> public static SafeLoadLibraryHandle LoadLibrary(string name, LoadLibraryFlags flags) { SafeLoadLibraryHandle ret = Win32NativeMethods.LoadLibraryEx(name, IntPtr.Zero, flags); if (ret.IsInvalid) { throw new SafeWin32Exception(); } return(ret); }
/// <summary> /// Get the manifests from a file. /// </summary> /// <param name="filename">The file to extract the manifests from.</param> /// <returns>The list of manifests.</returns> public static IEnumerable <ExecutableManifest> GetManifests(string filename) { string fullpath = Path.GetFullPath(filename); using (SafeLoadLibraryHandle library = SafeLoadLibraryHandle.LoadLibrary(fullpath, LoadLibraryFlags.LoadLibraryAsImageResource | LoadLibraryFlags.LoadLibraryAsDataFile)) { return(library.GetResources(WellKnownImageResourceType.Manifest).Where(m => m.Size > 0) .Select(m => new ExecutableManifest(fullpath, m.ToArray())).ToArray()); } }
/// <summary> /// Format a message. /// </summary> /// <param name="module">The module containing the message.</param> /// <param name="message_id">The ID of the message.</param> /// <returns>The message. Empty string on error.</returns> public static string FormatMessage(SafeLoadLibraryHandle module, uint message_id) { if (Win32NativeMethods.FormatMessage(FormatFlags.AllocateBuffer | FormatFlags.FromHModule | FormatFlags.FromSystem | FormatFlags.IgnoreInserts, module.DangerousGetHandle(), message_id, 0, out SafeLocalAllocBuffer buffer, 0, IntPtr.Zero) > 0) { using (buffer) { return(Marshal.PtrToStringUni(buffer.DangerousGetHandle()).Trim()); } } return(string.Empty); }
internal ExecutableManifest(SafeLoadLibraryHandle hModule, string fullpath, IntPtr hName) { FullPath = fullpath; IntPtr hResHandle = Win32NativeMethods.FindResource(hModule, hName, new IntPtr((int)ResType.MANIFEST)); if (hResHandle == IntPtr.Zero) { throw new ArgumentException("Can't find manifest resource"); } IntPtr hResource = Win32NativeMethods.LoadResource(hModule, hResHandle); IntPtr buf = Win32NativeMethods.LockResource(hResource); int size = Win32NativeMethods.SizeofResource(hModule, hResHandle); if (size <= 0) { throw new ArgumentException("Invalid manifest size"); } byte[] manifest = new byte[size]; Marshal.Copy(buf, manifest, 0, size); MemoryStream stm = new MemoryStream(manifest); try { XmlDocument doc = LoadDocument(stm); UiAccess = GetUiAccess(doc); AutoElevate = GetAutoElevate(doc); ExecutionLevel = GetExecutionLevel(doc); LongPathAware = GetLongPathAware(doc); XmlWriterSettings settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true, NewLineOnAttributes = true }; StringWriter string_writer = new StringWriter(); XmlWriter writer = XmlWriter.Create(string_writer, settings); doc.Save(writer); ManifestXml = string_writer.ToString(); } catch (XmlException) { ParseError = true; ManifestXml = Encoding.UTF8.GetString(stm.ToArray()); } }
/// <summary> /// Load a library into memory. /// </summary> /// <param name="name">The path to the library.</param> /// <param name="flags">Additonal flags to pass to LoadLibraryEx</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>Handle to the loaded library.</returns> public static NtResult <SafeLoadLibraryHandle> LoadLibrary(string name, LoadLibraryFlags flags, bool throw_on_error) { SafeLoadLibraryHandle ret = Win32NativeMethods.LoadLibraryEx(name, IntPtr.Zero, flags); if (ret.IsInvalid) { if (throw_on_error) { throw new SafeWin32Exception(); } return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <SafeLoadLibraryHandle>(false)); } return(ret.CreateResult()); }
/// <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()); }
private void ParseDelayedImport(Dictionary <IntPtr, IntPtr> imports, ImageDelayImportDescriptor desc) { if (desc.pIAT == 0 || desc.pINT == 0) { return; } string name = Marshal.PtrToStringAnsi(RvaToVA(desc.szName)); IntPtr IAT = RvaToVA(desc.pIAT); IntPtr INT = RvaToVA(desc.pINT); try { using (SafeLoadLibraryHandle lib = LoadLibrary(name)) { IntPtr import_name_rva = Marshal.ReadIntPtr(INT); while (import_name_rva != IntPtr.Zero) { IntPtr import; // Ordinal if (import_name_rva.ToInt64() < 0) { import = lib.GetProcAddress(new IntPtr(import_name_rva.ToInt64() & 0xFFFF)); } else { IntPtr import_ofs = RvaToVA(import_name_rva.ToInt64() + 2); string import_name = Marshal.PtrToStringAnsi(import_ofs); import = lib.GetProcAddress(import_name); } if (import != IntPtr.Zero) { imports[IAT] = import; } INT += IntPtr.Size; IAT += IntPtr.Size; import_name_rva = Marshal.ReadIntPtr(INT); } } } catch (Win32Exception) { } }
/// <summary> /// Get the GetStagedPackageOrigin method as a delegate. It's supposed to be exposed by kernel32, /// but actually doesn't seem to be. /// </summary> /// <returns></returns> private static GetStagedPackageOrigin FindDelegate() { GetStagedPackageOrigin result = null; SafeLoadLibraryHandle kernel_base = SafeLoadLibraryHandle.GetModuleHandleNoThrow("kernelbase"); if (!kernel_base.IsInvalid) { result = kernel_base.GetFunctionPointer <GetStagedPackageOrigin>(false); } if (result != null) { return(result); } SafeLoadLibraryHandle kernel32 = SafeLoadLibraryHandle.GetModuleHandle("kernel32"); return(kernel32.GetFunctionPointer <GetStagedPackageOrigin>()); }
internal DbgHelpSymbolResolver(NtProcess process, string dbghelp_path, string symbol_path) { 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); _sym_set_options(SymOptions.INCLUDE_32BIT_MODULES | SymOptions.UNDNAME | SymOptions.DEFERRED_LOADS); 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]; int return_length; if (EnumProcessModulesEx(Handle, modules, modules.Length * IntPtr.Size, out 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 (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) { System.Diagnostics.Debug.WriteLine($"Couldn't load {dllpath}"); } } } } } }
internal static extern IntPtr FindResource(SafeLoadLibraryHandle hModule, IntPtr lpName, IntPtr lpType);
internal static extern int SizeofResource(SafeLoadLibraryHandle hModule, IntPtr hResInfo);
internal static extern bool EnumResourceNames(SafeLoadLibraryHandle hModule, IntPtr lpszType, EnumResNameProcDelegate lpEnumFunc, IntPtr lParam);
internal static extern bool GetModuleHandleEx(int dwFlags, string lpModuleName, out SafeLoadLibraryHandle phModule);
static extern bool GetModuleHandleEx(int dwFlags, IntPtr lpModuleName, out SafeLoadLibraryHandle phModule);
private static extern IntPtr LoadResource(SafeLoadLibraryHandle hModule, IntPtr hResInfo);