Skip to content

Instantly share code, notes, and snippets.

@holly-hacker
Last active August 12, 2021 08:27
Show Gist options
  • Save holly-hacker/c1fcee3df1ea35e7816c55147e6db78d to your computer and use it in GitHub Desktop.
Save holly-hacker/c1fcee3df1ea35e7816c55147e6db78d to your computer and use it in GitHub Desktop.
Creating managed hooks
namespace ns { class cl1 { void m1() {
// call to make sure they're JITed
// can probably be done another way
Assembly.GetCallingAssembly();
MainForm.PGetCallingAssembly(); // whatever method you want
MethodInfo m1 = typeof(Assembly).GetMethod("GetCallingAssembly", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
MethodInfo m2 = typeof(MainForm).GetMethod("PGetCallingAssembly", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
byte[] someByteCode = { 0xB4, 1, 2, 3, 4, 0xFF, 0xE0 };
if (m1 != null && m2 != null)
{
IntPtr ptrM1 = m1.MethodHandle.GetFunctionPointer();
IntPtr ptrM2 = m2.MethodHandle.GetFunctionPointer();
if (ptrM1 != IntPtr.Zero && ptrM2 != IntPtr.Zero)
{
byte[] ptrM2Bytes = UIntToByte(ptrM2);
someByteCode[1] = ptrM2Bytes[0];
someByteCode[2] = ptrM2Bytes[1];
someByteCode[3] = ptrM2Bytes[2];
someByteCode[4] = ptrM2Bytes[3];
MainForm.WriteProcessMemory(-1, ptrM1, someByteCode, someByteCode.Length, ref _);
}
}
}}}
namespace ns { class cl1 {
/// <summary>https://stackoverflow.com/a/36415711</summary>
public static void Install(MethodInfo methodToReplace, MethodInfo methodToInject)
{
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
else
{
long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
*tar = *inj;
#endif
}
}
}}}
private static void PatchMethod(MethodInfo m, DynamicMethod d)
{
RuntimeHelpers.PrepareMethod(m.MethodHandle);
var ptr = m.MethodHandle.GetFunctionPointer().ToInt64();
RuntimeHelpers.PrepareMethod(GetRuntimeMethodHandle(d));
var ptr2 = ((RuntimeMethodHandle)typeof(DynamicMethod).GetMethod("GetMethodDescriptor", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(d, new object[0])).GetFunctionPointer().ToInt64();
//WriteJump
if (IntPtr.Size == sizeof(long)) {
WriteByte(ptr, 0x48);
WriteByte(ptr + 1, 0xB8);
WriteLong(ptr + 2, ptr2);
WriteByte(ptr + 10, 0xFF);
WriteByte(ptr + 11, 0xE0);
} else {
WriteByte(ptr, 0x68);
WriteInt(ptr + 1, (int)ptr2);
WriteByte(ptr + 5, 0xc3);
}
unsafe void WriteByte(long loc, byte val) => *((byte*)loc) = val;
unsafe void WriteInt(long loc, int val) => *((int*)loc) = val;
unsafe void WriteLong(long loc, long val) => *((long*)loc) = val;
}
@holly-hacker
Copy link
Author

HoLLy-HaCKeR/c1fcee3df1ea35e7816c55147e6db78d#file-managedhook2-cs-L12

may i know why this is +2?

I assume the real method pointer you want is at that offset. I didn't write this code, I just copied it from stack overflow (see link in xmldoc comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment