call exe from my program - c#

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.

Related

How to distinguish DLL files

I have a program that gets every module loaded into a process and compares them with a database of forbidden DLL files, which works just fine, but it's too simple to circumvent (just change the name of dll file which you want to inject into the process). So I'm asking how can I distinguish DLL files. Is there any unique identifier which can be used in C#? Thanks.
EDIT: I forgot to mention that the program I'm creating checks dll files of another program not created by me which is written in C++.
You can iterate through every module loaded in a process How do I list all loaded assemblies? and see if there is a properly of each module such as ModuleVersionId that does not change when the filename is changed?
I'm not sure if this is even remotely a decent way of handling it, but maybe try hashing the DLL file and check against known trusted hashes of the files? this would require you to already have a trusted list of dll hashes but should safeguard against simply renaming to bypass your current security measure.

DLLs searching for DLLs

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.

represent Memory Stream as a physical file

I've ran into a bit of a stupid problem today:
In my project I have to use a library (that I can't replace), he problem is that I'm using MemoryStream instead of frequently saving to the HDD (because there are many files, and they are small in size, so it's perfect for MemoryStream). The problem is that the library API is built around filesystem access - and one of the functions accepts only direct path to file.
How can I still send a string (path) to the method, which makes a new FileStream without actually touch the hard-drive?
For example "\MEMORY\myfile.bin"?
Well - that's thought.
Basically, you have three possible solutions:
You can use a reflector to modify the library given.
You can inspect the appropriate method, and then, by using some reflection magic you might be able to modify the object at runtime (very un-recommended)
You can play around with system calls and API - and by going into low-level ring0 assembly modify kernal.dll to referrer I/O queries from your path to the memory. (maybe that's possible without ring0 access - I am not sure).
Obviously, the most recommended is to use a reflector to modify the library given. otherwise, I can't see a solution for you.
In respond to the first comment, you can:
use RAMDrive (a program which allocates small chunks of the system memory and show it as partition)
If the file must exist on the disk (and only disk paths are accepted), then the main option is a virtual filesystem which lets you expose custom data as a filesystem. There exist several options, such as now-dead Dokan, our Solid File System OS Edition and Callback File System (see description of our Virtual Storage product line) and maybe Pismo File Mount would work (never looked at it closely).
It all depends on how the library is constructed.
If it's a 100% managed library that uses a FileStream, you are probably stuck.
If it takes the provided filename and call a native WIN32 CreateFile function, it's possible to give it something else than a file such as a named pipe.
To test quickly if it's possible, pass #"\\.\pipe\random_name" to the method: if it responds by saying explicitely that it can't open pipes and filenames begining with \\.\, well, sorry. ON the other hand, if it says it can't find the file, you have a chance to make it work.
You can then create a NamedPipeServerStream and use the same name for your library method call prepended with \\.\pipe\.
You can't "represent" it as a file, but you could "convert" it to a file using a StreamWriter class.

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.

Run Assembly as Process

For example, I download an EXE or MSI file from dataBase as byte array. And I want to run it. I can save it in a file and then Process.Start(path). But if I don't want to create a real file, can I do the same from, for example, Assembly?
Thanks a lot!
If the byte array is a .NET assembly, you can use Assembly.Load with the byte array, then use reflection to work with the types contained within the assembly. This article demonstrates the technique.
This loads it directly into your process, so it works like a referenced assembly.
If the file is a native executable, however, this will not work - another technique will be required. Personally, at this point, I would save it to disk and execute. There are, however, approaches using CreateProcess and inspecting the Process Environment Block. This would likely require unsafe code in C# mixed with P/Invoke to make work correctly, however.
Oh, and incidentally, a MSI is not directly executable. It has to be saved to disk and be called via msiexec.
As for the others, consider exactly what you are trying to do. If you have to solve the general case, you will be writing them to disk and executing them too.

Categories