/// <summary>
/// Finds the specified function in the remote module.
/// </summary>
/// <param name="functionName">The name of the function (case sensitive).</param>
/// <returns>A new instance of a <see cref="RemoteFunction" /> class.</returns>
/// <remarks>
/// Interesting article on how DLL loading works: http://msdn.microsoft.com/en-us/magazine/bb985014.aspx
/// </remarks>
public RemoteFunction FindFunction(string functionName)
{
// Create the tuple
var tuple = Tuple.Create(functionName, MemorySharp.Handle);
// Check if the function is already cached
if (CachedFunctions.ContainsKey(tuple))
{
return(CachedFunctions[tuple]);
}
// If the function is not cached
// Check if the local process has this module loaded
var localModule =
Process.GetCurrentProcess()
.Modules.Cast <ProcessModule>()
.FirstOrDefault(m => string.Equals(m.FileName, Path, StringComparison.CurrentCultureIgnoreCase));
var isManuallyLoaded = false;
try
{
// If this is not the case, load the module inside the local process
if (localModule == null)
{
isManuallyLoaded = true;
localModule = ModuleCore.LoadLibrary(Native.FileName);
}
// Get the offset of the function
var offset = ModuleCore.GetProcAddress(localModule, functionName).ToInt64() -
localModule.BaseAddress.ToInt64();
// Rebase the function with the remote module
var function = new RemoteFunction(MemorySharp, new IntPtr(Native.BaseAddress.ToInt64() + offset),
functionName);
// Store the function in the cache
CachedFunctions.Add(tuple, function);
// Return the function rebased with the remote module
return(function);
}
finally
{
// Free the module if it was manually loaded
if (isManuallyLoaded)
{
ModuleCore.FreeLibrary(localModule);
}
}
}