Injecting libs through C# or whatever programming language is familiar but injecting a C# lib without any use of COM reg or CLR Runtime hosts? How?
Yeah I'm here to explain step-by-step how to do it. Before we rush to the "How to apply a hook?" part, I'm going to explain how the functionality of exporting C# functions works.
2. DLL Exporting
So I could let you all go through the pain of learning how exporting functions works but Robert Giesecke already did for you all;
.So after you downloaded his project template and put it into your "Documents\Visual Studio 20xx\Templates\ProjectTemplates" map without extracting the archive. You should have something that looks like this;
Code:
internal static class UnmanagedExports
{
[DllExport("adddays", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
static double AddDays(double dateValue, int days)
{
return DateTime.FromOADate(dateValue).AddDays(days).ToOADate();
}
}
3. C# WinHook
The process memory class; (Functions in reading/writing to/from the memory)
- Create a file named ProcessMemory.cs or whatever you want to call it.
- Make it a [ public static class ].
- Following this Singleton template if you want.
-Following with a DLL Import of VirtualProtect; Changes protection in the virtual address.
Code:
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool VirtualProtect(IntPtr address, uint size, uint newProtect, out uint oldProtect);
Code:
public static byte[] ReadProcessMemory(IntPtr address, int length)
{
var buffer = new byte[length];
Marshal.Copy(address, buffer, 0, length);
return buffer;
}
public static void WriteProcessMemory(IntPtr address, byte[] buffer)
{
uint oldProtect;
VirtualProtect(address, (uint)buffer.Length, 0x40, out oldProtect);
Marshal.Copy(buffer, 0, address, buffer.Length);
VirtualProtect(address, (uint)buffer.Length, oldProtect, out oldProtect);
}
Code:
[ComVisible(true)]
[Guid("00000000-0000-0000-0000-000000000001"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDetourHook
{
/// <summary>
/// If the hook has been installed yet.
/// </summary>
bool IsInstalled { get; }
/// <summary>
/// Invoke original hooked function.
/// </summary>
/// <param name="args"></param>
/// <returns>Original object returned by hooked func.</returns>
object InvokeOriginal(params object[] args);
/// <summary>
/// Instal hook.
/// </summary>
/// <returns>Succession of installation</returns>
bool Install();
/// <summary>
/// Remove hook.
/// </summary>
/// <returns>Succession of uninstalling</returns>
bool Uninstall();
}
Code:
public class DetourHook
: IDetourHook
{
#region Variables
protected readonly IntPtr HookPtr;
protected readonly byte[] newBytes;
protected readonly byte[] originalBytes;
protected readonly IntPtr TargetPtr;
protected readonly Delegate TargetFunc;
/// <summary>
/// Gets a value indicating whether the hook is installed.
/// </summary>
public bool IsInstalled { get; private set; }
#endregion
#region Constructor
/// <summary>
/// Initializes the variables.
/// </summary>
/// <param name="target"></param>
/// <param name="hook"></param>
public DetourHook(Delegate TargetFunc, Delegate HookFunc)
{
this.TargetPtr = Marshal.GetFunctionPointerForDelegate(TargetFunc);
this.TargetFunc = TargetFunc;
this.HookPtr = Marshal.GetFunctionPointerForDelegate(HookFunc);
originalBytes = new byte[6];
Marshal.Copy(TargetPtr, originalBytes, 0, 6);
var hookPointerBytes = BitConverter.GetBytes(HookPtr.ToInt32());
newBytes = new byte[] { 0x68, hookPointerBytes[0], hookPointerBytes[1], hookPointerBytes[2], hookPointerBytes[3], 0xC3 };
}
#endregion
#region Functions
//for documentation check the interface.
public object InvokeOriginal(params object[] args)
{
Uninstall();
var returnValue = TargetFunc.DynamicInvoke(args);//ret
Install();
return returnValue;//ret
}
public bool Install()
{
ProcessMemory.WriteProcessMemory(TargetPtr, newBytes);
IsInstalled = true;
return true;
}
public bool Uninstall()
{
ProcessMemory.WriteProcessMemory(TargetPtr, originalBytes);
IsInstalled = false;
return true;
}
#endregion
}
-Sample hook class;
Code:
public static class SampleHookClass
{
public static readonly IntPtr SendPacketAddress = (IntPtr)0x6BFD0C;
public static readonly IntPtr RecvPacketAddress = (IntPtr)0x6C05E8;
[UnmanagedFunctionPointer(CallingConvention.ThisCall, SetLastError = true)]
public delegate int NetworkFunction(IntPtr self, IntPtr pckt, ushort len);//credits to IAmHawtness for correcting me
public static readonly NetworkFunction originalSendfunc = (NetworkFunction)Marshal.GetDelegateForFunctionPointer(SendPacketAddress, typeof(NetworkFunction));
public static readonly NetworkFunction originalRecvfunc = (NetworkFunction)Marshal.GetDelegateForFunctionPointer(RecvPacketAddress, typeof(NetworkFunction));
public static void InitHooks()
{
var mySendFunc = new NetworkFunction(MySendFunction);
var myRecvFunc = new NetworkFunction(MyRecvFunction);
//Add hooks.
WinHookManager.This.InitHook(originalSendfunc, mySendFunc, "Conquer::SendPacket");
WinHookManager.This.InitHook(originalRecvfunc, myRecvFunc, "Conquer::RecvPacket");
//Install hooks.
WinHookManager.This.Install("Conquer::SendPacket");
WinHookManager.This.Install("Conquer::RecvPacket");
}
private static int MySendFunction(IntPtr self, IntPtr pckt, ushort len)
{
//Do something here.
return (int)WinHookManager.This.InvokeOriginal("Conquer::SendPacket", new object[] { self, pckt, len });
}
private static int MyRecvFunction(IntPtr self, IntPtr pckt, ushort len)
{
//Do something here.
return (int)WinHookManager.This.InvokeOriginal("Conquer::RecvPacket", new object[] { self, pckt, len });
}
}
Code:
internal static class UnmanagedExports
{
[DllExport("dll_main", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
static void main()
{
SampleHookClass.InitHooks();//Initializes&installs all specified hooks.
}
}

Code:
Process proc;
proc= Process.GetProcessesByName("proc")[0];
//or create the proc yourself.
Injector injector = new Injector(proc);
injector.InjectLibrary("libname.dll");
injector.CallExport("libname.dll", "dll_main");
Console.ReadKey();
injector.EjectLibrary("libname.dll");
injector.Dispose();






