Skip to content

Instantly share code, notes, and snippets.

@smourier
Created November 6, 2024 18:17
Show Gist options
  • Save smourier/5c12886c75d25d0e1c8b9421629d6c55 to your computer and use it in GitHub Desktop.
Save smourier/5c12886c75d25d0e1c8b9421629d6c55 to your computer and use it in GitHub Desktop.
Enumerate Dll Exports in C#
public static class BinaryUtilities
{
[DllImport("dbghelp", CharSet = CharSet.Unicode)]
private static extern bool SymInitialize(nint hProcess, string? userSearchPath, bool fInvadeProcess);
[DllImport("dbghelp", CharSet = CharSet.Unicode)]
private static extern bool SymCleanup(nint hProcess);
[DllImport("dbghelp", CharSet = CharSet.Unicode)]
private static extern ulong SymLoadModuleEx(nint hProcess, nint hFile, string imageName, string? moduleName, long baseOfDll, int dllSize, nint data, int flags);
[DllImport("dbghelp", CharSet = CharSet.Unicode)]
private static extern bool SymEnumerateSymbols64(nint hProcess, ulong baseOfDll, PSYM_ENUMSYMBOLS_CALLBACK64 enumSymbolsCallback, nint userContext);
private delegate bool PSYM_ENUMSYMBOLS_CALLBACK64(string symbolName, ulong symbolAddress, uint symbolSize, nint userContext);
private static readonly ConcurrentDictionary<string, IReadOnlySet<string>> _exports = new(StringComparer.OrdinalIgnoreCase);
public static IReadOnlySet<string> GetExports(string dllPath)
{
ArgumentNullException.ThrowIfNull(dllPath);
if (!_exports.TryGetValue(dllPath, out var exports))
{
var handle = Process.GetCurrentProcess().Handle;
if (!SymInitialize(handle, null, false))
return new HashSet<string>();
var address = SymLoadModuleEx(handle, 0, dllPath, null, 0, 0, 0, 0);
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (address != 0)
{
SymEnumerateSymbols64(handle, address, (n, a, s, c) =>
{
set.Add(n);
return true;
}, 0);
}
SymCleanup(handle);
_exports[dllPath] = set;
exports = set;
}
return exports;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment