Skip to content

Instantly share code, notes, and snippets.

@mgeeky
Forked from dr4k0nia/HInvoke.cs
Created May 18, 2023 00:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgeeky/c72a5a3dc4528d0058b6d44156a99b49 to your computer and use it in GitHub Desktop.
Save mgeeky/c72a5a3dc4528d0058b6d44156a99b49 to your computer and use it in GitHub Desktop.
A very minimalistic approach of calling .net runtime functions or accessing properties using only hashes as identifiers. It does not leave any strings or import references since we dynamically resolve the required member from the mscorlib assembly on runtime. Read the blog post: https://dr4k0nia.github.io/dotnet/coding/2022/08/10/HInvoke-and-avo…
using System.Linq;
using System.Reflection;
namespace HashInvoke;
public class HInvoke
{
public static T InvokeMethod<T>(uint classID, uint methodID, object[]? args = null)
{
// Get the System assembly and go trough all its types hash their name
// and find the hash that matches the supplied one
var typeDef = typeof(void).Assembly.GetTypes()
.FirstOrDefault(type => GetHash(type.FullName!) == classID);
// Use the type and go trough its methods hash their name
// and find the hash that matches the supplied one
var methodInfo = typeDef.GetRuntimeMethods()
.FirstOrDefault(method => GetHash(method.Name) == methodID);
// Invoke the resolved method with the supplied args
if (methodInfo != null)
return (T) methodInfo.Invoke(null, args);
return default!;
}
public static void InvokeMethod(uint classID, uint methodID, object[]? args = null)
{
// This part can be adjusted to work with any Assembly you want
var typeDef = typeof(void).Assembly.GetTypes()
.FirstOrDefault(type => GetHash(type.FullName!) == classID);
var methodInfo = typeDef.GetRuntimeMethods()
.FirstOrDefault(method => GetHash(method.Name) == methodID);
if (methodInfo != null)
methodInfo.Invoke(null, args);
}
public static T GetPropertyValue<T>(uint classID, uint propertyID)
{
var typeDef = typeof(void).Assembly.GetTypes()
.FirstOrDefault(type => GetHash(type.FullName!) == classID);
var propertyInfo = typeDef.GetRuntimeProperties()
.FirstOrDefault(property => GetHash(property.Name) == propertyID);
if (propertyInfo != null)
return (T) propertyInfo.GetValue(null);
return default!;
}
private static uint GetHash(string name)
{
uint sum = 0;
foreach (char c in name)
{
sum = (sum >> 0xA | sum << 0x11) + c;
}
// zero terminator:
sum = (sum >> 0xA | sum << 0x11) + 0;
return sum;
}
}
internal static unsafe class Program
{
public static void Main (string[] args)
{
Console.WriteLine (
"Hello you look nice, you would not attach a debugger to me would u?");
// Using the Microsoft.Win32.Win32Native functions we can avoid using
// Pinvoke
var module = HInvoke.InvokeMethod<IntPtr> (
13239936, 811580934,
new object[]{
"kernel32.dll" }); // Microsoft.Win32.Win32Native.GetModuleHandle
var address = HInvoke.InvokeMethod<IntPtr> (
13239936, 1721745356,
new object[]{
module,
"IsDebuggerPresent" }); // Microsoft.Win32.Win32Native.GetProcAddress
if (((delegate * unmanaged[Stdcall]<bool>) address) ())
Console.WriteLine ("Hey meanie I said no debugging :c");
HInvoke.InvokeMethod (2164260848, 3770666652); // System.Console.ReadKey();
if (HInvoke.GetPropertyValue<bool> (
1577037771, 179842977)) // System.Diagnostics.Debugger.IsAttached
HInvoke.InvokeMethod (1174404872, 2029614223,
new object[]{ 0 }); // System.Environment.Exit(0)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment