Skip to content

Instantly share code, notes, and snippets.

@dr4k0nia
Last active September 12, 2023 17:09
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save dr4k0nia/95bd2dc1cc09726f4aaaf920b9982f9d to your computer and use it in GitHub Desktop.
Save dr4k0nia/95bd2dc1cc09726f4aaaf920b9982f9d 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