C
C#4d ago
zedseven

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:
IL_0000: nop
IL_0001: nop
IL_0002: ldnull
IL_0003: ret
IL_0000: nop
IL_0001: nop
IL_0002: ldnull
IL_0003: ret
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
ACiDCA7
ACiDCA74d ago
which third party dll is it? might be some anti decompilation technique?
zedseven
zedsevenOP4d ago
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.
ACiDCA7
ACiDCA74d ago
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?
zedseven
zedsevenOP4d ago
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?
ACiDCA7
ACiDCA74d ago
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
zedseven
zedsevenOP4d ago
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?
ACiDCA7
ACiDCA74d ago
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
zedseven
zedsevenOP4d ago
That's fair, thank you for your help - I really appreciate it!
333fred
333fred4d ago
@zedseven you are attempting to decompile a ref assembly, not a real assembly
333fred
333fred4d ago
Reference assemblies - .NET
Learn about reference assemblies, a special type of assemblies in .NET that contain only the library's public API surface
zedseven
zedsevenOP4d ago
But there is no other assembly - this one DLL is the only one required and I can see some functions have real code
333fred
333fred4d ago
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
zedseven
zedsevenOP4d ago
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;
333fred
333fred4d ago
Then what you're debugging is nearly certainly a different dll
zedseven
zedsevenOP4d ago
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
333fred
333fred4d ago
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
zedseven
zedsevenOP4d ago
If it was patching at runtime, I would see references to System.Reflection or a library that references it, correct?
Monsieur Wholesome
prolly reflection, mono or harmony
zedseven
zedsevenOP4d ago
I don't see references to any of them :/ Thank you all for your help, though - I appreciate it
Aaron
Aaron4d ago
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 from
Aaron
Aaron4d ago
yes, it does
No description
Aaron
Aaron4d ago
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
ACiDCA7
ACiDCA74d ago
also int the callstack you can see in which module you are currently in
Aaron
Aaron4d ago
(its under Debug > Windows > Modules, or by default Ctrl+Alt+U)
canton7
canton74d ago
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
zedseven
zedsevenOP4d ago
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
Aaron
Aaron4d ago
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
zedseven
zedsevenOP4d ago
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
Aaron
Aaron4d ago
then you have something very odd going on
zedseven
zedsevenOP4d ago
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?
canton7
canton74d ago
It might have been - that was one of the ones I looked at
zedseven
zedsevenOP4d ago
I was able to find a deobfuscator and it identified the DLL as obfuscated by that tool So I guess mystery solved
canton7
canton74d ago
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)
zedseven
zedsevenOP4d ago
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

Did you find this page helpful?