I am trying to use EasyHook to detect native LoadLibrary calls.
It indeed detects the loading of libraries, however the process results in freezing.
This is because the LoadLibrary_Hook method below cannot load the dll or library since It returns 0 IntPtr (Probably can't find the library.).
I even tried setting the events to a "void" type but then the process simply crashes, this is probably because EasyHook expects me to return a value to overwrite the function.
Is there a way for me to return the exactly needed library to be loaded, or just simply get the name of the library that is being loaded without me having to load the library manually?
(There are also names like this which are loading in the process: 瑮汤汤l邐邐讐嗿謘ౕ㍓四襗ﱝ嶉觬嶉觰嶉㯨࿓トă謀ࡅ쌻萏Ͽ䶋㬔瓋㤉ᡝ萏ϯ팻Ѵ᪉ᢉ疋㬐ă㬀瓋謇ᡅᦉᢉ綋㬜 which is kinda odd...)
private static LocalHook hook;
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
public static extern IntPtr GetProcAddress(IntPtr handle, string varormethodname);
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
public delegate IntPtr LoadLibraryDelegate(string lpFileName);
public TestHook()
{
IntPtr kernel32 = GetModuleHandle("kernel32.dll");
Logger.Log("Kernel: " + kernel32);
IntPtr address = GetProcAddress(kernel32, "LoadLibraryA");
Logger.Log("Address: " + address);
hook = LocalHook.Create(address,
new LoadLibraryDelegate(LoadLibrary_Hook),
null);
hook.ThreadACL.SetExclusiveACL(new Int32[] {0});
//RemoteHooking.WakeUpProcess();
}
public IntPtr LoadLibrary_Hook(string lpFileName)
{
Logger.Log("File load: " + lpFileName);
return LoadLibrary(lpFileName);
}
Solution was to call the original method using the original function address:
public IntPtr LoadLibrary_Hook(string lpFileName)
{
Logger.Log("File load: " + lpFileName);
LoadLibraryDelegate origMethod = (LoadLibraryDelegate)Marshal.GetDelegateForFunctionPointer(LoadLibraryAddress, typeof(LoadLibraryDelegate));
return origMethod(lpFileName);
}
Related
I have a C++ dll for monitoring printers (using FindFirstPrinterChangeNotification). I am making C# Wrapper for it:
private static class NativeMethods {
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32", SetLastError = true)]
public static extern bool FreeLibrary(IntPtr hModule);
}
public string LibPath;
private IntPtr LibPtr;
private GBtMX GBtMain;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void GBtMX();
public GhostBuster() {
LibPath = AppDomain.CurrentDomain.BaseDirectory + #"\GhostBusterC.dll";
}
public string Init() {
if (!File.Exists(LibPath))
return "Incorrect path " + LibPath;
LibPtr = NativeMethods.LoadLibrary(LibPath);
if (LibPtr == IntPtr.Zero)
return "Couldn't import library. Error(GetLastWin32Error): " + Marshal.GetLastWin32Error().ToString();
IntPtr GBtMainPtr = NativeMethods.GetProcAddress(LibPtr, "tmain");
if (GBtMainPtr == IntPtr.Zero)
return "No access to GhostBuster.tmain. Error (GetLastWin32Error): " + Marshal.GetLastWin32Error().ToString();
GBtMain = (GBtMX)Marshal.GetDelegateForFunctionPointer(GBtMainPtr, typeof(GBtMX));
return "";
It returns "No access to GhostBuster.tmain. Error (GetLastWin32Error): 0".
What am i doing wrong?
Thanks in advance.
You don't specify SetLastError in your p/invoke, so that's why Marshal.GetLastWin32Error() is failing to return anything useful. The p/invoke should be
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(
IntPtr hModule,
[MarshalAs(UnmanagedType.LPStr)]
string lpProcName
);
Note also that it makes sense to be explicit about the marshaling of the procedure name. That is always an ANSI string, reflecting the PE format.
When you make this change I expect that the error will be ERROR_PROC_NOT_FOUND indicating that the DLL does not export anything with the name that you passed to GetProcAddress.
Check that you spelled the function name correctly. Did you get the letter case right? Is there any decoration or mangling applied when the DLL is built? Use a tool like dumpbin or Dependency Walker to check the names of the DLL's exports.
I'am going to use a kernel32 dll in asp.net web application. This is the code:
//DllGetClassObject function pointer signature
private delegate int DllGetClassObject(ref Guid ClassId, ref Guid InterfaceId, [Out, MarshalAs(UnmanagedType.Interface)] out object ppunk);
//Some win32 methods to load\unload dlls and get a function pointer
private class Win32NativeMethods
{
[DllImport("kernel32.dll", CharSet=CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string lpFileName);
}
public string GetTheDllHandle (dllName)
{
IntPtr dllHandle = Win32NativeMethods.LoadLibrary(dllName); // the dllHandle=IntPtr.Zero
return dllHandle.ToString();
}
The problem that when I call my function GetTheDllHandle, the dllHandle return zero
Did anybody out there made something similar? Or does anybody have any suggestions?
Returning 0 while loading DLLs is coming due to several reasons like , DLL is not there on specified path or DLLs is not supported with platform or dependent dlls are not loaded before you build your native DLL. so you can track these errors by set true for SetLastError property
DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
public string GetTheDllHandle (dllName)
{
IntPtr dllHandle = Win32NativeMethods.LoadLibrary(dllName); // the dllHandle=IntPtr.Zero
if (dllHandle == IntPtr.Zero)
return Marshal.GetLastWin32Error().ToString(); // Error Code while loading DLL
else
return dllHandle.ToString(); // Loading done !
}
I have a C dll with exported functions
I can use the command-line tool dumpbin.exe /EXPORTS to extract the list of exported functions, and then use them in my C# code to (successfully) call these functions.
Is there a way to get this exported-functions-list directly from .NET, without having to use an external command-line tool?
Thanks
As far as I know there is no class in the .Net Framework that
provides the information you need.
However you can use the platform invocation services (PInvoke) of the .Net platform to
use the functions of the Win32 dbghelp.dll DLL. This DLL is part of
the Debugging Tools for the Windows platform. The dbghelp DLL provides
a function called SymEnumerateSymbols64 which allows you to enumerate all
exported symbols of a dynamic link library. There is also a
newer function called SymEnumSymbols which also allows to enumerate
exported symbols.
The code below shows a simple example on how to use the SymEnumerateSymbols64
function.
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)]bool fInvadeProcess);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymCleanup(IntPtr hProcess);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile,
string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymEnumerateSymbols64(IntPtr hProcess,
ulong BaseOfDll, SymEnumerateSymbolsProc64 EnumSymbolsCallback, IntPtr UserContext);
public delegate bool SymEnumerateSymbolsProc64(string SymbolName,
ulong SymbolAddress, uint SymbolSize, IntPtr UserContext);
public static bool EnumSyms(string name, ulong address, uint size, IntPtr context)
{
Console.Out.WriteLine(name);
return true;
}
static void Main(string[] args)
{
IntPtr hCurrentProcess = Process.GetCurrentProcess().Handle;
ulong baseOfDll;
bool status;
// Initialize sym.
// Please read the remarks on MSDN for the hProcess
// parameter.
status = SymInitialize(hCurrentProcess, null, false);
if (status == false)
{
Console.Out.WriteLine("Failed to initialize sym.");
return;
}
// Load dll.
baseOfDll = SymLoadModuleEx(hCurrentProcess,
IntPtr.Zero,
"c:\\windows\\system32\\user32.dll",
null,
0,
0,
IntPtr.Zero,
0);
if (baseOfDll == 0)
{
Console.Out.WriteLine("Failed to load module.");
SymCleanup(hCurrentProcess);
return;
}
// Enumerate symbols. For every symbol the
// callback method EnumSyms is called.
if (SymEnumerateSymbols64(hCurrentProcess,
BaseOfDll, EnumSyms, IntPtr.Zero) == false)
{
Console.Out.WriteLine("Failed to enum symbols.");
}
// Cleanup.
SymCleanup(hCurrentProcess);
}
In order to keep the example simple I did not use the
SymEnumSymbols function. I've also did the example
without using such classes as the SafeHandle class of
the .Net framework. If you need a example for the
SymEnumSymbols function, just let me know.
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
static void Main(string[] args)
{
IntPtr handle = LoadLibrary(#"ItwNidSmart.dll");
if (handle == IntPtr.Zero)
{
try
{
int hr = Marshal.GetHRForLastWin32Error();
Marshal.ThrowExceptionForHR(hr);
}
catch (Exception ex)
{
Console.Write("Error: "+ ex.Message);
}
}
IntPtr proc = GetProcAddress(handle, "InitializeModule");
}
I try to load this native C++ library in my Windows 7 x64, but I got this error. I've already built this solution to x86 application.
The error occurs at the call to LoadLibrary().
You didn't actually state the exact error message, and which line it occurs on. Is it possible that you are erroneously linking to the 32 bit version of ItwNidSmart.dll?
In fact, your P/Invokes are wrong, which may or may not be the cause of your problem. The most important error is that GetProcAddress specifies the procedure name as an ANSI string. They should read:
[DllImport("kernel32", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
static extern UIntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
I'm not sure that these errors are actually causing you problems.
EDIT
You state in a comment that the failure occurs at the call to LoadLibrary(). If this raises an exception then the only explanation that I can come up with is that the fault lies in the DLLMain() of the DLL and not in the C# code. If the DLL was the wrong bitness, or not found, then LoadLibrary() would return NULL.
I think to solve this you need to look to the DLL and not the C# code.
My application should perform some action whenever user pressed certain keys in windows.
Calling SetWindowsHookEx with WH_KEYBOARD_LL option seems to be standard way to achieve this. However in my case something is clearly wrong and callback in not fired.
Main method of my debugging console application:
static void Main(string[] args)
{
IntPtr moduleHandle = GetCurrentModuleHandle();
IntPtr hookHandle = IntPtr.Zero;
try
{
User32.HookProc hook = (nCode, wParam, lParam) =>
{
// code is never called :-(
if (nCode >= 0)
{
Console.WriteLine("{0}, {1}", wParam.ToInt32(), lParam.ToInt32());
}
return User32.CallNextHookEx(hookHandle, nCode, wParam, lParam);
};
hookHandle = User32.SetWindowsHookEx(User32.WH_KEYBOARD_LL, hook, moduleHandle, 0);
Console.ReadLine(); //
}
finally
{
if (hoodHandle != IntPtr.Zero)
{
var unhooked = User32.UnhookWindowsHookEx(hookHandle);
Console.WriteLine(unhooked); // true
hookHandle = IntPtr.Zero;
}
}
}
GetCurrentModuleHandle method:
private static IntPtr GetCurrentModuleHandle()
{
using (var currentProcess = Process.GetCurrentProcess())
using (var mainModule = currentProcess.MainModule)
{
var moduleName = mainModule.ModuleName;
return Kernel32.GetModuleHandle(moduleName);
}
}
Imports from user32.dll and kernel32.dll:
public static class User32
{
public const int WH_KEYBOARD_LL = 13;
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
}
public static class Kernel32
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
}
Do you have any idea what I is my problem?
The SetwindowHook API cannot be called from a C# console application. You need to call it in a Windows DLL (it won't work in a .Net DLL).
There is certainly a way to work around this issue, and I did use it one of the applications I built a long while ago. But I don't remember it right now. You may be able to find out if you search long enough.
Is this a console app as Main(string[] args) and Console.ReadLine() would suggest?
if so then this might be the source of your problem
When you use the Win32 API like this, it is very important that you check for errors yourself. You no longer have the friendly .NET wrappers that will do it for you and throw an exception. This needs to be done in several places, but here's one:
hookHandle = User32.SetWindowsHookEx(User32.WH_KEYBOARD_LL, hook, moduleHandle, 0);
if (hookHandle == IntPtr.Zero) throw new Win32Exception();
The real problem is your use of mainModule.ModuleName. If only gives the name of the file, not the full path. GetModuleHandle() will fail and return IntPtr.Zero. As above, if you would have tested this then you'd have quickly found the problem.
There's an additional failure mode when you run this code in .NET 4.0. The CLR no longer fakes native modules for managed code. SetWindowsHookEx() needs a valid DLL handle but it doesn't actually use it since this is a low-level hook. The best way to get one is to ask for user32.dll, it is always loaded in a managed program:
IntPtr moduleHandle = LoadLibrary("user32.dll");
if (moduleHandle == IntPtr.Zero) throw new Win32Exception();
No need to release it.