Reasons why a DLL might decompile to have every function return `null`?
I have a third-party DLL that I'm working with, and when I try to decompile it, the decompiled code shows every function as empty, returning
null
or true
. The IL code that the decompilers show matches the bad code:
I've tried four different decompilers, all with the same results: dotPeek
, ILSpy
, dnSpy
, and ildasm
. The only exception seems to be when I use the View Disassembly window in Visual Studio while debugging - then I can see some IL code that looks correct, but when I get it to actually decompile, it uses ILSpy and goes back to being useless.
I know for a fact that the functions do not simply return null
, and that this code is incorrect.
Does anyone have any ideas why this might be the case, or how I can get around it? I'm trying to decompile it to understand a nondescript error that the DLL gives me when calling it from an unmanaged C++ program with a bridge DLL.34 Replies
which third party dll is it?
might be some anti decompilation technique?
Unfortunately, I can't share the DLL. It appears to have been written in C#, and it exposes a COM interface.
I suspect that you're right about it being an anti-decompilation technique, but I haven't been able to find cases of anyone else getting similar results when decompiling.
even if i go onto thin ice now... are there any methods in the assembly that arent just empty? might they have some il emit stuff in there or are there any other dlls that might do the il emitting?
There are some methods with real code in them, but the majority of the DLL is just classes with functions that do nothing. What do you mean about IL emitting?
there are libs that can generate/load IL during runtime
so on static analysis you do not see the IL because its scrambled somewhere but when you actually execute the code its readable
Interesting - that would explain why VS' debugger could see real IL but static decompilers can't
Do you know the names of any of these libs?
Also, do you know of any tools that could convert raw IL code (pasted, not from a DLL) into readable source code?
Do you know the names of any of these libs?i do know some but i dont want to get on the bad side of admins here so i wont share.. you would have to look for them yourself
That's fair, thank you for your help - I really appreciate it!
@zedseven you are attempting to decompile a ref assembly, not a real assembly
Reference assemblies - .NET
Learn about reference assemblies, a special type of assemblies in .NET that contain only the library's public API surface
But there is no other assembly - this one DLL is the only one required
and I can see some functions have real code
To be frank, I don't buy this. It sounds like you're dealing with something that is actually just returning null
Unless you can find the code that is supposedly hooking and replacing il at runtime, it's not happening
I'm certain that it isn't - when I debug it, VS' disassembly window shows real IL code
The actual issue I'm trying to figure out through decompilation is as follows:
When a function in this DLL is called using a managed Visual C++ executable, it works.
When I call that function from an unmanaged C++ executable, using a C++/CLI bridge, it returns an error (a string error message created by the DLL, not a crash or exception)
Something within the DLL doesn't like when it's called from an unmanaged entrypoint
but for sure there is real code inside it - not just a bunch of
return null;
Then what you're debugging is nearly certainly a different dll
I don't think so - I checked and there is no other DLL packaged with the one I'm working with. VS' disassembly shows function and class names that only exist within the one I'm looking at, too
If there is no real code inside the methods you're disassembling, and you cannot find code that is patching it at runtime, then unless they've managed to find bugs in the runtime to obfuscate their real code (not impossible, but I've never heard of this particular form), then you're not looking at the same dll
If it was patching at runtime, I would see references to
System.Reflection
or a library that references it, correct?prolly reflection, mono or harmony
I don't see references to any of them :/
Thank you all for your help, though - I appreciate it
if this is true, do
typeof(SomethingFromThatAssembly).Assembly.Location
or I believe VS actually has a window that will tell you where modules are loaded fromyes, it does

look at your DLL in that window, see the path it was loaded from
if it doesnt have a path, then it was loaded from a stream or from memory by some other DLL in the process
also int the callstack you can see in which module you are currently in
(its under
Debug > Windows > Modules
, or by default Ctrl+Alt+U
)IIRC there is a C# obfuscation tool which loads all methods impls at runtime. I can't remember the name -- it's been years since I looked at that stuff -- but I remember it being a thing
I just checked, and it shows the current function in the call stack as being inside the same DLL as I've been trying to decompile
is it the same DLL as in its named the same thing or the path in the modules window shows exactly the path to the .dll file you've been decompiling
It's named the same as what I expect, and in the modules window I can see there's only one DLL loaded with that name, and the path matches where the file is
then you have something very odd going on
I agree lol
Thank you for your suggestions though
Since I'm not having much luck seeing inside the binary, has anyone seen a similar situation to what I described here, before?
Was it by chance .NET Reactor?
It might have been - that was one of the ones I looked at
I was able to find a deobfuscator and it identified the DLL as obfuscated by that tool
So I guess mystery solved
Iirc that might have been the only one that wasn't trivially deobfuscatable with de4dot
(but it did end up randomly corrupting our code occasionally, so we dropped it)
Yep, de4dot identified it but failed to deobfuscate
A different tool (not sure if I should name it here) was successful though
Yeah I've been wondering if the reason for the actual error is caused somehow by the obfuscation - since the entry point is an unmanaged executable, maybe something in the CLR is different and one of the obfuscation techniques fails