DLLs searching for DLLs - c#

I've done an extension for Thunderbird. It calls (via js-ctypes) a C++ DLL I've written which in turn references other DLLs which are assemblies written in C# (existing code). If all the files are in the same directory as the Thunderbird executable, it all works fine.
I've now moved my own files to a directory I've made to keep them distinct from the Thunderbird files. The directory is in the path, so my C++ DLL gets loaded when called. However when it starts looking for the referenced assemblies, it fails.
Procmon shows that it is only looking for referenced assemblies in the directory which Thunderbird is running from. Not only is there no path, it's not even looking in the system directories.
What can I do to get my DLL loading its dependencies without dumping everything into Thunderbird's own folder, which as well as being somewhat messy will get silly when I port the extension to other mail programs?
Edit: Added extracts from the JS code.
From my 'init' function, there's;
this._kernel32 = ctypes.open("kernel32.dll");
this._setDLLDir = this._kernel32.declare("SetDllDirectoryA",
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr);
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
this._lib = ctypes.open("AttacherC.dll");
this._getStr = this._lib.declare("GetPackage",
ctypes.default_abi,
ctypes.char.ptr);
this._freeStr = this._lib.declare("FreePackage",
ctypes.default_abi,
ctypes.void_t,
ctypes.char.ptr);
ret = this._setDLLDir(null);
And where I'm actually making the call to _getStr and search for AttacherC.dll's dependencies is made is;
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
var str = this._getStr();
In each case, ret is true (according to the debugger on stepping through) suggesting the call to SetDllDirectory succeeds. Behaviour is the same whether I use the "A" or "W" version, there being nothing in the JS to simply let me call "SetDllDirectory". It's as if each call is happening in its own isolated context, yet in my DLL "GetPackage" uses malloc to allocate some memory which then needs to be freed in "FreePackage". FreePackage doesn't throw an exception suggesting the fact the memory's been allocated is persisting between the two calls.
More odd behaviour; if I specify a random string as the path in SetDllDirectory ("helloworld" in this case) ret is still true. So either SetDllDirectory isn't actually getting the string correctly via ctypes, or it's not doing any sanity checking on it.
My feeling now is that each js-ctypes call is happening in its own context, in some way, and it's upsetting .net's assembly search mechanism, and the only way to get this to work is to have a seperate native DLL with a single function called from javascript. This then calls SetDllDirectory and LoadLibrary in the same context to call the next wrapper in the chain, which then calls my real C# code. Messy and seems more prone to things going wrong so I'm hoping someone comes along and proves me wrong?

Since nobody else seems to have an answer I'll document what I ended up doing.
When native code calls a dotnet DLL the CLR starts up behind the scenes to run it. Although the native code can search for the DLL in a variety of places- including that specified by SetDllDirectory- the CLR will only look in the directory from which the initial executable has been started, and in the Global Assembly Cache. To access assemblies that your DLL has been linked to by adding references to them in Visual Studio, they have to be in one of these two locations.
Since I didn't want to do either, what's needed is to make a .net DLL that is directly dependent only on framework assemblies, with no references to any of my own. This then gets the CLR up and running my code. I can then load the assembly I want to use via Assembly::LoadFrom() and invoke the method I want to use as documented here.
Of course, loading the assembly this way will still cause any other dependent assemblies to be searched for in the executable dir or in the GAC, if they're not already loaded, and in all but the most trivial case it's too complicated to bother explicitly loading each assembly in order from the most fundamental upwards. So the AssemblyResolve event is registered first. When the CLR can't find an assembly in its two search locations, it raises this event and lets me determine the full path of the assembly and load it, again using Assembly::LoadFrom().
Of course, LoadFrom needs to know the base path- the only information that seems to be available concerns the executable's directory, but there's plenty of ways to resolve that.

You will need to modify the DLL search path.
Make a call to SetDllDirectory before calling ctypes.open() to load your C++ DLL. Pass to SetDllDirectory the directory containing your DLL, and its dependent modules. When the call to ctypes.open() returns, call SetDllDirectory again, passing NULL, to undo the search path modification.

Related

call exe from my program

I have software from the hardware manufacturer, however I do not want my customers to directly use this software, so I want to call manufacturer's software through my program.
I tried to embed an exe file into a resource, but when I called it, my program had to write the exe to disk and I don't want to expose the .exe file.
I also tried the following:
byte[] bin= Properties.Resources.myPro;
Assembly a = Assembly.Load(bin);
MethodInfo method = a.EntryPoint;
if (method != null)
{
object o = a.CreateInstance(method.Name);
method.Invoke(o, null);
}
but got this error when run to Assembly.Load(bin):
Could not load file or assembly '622592 bytes loaded from meter_config,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.
What is the problem, and how do I fix it?
Firstly, the error message you're getting:
An attempt was made to load a program with an incorrect format.
This indicates that the .exe file is not a .NET assembly. As such there is basically zero chance that you're going to be able to execute it from memory or directly from resource. You're going to have to put it somewhere on disk in order to get it to run.
Without a lot more information, all I can suggest is that you run it from a temporary or hidden location. Assuming that you are licensed to do so by the hardware manufacturer, of course.
I would suggest that you extract the .exe file to the temporary folder with a random file name, execute it, then delete the file after it has completed its operation. If you want you can add use the MoveFileEx API to delete a file on reboot. There's an example here on StackOverflow on how to do that. It makes sure that the file is removed from the computer at some point.
If you don't want to delete the file then the other option is to extract it into a path deep in the user's AppData hierarchy. Disguise it however you like, maybe put it in a folder with the hidden flag set, etc.
This kind of obfuscation won't stop a determined user from tracking it down, especially if it runs for more than a few seconds and can be easily seen in Task Manager or Process Explorer. Not much you can do about that unless you want your program to be flagged as a rootkit.
The alternative is to see if the manufacturer will supply a .NET library you can use instead of a standard Windows executable.
Since your using C# (which is generally managed code) you can't load as unmanaged assembly, so, if manufacturer's program is developed in C or C++ or something else which works at lower level than C#, be careful whether that code is managed or not. If it's unmanaged, unfortunately you can't do anything, except including a static entry point (if the code of manufacturer's program exports some method) just as this (you can reference here):
[DebuggerHidden, DebuggerStepperBoundary, DllImport("YourAssemblyLocation", SetLastError = true)]
[return: MarshalAs(UnmanagedType.YourPrimitiveType)]
internal static extern YourMethodType YourMethodName();
I hope this can be useful for you and let me know about the question.

I have the start address of a loaded DLL, how can I discover and call its exports?

I'm writing an add-in that runs in-process. I'm reliably able to discover the memory address of a DLL that is already loaded in that process. The memory at the offset clearly shows an "MZ" DOS header and a "PE" header. Later, there appears to be the names of exported functions etc. This walks and talks like a loaded DLL.
So, now, I'd like to discover more about what the DLL is, and more interestingly, what I might be able to do with it.
I've used PE utilities in the past, but they've always worked with file-based DLLs. How can I list the exported functions of an in-memory DLL, other than by inspecting the process in a hex editor? Is there any way to discover the file-based DLL that is currently loaded? (I'm not overly familiar with the linking that I think takes place when the dll is loaded.)
If I have the names of the exported functions, is it just a matter of trying to call those functions, and guessing their arguments and return values? Or is there some more robust reverse engineering that could be performed?
Given the starting address of the DLL, and a function name, how would I go about making a call in C#?
There are actually many questions here (and some are pretty vast). I'll try providing answers to some.
To get the handle of a module (.dll) loaded in the current process use
[MSDN]: GetModuleHandleEx function, whether its name or address is known (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS flag)
To get the file name containing the code of a loaded .dll use [MSDN]: GetModuleFileName function. At this point you'll be able to use PE utilities that you mentioned (Dependency Walker or [MSDN]: Sysinternals Suite can be very useful)
Apparently, getting the functions signatures from a .dll is not a trivial task (sometimes it's quite impossible). Here are 3 URLs, but Google would yield tons of results on this topic:
[MSDN]: how can I get metadata (signature with parameters and return type) of C++ dll
[SO]: Is there any native DLL export functions viewer?
[SO]: Get signatures of exported functions in a DLL
But a .dll comes with one or more header file(s) that contain(s) (among other things) the functions/classes declarations. Lacking the header(s) would mean that either:
The .dll symbols are for internal purposes only (and not to be called "manually")
They are private (e.g. protected by a license), and in that case reverse engineering them wouldn't be very ethical
Anyway, considering that one way or another you get the functions names and signatures, you can load the functions via [MSDN]: GetProcAddress function, and then call them.
Doing everything from .NET (C#) (again, function names and signatures are required), only adds an extra level of complexity because C# code runs in managed environment, while C/C++ runs in native environment, and when data is exchanged between the 2 environments it needs to be marshalled/unmarshalled ([MSDN]: Overview of Marshaling in C++).
Below are 3 URLs, but again, Internet is full of information:
[MSDN]: Calling Native Functions from Managed Code
[SO]: Is it possible to call a C function from C#.Net
[SO]: Calling C DLL from C#

Accessing resources in registered .NET DLL via res protocol

I have a .NET DLL that I register with regasm.exe as a Browser Helper Object. I embedded several Win32 resources in the DLL using .res files and /win32 switch to csc.exe.
image.png HTML "image.png"
I am able to access the resources using the res protocol as long as I include the absolute path of the DLL.
res://C:\Path\To\My\Dll\Assembly.dll/image.png
This is rather unfortunate. I would much rather just reference the assembly name as I have seen in many other examples:
res://Assembly.dll/image.png
But this results in an error because the browser can't find the resource.
Ideas?
I think there are a couple things that can be done. First, I believe your assembly needs to be a part of the global assembly cache if you don't want to be forced to use the full path.
Add assembly to global assembly cache.
It's not pretty and you must also keep in mind that a newer build of the DLL will be different from the version in cache. So it would essentially be another extra step to take which would just lead us back to accepting having to put in the full path in the first place.
Second, another solution I believe that works would be to place the DLL in the same directory as the VS utility or the other resources you're trying to use. This could be applicable to multiple different things that one might want to do, but requires manually moving your files around.
Third, you create some custom environmental variables that represent the path that you desire. So instead of typing the full path in the future, you just type your variable.
The third option is my favorite and something that I use for multiple different things I need to accomplish from the command-line.

Way to determine true calling assembly

I have some security built into a client side program that downloads a DLL from the web, and called a function inside that DLL. The DLL is strong-named, and the function in the DLL uses Assembly.GetCallingAssembly() to determine the calling assembly so that I can accurately get a path to the program who called it. From there we do a hash check of the assembly and verify that it is the correct one.
We have people that have gotten themselves attached in full trust mode, and are able to spoof the GetCallingAssembly call to point to the real executable, while they run a modified version of it. Is there something else other then GetCallingAssembly that I can use to get the true caller? Some callstack or something that may provide the real executable since GetCallingAssembly seems to be easily spoofed.
You can't do this while running in full trust mode. Full trust means people can do things like spoofing. Here is a similar discusison:
reflection is possible on obfuscation
I'm not sure how secure it is, but I've used this in the past to get the startup path:
string startup_path =
Path.GetDirectoryName(typeof(SomeClassInDll).Assembly.Location);

Best way to only perform a function if a (.NET) DLL is loaded?

I am not sure the best way to explain this so please leave comments if you do not understand.
Basically, I have a few libraries for various tasks to work with different programs - notification is just one example.
Now, I am building a new program, and I want it to be as lightweight as possible. Whilst I would like to include my notification engine, I do not think many people would actually use its functionality, so, I would rather not include it by default - just as an optional download.
How would I program this?
With unmanaged Dlls and P/Invoke, I can basically wrap the whole lot in a try/catch loop, but I am not sure about the managed version.
So far, the best way I can think of is to check if the DLL file exists upon startup then set a field bool or similar, and every time I would like a notification to be fired, I could do an if/check the bool and fire...
I have seen from the debug window that DLL files are only loaded as they are needed. The program would obviously compile as all components will be visible to the project, but would it run on the end users machine without the DLL?
More importantly, is there a better way of doing this?
I would ideally like to have nothing about notifications in my application and somehow have it so that if the DLL file is downloaded, it adds this functionality externally. It really is not the end of the world to have a few extra bytes calling notification("blabla"); (or similar), but I am thinking a lot further down the line when I have much bigger intentions and just want to know best practices for this sort of thing.
I do not think many people would
actually use its functionality, so, I
would rather not include it by default
- just as an optional download.
Such things are typically described as plugins (or add-ons, or extensions).
Since .NET 4, the standard way to do that is with the Managed Exensibility Framework. It is included in the framework as the System.ComponentModel.Composition assembly and namespace. To get started, it is best to read the MSDN article and the MEF programming guide.
You can use System.Reflection.Assembly and its LoadFile method to dynamically load a DLL. You can then use the methods in Assembly to get Classes, types etc. embedded in the DLL and call them.
If you just check if the .dll exists or load every .dll in a plugin directory you can get what you want.
To your question if the program will run on the user's machine without the dlls already being present - yes , the program would run. As long as you dont do something that needs the runtime to load the classes defined in the dll , it does not matter if the dll is missing from the machine. To the aspect you are looking for regarding loading the dll on demand , I think you are well of using some sort of a configuration and Reflection ( either directly or by some IoC strategy. )
Try to load the plugin at startup.
Instead of checking a boolean all over the place, you can create a delegate field for the notification and initialize it to a no-op function. If loading the plugin succeeds, assign the delegate to the plugin implementation. Then everywhere the event occurs can just call the delegate, without worrying about the fact that the plugin might or might not be available.

Categories