Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# unmanaged dll exporting (how it works)

I have found libraries that would export managed code as unmanaged so you can use it by unmanaged languages like C/C++. But I did not find anything that would explain how it's done (which is what I'm more interested in)

I'm looking for information, tutorials, articles, code sources or anything that could help me to understand how this works

On a side note, if you found some hooks/detours resources in your bookmarks I would love to read them too :)

Thanks in advance and have a wonderful day.

like image 526
user3761832 Avatar asked Jul 01 '15 08:07

user3761832


2 Answers

I'll post an answer, collecting the comments I wrote.

The most famous library for doing it is (as today) the UnmanagedExports. Its page is https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports . Sadly there is no source code available, but it is licensed under the MIT license, so it is probably ok to use IlSpy to take a look at it.

There are a few references about how it is done.

There are at least two articles on Codeproject: How to Automate Exporting .NET Function to Unmanaged Programs that seems to be for .NET 2.0 and Unmanaged code can wrap managed methods that sadly is about .NET 1.1.

There is some reference in the book Expert .NET 2.0 IL Assembler around page 384.

You can surely do another thing: observe what UnmanagedExports do: UnmanagedExports in the end is "composed" of two parts: an assembly RGiesecke.DllExport.Metadata.dll containing a "stupid" attribute DllExportAttribute plus two assemblies (that on my computer the nuget installs in the packages\UnmanagedExports.1.2.6\tools folder): RGiesecke.DllExport.dll and RGiesecke.DllExport.MSBuild.dll. The nuget installer of UnmanagedExports adds some lines to the csproj, like:

<Import Project="packages/UnmanagedExports.1.2.6/tools/RGiesecke.DllExport.targets" Condition="Exists('packages/UnmanagedExports.1.2.6/tools/RGiesecke.DllExport.targets')" />

that cause the execution of the class RGiesecke.DllExport.MSBuild.DllExportAppDomainIsolatedTask contained in the assembly RGiesecke.DllExport.MSBuild.dll. This class, using Mono.Cecil, rewrites the assembly doing some code reweaving. This program simply calls ildasm to generate the il code source, modifies the il code source and then uses ilasm to generate back the "original" .dll/.exe . So simply put, generate two assemblies, one with the <Import /> and another with the <Import /> commented out, then do a

ildasm yourdll.dll /out=source.il

of both files and compare it with your favourite file comparer.

Another interesting link is here. There are some comments to how to make it work on x64.

If I had to build something similar, I would probably try to integrate it to Fody. In this way I would have the whole post-build Task for free (because it is done by Fody)

Can't be done with Mono.Cecil... Mono.Cecil can't write mixed-mode assemblies (that are needed to export symbols). You have to use the same "trick" used by UnmanagedExports (and by the various other examples)... Generate the IL file, modify it (it is a text file in a fixed format... quite easy to modify), re-generate the .dll/.exe .

like image 137
xanatos Avatar answered Sep 21 '22 15:09

xanatos


Here is the source code of unmanaged exports maintained on github:

https://github.com/3F/DllExport

Unmanaged exports has to be doing essentially what c++/cli compiler has to do for reverse pinvoke.

like image 30
denfromufa Avatar answered Sep 19 '22 15:09

denfromufa