detect all dependencies of an application during runtime - c#

I had the following question regarding the searching of all dependencies of a dll during runtime.
I have general.dll which reads different files (other dlls, *.amd etc.) according to the used methods. I use this dll in my application, for example, Sample.exe (C#).
I am able to detect all dependencies (for Sample.exe) during runtime using Process Monitor (using filter by process name).
Please, prompt me how I can detect programmatically all dependencies which Sample.exe (with embedded general.dll) uses (reads) during runtime, i.e. what I need use in order to develop (in C#) similar functionality like in Process Monitor.
Thanks!

For C#/.NET directly:
You can use classes from System.Diagnostics, the property Process.Modules will fetch you a list of modules that have been loaded by the associated process, you can list all processes by calling Processes.GetProcesses().
For C++ side or if you want to invoke platform APIs:
You are looking for Win32 function EnumProcessModules(), which allows you to list all the modules (DLLs) loaded in a process referenced by a handle (which you can OpenProcess() by PID or whatever).
There is even a full example called Enumerating All Modules For a Process.
Detecting also other opened files:
I noticed late you wanted to detect also any other opened files, so I suggest the following hack: Hook Win32 API CreateFileW() (the Wide version is enough, Ascii one is just its wrapper) and log whatever is being opened (not only created, the function name can be misleading).
This is a working example code which shows what you'd need to do:
#include <windows.h>
#include <cstdio>
#include <cassert>
typedef HANDLE (WINAPI *CreateFileWType)(LPCWSTR, DWORD, DWORD,
LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
CreateFileWType origCreateFile;
HANDLE WINAPI myCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
// Log something about the file
printf("*** %S [%c%c]\n",
lpFileName,
(dwDesiredAccess & GENERIC_READ) ? 'R' : '-',
(dwDesiredAccess & GENERIC_WRITE) ? 'W' : '-');
// Call the original function
return origCreateFile(lpFileName, dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, hTemplateFile);
}
int main()
{
// Get pointer to the function and verify it can be hot-patched
HMODULE hKernelBase = GetModuleHandle(TEXT("KernelBase"));
BYTE* addr = reinterpret_cast<BYTE*>(GetProcAddress(hKernelBase, "CreateFileW"));
assert(addr != NULL);
assert(addr[0] == 0x8B && addr[1] == 0xFF); // `mov edi, edi` prologue
// Save the original function location (after the prologue)
origCreateFile = reinterpret_cast<CreateFileWType>(addr + 2);
// Hot-patch the function to call our hook
DWORD dwOldProtect;
VirtualProtect(addr - 5, 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);
addr[-5] = 0xE9; // jmp ...
*reinterpret_cast<DWORD*>(&addr[-4]) = reinterpret_cast<BYTE*>(&myCreateFileW) - addr;
*reinterpret_cast< WORD*>(&addr[ 0]) = 0xF9EB; // jmps $-5
VirtualProtect(addr - 5, 7, dwOldProtect, &dwOldProtect);
// Test that it all works - original application would continue here
fopen("input.txt", "r");
fopen("output.txt", "w");
return 0;
}
Example output:
*** input.txt [R-]
*** output.txt [-W]
This won't log any low-level system operations like loading DLLs, because such things are using NT call NtCreateFile() directly, but should work for most cases of file access fine. Also more error checking, converting into Managed C++/CLR or whatever is left as an exercise to the reader.

One of the possible approach could be that you dynamically inject a seperate dll (which can return back all the information) in process Sample.exe. For concept please refer
http://support.microsoft.com/kb/197571
Once the dll is loaded in Sample.exe you can extract all necessary information through your application
Edit: Please refer below link, it could be helpful
http://www.codeproject.com/Articles/38438/Monitoring-Process-Statistics-in-C-WPF

Related

How to use complex data types from External Dependencies with DllImport in C#

I have a win32 API library .dll file for some hardware that I need to access in c#. I believe using DllImport to create a wrapper class for the .dll that makes it usable in my C# uwp application.
The first function I believe have done correctly
(C code)
ADIOLIB_API
aDIO_Error WINAPI aDIO_General_Enum(aDIO_Enum_Info* DeviceList,
uint8 ListSize)
(C# code)
[DllImport("aDIOLib.dll")] static extern aDIO_Error aDIO_General_Enum(ref aDIO_Enum_Info DeviceList, Byte ListSize);
public static aDIO_Error aDIOGeneralEnum(ref aDIO_Enum_Info DeviceList, Byte ListSize)
{
return aDIO_General_Enum(ref DeviceList, ListSize);
}
public struct aDIO_Enum_Info
{
UInt32 dev_num;
aDIO_Intrfc_Avail availability;
UInt32 base_address;
UInt32 irq;
bool has_wake;
}
aDIO_Error is just a UInt32 error code, so that part has been handled as well.
When I moved on to the next function to create a wrapper for it I ran into this issue. So the function header is like this:
ADIOLIB_API
aDIO_Error WINAPI aDIO_General_Open(aDIO_Enum_Info DeviceInfo,
aDIO_Handle* Handle)
After thinking the aDIO_Handle is probably another struct that I have to replicate in C#, I looked at the declaration for it and found this:
typedef struct
{
/**
Holds a critical section object used to control access to all library
state and functionality.
*/
CRITICAL_SECTION global_lock;
/**
Holds a handle to the aDIO device file. (Used to send IOCTLs to the
driver.)
*/
HANDLE dev_file;
/**
Holds device/board information retrieved from the driver.
*/
aDIO_Intrfc_Board_Info dev_info;
/**
Holds a critical section object used to control access to the error
logging function and the last error message.
*/
CRITICAL_SECTION log_section;
/**
Holds the last un-retrieved error message.
*/
char last_error_msg[ADIO_ERROR_MAX_MSG_LENGTH];
/**
Holds a pointer to the structure holding the state of the Interrupt
module.
*/
void* int_state;
} aDIO_Descriptor, *aDIO_Handle;
Both the HANDLE and CRITICAL_SECTION types are from external dependencies (minwinbase.h and winnt.h) in which this dll has like 100s of external header files. How am i supposed to make a DllImport for this aDIO_General_Open function without recreating all the header files in the process.
Any help would be much appreciated.
Please ask me questions to clarify if you have any! I am new to this DllImport stuff

Calling a function of a 32-bit DLL from a 64-bit Application

I have a 32bit dll (no source code) that I need to access from 64bit C# application. I've read this article and took a look into the corresponding code from here. I've also read this post.
I'm not sure that I'm asking the right question, so please help me.
There are 3 projects: dotnetclient, x86Library and x86x64. The x86x64 has x86LibraryProxy.cpp which loads the x86library.dll and calls the GetTemperature function:
STDMETHODIMP Cx86LibraryProxy::GetTemperature(ULONG sensorId, FLOAT* temperature)
{
*temperature = -1;
typedef float (__cdecl *PGETTEMPERATURE)(int);
PGETTEMPERATURE pFunc;
TCHAR buf[256];
HMODULE hLib = LoadLibrary(L"x86library.dll");
if (hLib != NULL)
{
pFunc = (PGETTEMPERATURE)GetProcAddress(hLib, "GetTemperature");
if (pFunc != NULL)
dotnetclient calls that GetTemperature function and print the result:
static void Main(string[] args)
{
float temperature = 0;
uint sensorId = 2;
var svc = new x86x64Lib.x86LibraryProxy();
temperature = svc.GetTemperature(sensorId);
Console.WriteLine($"temperature of {sensorId} is {temperature}, press any key to exit...");
This all works if I build all projects either as x86 or x64. The result for the temperature I get is 20. But, the whole idea was to use 32bit x86x64Lib.dll. That means that dotnetclient should be built as x64 and x86Library and x86x64 as x86, right? If I do this I get -1 as a result.
Should I build x86Library and x86x64 as x86 and dotnetclient as x64? If I do, so what can be the problem that I get -1?
CLARIFICATION
It seems that the provided example only works when both client and server are build in 32 or 64 bit. But not when the client build in 64bit and the server in 32bit. Can someone take a look please?
IMHO, the easiest way to do this is to use COM+ (Component Services) which is part of Windows for like 20 years or so (previous versions used to be called MTS...). It provides the surrogate infrastructure for you with tools, UI, and everything you need.
But that means you'll have to use COM, so it's good to know a bit of COM for this.
First create an x86 COM DLL. I've used ATL for that. Created an ATL project, added an ATL simple object to it, added the method to the IDL and implementation.
.idl (note the [out, retval] attributes so the temperature is considered a return value for higher level languages including .NET):
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(f9988875-6bf1-4f3f-9ad4-64fa220a5c42),
dual,
nonextensible,
pointer_default(unique)
]
interface IMyObject : IDispatch
{
HRESULT GetTemperature(ULONG sensorId, [out, retval] FLOAT* temperature);
};
[
uuid(2de2557f-9bc2-42ef-8c58-63ba77834d0f),
version(1.0),
]
library x86LibraryLib
{
importlib("stdole2.tlb");
[
uuid(b20dcea2-9b8f-426d-8d96-760276fbaca9)
]
coclass MyObject
{
[default] interface IMyObject;
};
};
import "shobjidl.idl";
Method implementation for testing purposes:
STDMETHODIMP GetTemperature(ULONG sensorId, FLOAT* temperature)
{
*temperature = sizeof(void*); // should be 4 in x86 :-)
return S_OK;
}
Now, you must register this component in the 32-bit registry (in fact, if you're running Visual Studio w/o admin rights, it will complain at compile time that the component cannot be registered, that's expected), so on a 64-bit OS, you must run something like this (note SysWow64) with admin rights:
c:\Windows\SysWOW64\regsvr32 x86Library.dll
Once you've done that, run "Component Services", browse "Computers/My Computer/COM+ Applications", right click and create a New Application. Choose a name and a "Server application". It means your component will be hosted in COM+ surrogate process.
Once you've done that, browse "Components", right click and create a New Component. Make sure you select "32-bit registry". You should see your object's ProgId. In my case when I created my ATL project I added "MyObject" as a Progid, but otherwise it could be named something like "x86Library.MyObject" or "x86LibraryLib.MyObject"... If it's not there, than you made some mistake earlier.
That's it. Now, this .NET program will always be able to run, compiled as AnyCpu or x86 or x64:
class Program
{
static void Main(string[] args)
{
var type = Type.GetTypeFromProgID("MyObject"); // the same progid
dynamic o = Activator.CreateInstance(type);
Console.WriteLine(o.GetTemperature(1234)); // always displays 4
}
}
You can use Component Services UI to configure your surrogate (activation, shutdown, etc.). It also has an API so you can create COM+ apps programmatically.
You are not going to be able to directly call 32-bit code from 64-bit code (or the other way around), it simply is not going to happen.
There are alternatives, such as creating a 32-bit COM host program that then forwards calls to the DLL. Coupled with that you use DCOM standard marshalling so your 64-bit process can connect to the 32-bit host.
But if recompiling the 32-bit DLL is at all an option that is almost certainly your best option.

Code Access Security is preventing PInvoking Setup API calls

I'm rewording this question since I understand a bit more now. Originally, what I had was too vague. I've discovered that I'm being routed by something called "Code Access Security." This is old-hat to everyone reading this, I'm sure, but not to me.
The application is very large so in a nutshell I have two assemblies. One is a utilities assembly with various "tools" used throughout the program. The other is calling upon these tools in order to function.
In the utilities assembly, there are many functions that are PInvoked but the one giving me grief is: SetupDiGetDeviceInterfaceDetail() (see here). My function prototype looks like this:
[DllImport("SetupApi.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(
SafeHandleZeroOrMinusOneIsInvalid deviceInfoSet,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
uint deviceInterfaceDetailDataSize,
IntPtr requiredSize,
IntPtr deviceInfoData);
In the assembly which uses this function, I'm using the two step process outlined in the remarks in order to gain the understanding of how much space I need to store the DevicePath which is in the SP_DEVICE_INTERFACE_DETAIL_DATA structure (see here). For example:
string GetDevicePath(SafeHandleSeroOrMinusOneIsInvalid hList, SP_DEVICE_INTERFACE_DATA infoSet)
{
IntPtr pReqSize = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(pReqSize, 0);
uint reqSize;
// get the size needed
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
IntPtr.Zero,
0,
pReqSize,
IntPtr.Zero);
reqSize = (uint)Marshal.ReadInt32(pReqSize, 0);
IntPtr pDevInfoDetail = Marshal.AllocHGlobal((int)reqSize + 4); // +4 for cbSize
// call again, this time getting the actual data wanted
PInvoke.SetupDiGetDeviceInterfaceDetail(hList,
ref infoSet,
pDevInfoDetail,
reqSize,
IntPtr.Zero,
IntPtr.Zero);
string path;
// work .NET magic to read from unmanaged memory the path string and assign it
// to the above variable. Deallocate both unmanaged memory blocks.
return path;
}
The most frustrating thing is, these assemblies are used by two different programs. One is a GUI using the Visual Studio Isolated Shell. The other is simply a command line program. When the GUI is running, the above code is called and executes as expected. In the command line tool however, they fail (as described in the MSDN reference for this Setup API function) with some data about what happened. At this point, I'm able only to recover a portion of the data that is returned.
This is what comes back from the runtime:
stem.Security.PartialTrustVisibilityLevel, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
I know this has something to do with Code Access Security but I'm not at all sure how to fix. Using some suggestions that I've found thus far I've tried this attribute to the assembly (I placed it before the namespace block of code):
[assembly: AllowPartiallyTrustedCallers]
But this caused other compilation problems.
Please, anything would be most helpful and greatly appreciated.
Andy
Unfortunately, the problem isn't yet fixed. However, the problem appears to have nothing to do with Code Access Security as I first thought. I was being thrown a red herring. I stepped my way through the code using the memory window in Visual Studio and noticed that these strings were in memory before calling the Setup API function to fill them. Occasionally, I would get a different block of memory with different contents too, I just usually ended up with the contents I pasted.
The problem actually appears to have something to do with the 64 vs. 32 bit environments (at least, that's my theory at this point).
However, this question isn't the actual problem so I'm "answering" it to close it.

How to open a file when file handle number is known?

I open a file in C# with FileStream, and I got the file handle number with this line:
IntPtr file_handle = fs.SafeFileHandle.DangerousGetHandle();
Now I want to pass this handle to C++ code and use this handle value to access the file. Is this possible? How to open a file with merely a file handle in C++?
Thanks.
Update
I use C# to P/Invoke into a C++ Win32 DLL(not a COM DLL). I open the file in C# as FileStream, and pass the handle to the C++. Here is some of my code in the C++ DLL:
extern "C" __declspec(dllexport)void read_file(HANDLE file_handle)
{
char buffer[64];
::printf("\nfile = %d\n",file_handle);
if(::ReadFile(file_handle,buffer,32,NULL,NULL))
{
for(int i=0;i<32;i++)
cout<<buffer[i]<<endl;
}
else
cout<<"error"<<endl;
}
And here is my C# code:
[DllImport("...",EntryPoint = "read_file", CharSet = CharSet.Auto)]
public static extern void read_file(IntPtr file_handle_arg);
But I get this error:
Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
Thanks.
You can use win32 calls, the same way the filestream/file constructors do (via p/invoke).
Cracking it open in .NET Reflector, it looks like it is using this function:
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
int dwDesiredAccess,
FileShare dwShareMode,
SECURITY_ATTRIBUTES securityAttrs,
FileMode dwCreationDisposition,
int dwFlagsAndAttributes,
IntPtr hTemplateFile);
Here is an official reference:
http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
This is just to open the file, though, as you asked when you said:
How to open a file with merely a file handle in C++
If you want to read an already open file, you might have more trouble. I'm not sure. You might be able to use this function:
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern unsafe int ReadFile(
SafeFileHandle handle,
byte* bytes,
int numBytesToRead,
IntPtr numBytesRead_mustBeZero,
NativeOverlapped* overlapped
);
http://msdn.microsoft.com/en-us/library/aa365467(v=VS.85).aspx
That entirely depends -- but it's unlikely that you will be able to do this. I'm assuming that your C# code and C++ code are running in different processes -- if you're in the same process you should just be able to marshall over the IntPtr over as a HANDLE.
The problem is that file handles are specific to a process -- you won't be able to use that handle in another process.
That said, you're probably better off:
Passing the name of the file to the C++ code and opening it there
Passing the data actually contained whithin the file to the C++ and dealing with it there.
If the C++ code is C++/CLI, then don't bother with the handle at all. Just pass the FileStream object directly to your C++ code.
If the C++ is native code, then you can use the file handle anywhere you'd normally use a Windows HANDLE value for files, such as ReadFile and WriteFile. You wouldn't use the handle to open a file because it's already open. If you want another copy of the handle, or if you want to give the handle to another process, then use DuplicateHandle. If you need to the value with POSIX-like functions like _read and _write, then call _open_osfhandle to get a file descriptor. You can wrap the file descriptor into a C FILE* stream with _fdopen.
Turns out the title isn't really what the OP was after.
But if someone ever really needs to do this (say: Re-opening a file with different permissions), you can probably use a combination of GetFileInformationByHandle to get the File ID and OpenFileById.
FWIW.

Dynamically loading a dll in C#

I have a window to use for editing. The editor should load a dll (which I have full control of) in response to the user's selection to know how to display the information visually.
(They're dll's, as a user will not necessarily want or need every single display model, and also allow new ones to be added without messing around with the main project)
They will all simply be stored in a subdirectory (for now anyway)
I'm pretty sure I can enumerate the available dlls but I need to do 2 more things that I'm not sure on
1) Some way to get metadata from\on the dll, so I can build the lists of possible display selections...
2) Load the selected dll, and unload it as necessary
Any suggestions would be greatly appreciated.
If you are using raw dll's and not .NET assemblies then here are some handy P/Invokes for you:
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern void SetDllDirectory(string lpPathName);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
privatestatic extern int GetModuleFileName(IntPtr module, [Out] StringBuilder fileName, int size);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static bool FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
Note that SetDllDirectory may need some protection as it is not available on all versions of windows (Windows 2000, in particular doesn't have it).
And in use:
SetDllDirectory(candidateFolder);
IntPtr dllHandle = LoadLibrary(dllName);
if (dllHandle != IntPtr.Zero)
{
_dllHandle = dllHandle;
_location = candidateFolder;
_fullPath = Path.Combine(candidateFolder, dllName);
IntPtr p = GetProcAddress(_dllHandle, procName);
if (p == IntPtr.Zero)
throw new ArgumentException("procName");
SomeDelegateType d = (SomeDelegateType)Marshal.GetDelegateForFunctionPointer(p, typeof(SomeDelegateType));
d(/* args */);
}
otherwise, you will be using Assembly methods. Looking at assembly level attributes or object level attributes is a good way to get extra information, although if what you want is a plug-in system, you should use a plug-in system, like the Managed Add-In Framework at CodePlex. See also this SO question and answer.
Take a look at the Castle Windsor framework. It is designed to handle all of your requirements including DLL unloading. It's also free and open source.
I don't know if changing how your program works is an option, but, you could use dependency injection for this, as long as they adhere to a certain interface.
The user selects, you dynamically set class to be loaded, and then just get an instance of the class.
I am not dealing with the unloading, I am just thinking about how you could possibly get classes, and since plinth already gave links to the functions for actually handling the dll, I think I will just end here.
For a native module, the simplest way to get "metadata" would be to define some C-exported (non-name-mangled) functions that return the information you want. At their simplest, these would return pointers to static data within the modules, e.g.:
extern "C" const char* GetModuleDescription();
...
const char* GetModuleDescription() { return "Dummy Module"; }
You would then load each ".dll" file in the directory using LoadLibrary, load and call your known exports from it using GetProcAddress. If you can't load a file or find the exports, then it's not a valid plugin module, so skip it.
Once you're done with a module, you can call FreeLibrary. Windows will then unload the module from your address space.
OK, I;ve figured out I need to use a second AppDomain, load the dll into that, and then I can unload the AppDomain as required.
string SignalSystemDLLPath = AppDomain.CurrentDomain.BaseDirectory + MyApp.Properties.Resources.SystemModuleFolder;
AppDomainSetup info = new AppDomainSetup();
info.ApplicationBase = DLLPath;
DLLDomain = AppDomain.CreateDomain("EditorDomain", null, info);
DLLPath is set to the subdir that holds the dll's.
I then foreach on all the dll's to get the AssemblyName, then later
I use
DLLDomain.Load(SelectedAssemblyName)
to load the DLL. I keep getting FileNotFound exceptions though.
After much googling I've decided its to much work at the moment, and I can refactor it later If I really need to do it...
Thank you for your replies though!
Found out how to do this very easy using MEF, simply use a DirectoryCatalog pointed at your plugin dir, and as long as you have matching [Export]s and [Import]s it works great.

Categories