Mamad R Mamad R - 14 days ago 7
C# Question

inject C# code to another process and call target functions

I am trying to calling a game functions with code injection. after some try I find a dll that did what I want.

so i saw the dll with ILSpy but cannot understand the code.

class <Module>
{
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("", CallingConvention = CallingConvention.ThisCall, SetLastError = true)]
[MethodImpl(MethodImplOptions.Unmanaged)]
internal unsafe static extern float* GetHealth(AttackableUnit*);
}
--------------------------
namespace Native
{
[NativeCppClass]
[StructLayout(LayoutKind.Sequential, Size = 1)]
internal struct AttackableUnit
{
}
}
---------------------
public unsafe float MaxHealth
{
get
{
Native.AttackableUnit* ptr = (Native.AttackableUnit*)base.GetPtr();
if (ptr != null)
{
return *<Module>.Native.AttackableUnit.GetMaxHealth(ptr);
}
return 0f;
}
}


Seems the dll inject c# code to the target app with a c++ dll and bootstrap .net in target.

And now I cannot understand what is the meaning of


[DllImport("", CallingConvention = CallingConvention.ThisCall,
SetLastError = true)]


Why is the file path empty?
How does the dll manage class and function call? I mean what technique the programmer use?

EDIT :
The name of library that I am trying to understand is Elobuddy perhaps helps.

Answer

Trying not to kick in a wide-open door, the C# language was not involved in generating this assembly. You are seeing the output of a C++/CLI project. A mixed-mode assembly, it contains both MSIL and native code. You'd generate a similar assembly with File > New > Project > Visual C++ > CLR > Class Library.

The author probably favored it to solve the CLR injection problem. It is not possible to inject a pure managed DLL into another process, the CLR has to first be loaded and initialized before it can execute any managed code. A chicken-and-egg problem that requires reverse-pinvoke (native code calling managed code) the opposite of what [DllImport] does. C++/CLI makes that very easy, I describe the technique in this answer. The Unmanaged Exports utility is popular (google DllExport), an assembly rewriter that uses the same technique that C++/CLI uses.

But the author also wanted to use native C++ code to implement the game hack. He is using a pure native DLL, it contains the GetHealth() function and AttackableUnit class definition. This DLL is implicitly loaded by the OS loader, like DLLs usually are, the reason why an empty string for the [DllImport] attribute is good enough. Otherwise necessary, the compiler cannot know which DLL has this native code, that doesn't get sorted out until the linker runs and uses the import library of the native DLL.

The C++/CLI compiler goes a bit overboard emitting metadata for the pure native constructs in the code. But does its best to make them look as much as possible like their managed equivalents. Do note it is very incomplete, you can't for example see the names of the members of the AttackableUnit C++ class. You will find a lot of other spew in the assembly, a lot of CRT declarations make it into the metadata as well. The native linker does not do a terrific job of hiding it. Mostly because it doesn't have to, this code is pretty well isolated into the internal <Module> class.

Decompiling the machine code for native functions like GetHealth back to the original C++ code is not generally possible. Especially the optimizer built into the back-end of the compiler does a terrific job of making it next to impossible to guess what the original code might have looked like. Hex-Rays is usually mentioned as a machine code decompiler that does a credible job of at least correctly identifying code vs data.