Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use EashHook to hook compileMethod of c# JIT, the program will crash #395

Open
bwmaples opened this issue Mar 13, 2022 · 3 comments
Open

Comments

@bwmaples
Copy link

bwmaples commented Mar 13, 2022

I modified the FileMon example to hook the compileMethod of a program.
The full code is here.
The code looks like this
Get compileMethod addr

// use getJit() method get compileMethod of jit
// source code https://github.com/dotnet/coreclr/blob/release/3.1/src/jit/ee_il_dll.hpp
public static IntPtr GetCompileMethodPtr() {
    // get CILJit() obj
    // source code https://github.com/dotnet/coreclr/blob/release/3.1/src/jit/ee_il_dll.cpp
    IntPtr pJit = GetJit();

    if (pJit == null) return IntPtr.Zero;
    // self define CorJit struct.
    // Although the structure of each .net version will be different, compileMethod is always the first member.
    compiler = Marshal.PtrToStructure<CorJitCompilerNative>(Marshal.ReadIntPtr(pJit));
    // get the origin compileMethod method
    originCompile = compiler.CompileMethod;
    // get the ptr of compileMethod
    originCompilePtr = Marshal.GetFunctionPointerForDelegate(originCompile);
    return originCompilePtr;
}

The delegate method is

// [source code](https://github.com/dotnet/coreclr/blob/release/3.1/src/jit/ee_il_dll.cpp)
internal static CorJitCompiler.CorJitResult compileMethodDel(IntPtr thisPtr, [In] IntPtr corJitInfoPtr, [In] CorInfo* methodInfo,
    CorJitFlag flags, [Out] IntPtr nativeEntry, [Out] IntPtr nativeSizeOfCode)
{
    Interface.Info("[" + RemoteHooking.GetCurrentProcessId() + ":" +
        RemoteHooking.GetCurrentThreadId() + "]: \"" + " ############# My This compile Method called ##############" + "\"");

    return originCompile(thisPtr, corJitInfoPtr, methodInfo, flags, nativeEntry, nativeSizeOfCode);
}

The hook code.

IntPtr originCompilePtr = GetCompileMethodPtr();
if (originCompilePtr == IntPtr.Zero)
{
    RemoteHooking.WakeUpProcess();
    return;
}

// create replace delegate
mCompileMethodDel = new CompileMethodDel(compileMethodDel);
// print ensure it isn't null
Interface.Info("origiCompilePtr is " + originCompilePtr.ToString());

CompileMethodHook = LocalHook.Create(
    originCompilePtr,
    mCompileMethodDel,
    this);
CompileMethodHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

It can print some logs, but it still crashes.

output

Usage: FileMon %PID%
   or: FileMon PathToExecutable

Please enter a process Id or path to executable: F:\extraIncome\testpro\ConsoleApp5\TargetProcess\WindowsFormsApp2.exe
Created and injected process 26336
<Press any key to exit>
The info is origiCompilePtr is 140711675387888
FileMon has been installed in target 26336.

The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
The info is [26336:35612]: " ############# My This compile Method called ##############"
@justinstenning
Copy link
Member

Not sure if this is the root cause but you should avoid calling Interface.xyz directly in your hook handler. See how FileMon example added messages to a queue and processes them on the entrypoint thread instead.

Generally speaking the hook handler should be as lightweight as possible, and definitely avoid any thread related activities.

The link you provided is invalid for full example so I can’t really comment further.

@bwmaples
Copy link
Author

bwmaples commented Mar 13, 2022

I've tried printing nothing, but it still crashes.

internal static CorJitCompiler.CorJitResult compileMethodDel(IntPtr thisPtr, [In] IntPtr corJitInfoPtr, [In] CorInfo* methodInfo,
    CorJitFlag flags, [Out] IntPtr nativeEntry, [Out] IntPtr nativeSizeOfCode)
{
    return originCompile(thisPtr, corJitInfoPtr, methodInfo, flags, nativeEntry, nativeSizeOfCode);
}

And I have update the link of full example, please try again or try this
https://github.com/bwmaples/HookJITCompileMethod

I also tried to run as administrator and it also fails

@bwmaples
Copy link
Author

bwmaples commented Mar 13, 2022

If I use this code, the program works, but I can't modify the compileMethod.

CompileMethodHook = LocalHook.Create(
    originCompilePtr,
    originCompile ,
    this);
CompileMethodHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

But I can't modify the target method.
It looks like a stack issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants