Jitex
A library to modify MSIL and native code at runtime
Install / Use
/learn @Hitmasu/JitexREADME
<img src="logos/jitex.svg" width="100" align="left"/> Jitex

A library to modify MSIL/Native code at runtime.
It's a library built in .NET Standard 2.0, works on all version >=.NET Core 2.0.
| | .NET Core (2.1 ~ 3.1) | .NET 5~8 | .NET Framework | Mono | | ----------- | --------------------- | ------------------ | -------------------------------------- | ----------------- | | Windows (x86/x64/ARM64) | :heavy_check_mark: | :heavy_check_mark: | :x: Not supported | :x: Not supported | | Linux (x86/x64/ARM64) | :heavy_check_mark: | :heavy_check_mark: | :x: Not supported | :x: Not supported | | MacOS (x86/x64/ARM64) | :heavy_check_mark: | :heavy_check_mark: | :x: Not supported | :x: Not supported |
Jitex can help you replace code at runtime easily.
using System;
using Jitex;
JitexManager.MethodResolver += context =>
{
if (context.Method.Name.Contains("Sum"))
context.ResolveMethod(Mul); //Replace Sum by Mul
};
int result = Sum(5, 5);
Console.WriteLine(result); //Output is 25
static int Sum(int n1, int n2) => n1 + n2;
static int Mul(int n1, int n2) => n1 * n2;
Support
- Intercept call method
- Modify normal and generic methods
- Detour method
- Replace MSIL code (IL)
- Replace native code
- Execute custom metadatatoken
- Replace content string
- Modules
Intercept call
using System;
using Jitex;
JitexManager.MethodResolver += context =>
{
if (context.Method.Name.Contains("Sum"))
context.InterceptCall();
};
//Every call from Sum, will be pass here.
JitexManager.Interceptor += async context =>
{
//Get parameters passed in call
int n1 = context.GetParameterValue<int>(0);
int n2 = context.GetParameterValue<int>(1);
n1 *= 10;
n2 *= 10;
//Override parameters value
context.SetParameterValue(0, n1);
context.SetParameterValue(1, n2);
//Or we can just set return value
context.SetReturnValue(100);
};
int result = Sum(5, 5); //Output is 100
Console.WriteLine(result);
int Sum(int n1, int n2) => n1 * n2;
Replace Method
/// <summary>
/// Take sum of 2 random numbers
/// </summary>
/// <returns></returns>
public static int SumReplace ()
{
const string url = "https://www.random.org/integers/?num=2&min=1&max=999&col=2&base=10&format=plain&rnd=new";
using HttpClient client = new HttpClient ();
using HttpResponseMessage response = client.GetAsync (url).Result;
string content = response.Content.ReadAsStringAsync ().Result;
string[] columns = content.Split ("\t");
int num1 = int.Parse (columns[0]);
int num2 = int.Parse (columns[1]);
return num1 + num2;
}
private static void MethodResolver (MethodContext context)
{
if (context.Method.Name == "Sum") {
//Replace Sum to our SumReplace
MethodInfo replaceSumMethod = typeof (Program).GetMethod (nameof (SumReplace));
context.ResolveMethod (replaceSumMethod);
}
}
Detour Method
private static void MethodResolver (MethodContext context) {
if (context.Method.Name == "Sum") {
//Detour by MethodInfo
MethodInfo detourMethod = typeof (Program).GetMethod (nameof (SumDetour));
context.ResolveDetour (detourMethod);
//or
context.ResolveDetour<Action> (SumDetour);
//Detour by Action or Func
Action<int, int> detourAction = (n1, n2) => {
Console.WriteLine ("Detoured");
Console.WriteLine (n1 + n2);
};
context.ResolveDetour (detourAction);
//Detour by Address
IntPtr addressMethod = default; //Address of method to execute.
context.ResolveDetour (addressMethod);
}
}
Replace MSIL
private static void MethodResolver (MethodContext context)
{
if (context.Method.Name == "Sum") {
//num1 * num2
byte[] newIL = {
(byte) OpCodes.Ldarg_0.Value, //parameter num1
(byte) OpCodes.Ldarg_1.Value, //parameter num2
(byte) OpCodes.Mul.Value,
(byte) OpCodes.Ret.Value
};
MethodBody body = new MethodBody (newIL, context.Method.Module);
context.ResolveBody (body);
}
}
Replace Native Code
private static void MethodResolver (MethodContext context)
{
if (context.Method.Name == "Sum") {
Assembler assembler = new Assembler (64);
//Replace with fatorial number:
//int sum = num1+num2;
//int fatorial = 1;
//for(int i = 2; i <= sum; i++){
// fatorial *= i;
//}
//return fatorial;
assembler.add (edx, ecx);
assembler.mov (eax, 1);
assembler.mov (ecx, 2);
assembler.cmp (edx, 0x02);
assembler.jl (assembler.@F);
assembler.AnonymousLabel ();
assembler.imul (eax, ecx);
assembler.inc (ecx);
assembler.cmp (ecx, edx);
assembler.jle (assembler.@B);
assembler.AnonymousLabel ();
assembler.ret ();
using MemoryStream ms = new MemoryStream ();
assembler.Assemble (new StreamCodeWriter (ms), 0);
byte[] asm = ms.ToArray ();
context.ResolveNative (asm);
}
}
Inject custom MetadataToken
You can inject a custom metadata too, in this way, you can "execute" metadatatoken not referenced in compile-time:
/// <summary>
/// Example of a external library to replace Sum.
/// </summary>
/// <remarks>
/// We replace Sum to return the PID of process running. To do this, normally we need
/// reference assembly (System.Diagnostics.Process) and class Process.
/// In this case, the original module, dont have any reference to namespace System.Diagnostics.Process.
/// As we pass the MetadataToken from Process.GetCurrentProcess().Id, its necessary resolve that manually,
/// because CLR dont have any information about that in original module.
/// </remarks>
public static class ExternLibrary
{
private static MethodInfo _getCurrentProcess;
private static MethodInfo _getterId;
static ExternLibrary()
{
LoadAssemblyDiagnostics();
}
public static void Initialize()
{
JitexManager.AddMethodResolver(MethodResolver);
JitexManager.AddTokenResolver(TokenResolver);
}
private static void LoadAssemblyDiagnostics()
{
string pathAssembly = Path.Combine(Directory.GetCurrentDirectory(), "../../../../", "System.Diagnostics.Process.dll");
Assembly assemblyDiagnostics = Assembly.LoadFrom(pathAssembly);
Type typeProcess = assemblyDiagnostics.GetType("System.Diagnostics.Process");
_getCurrentProcess = typeProcess.GetMethod("GetCurrentProcess");
_getterId = _getCurrentProcess.ReturnType.GetProperty("Id", BindingFlags.Public | BindingFlags.Instance).GetGetMethod();
}
private static void TokenResolver(TokenContext context)
{
if (context.TokenType == TokenKind.Method && context.Source.Name == "Sum")
{
if (context.MetadataToken == _getCurrentProcess.MetadataToken)
{
context.ResolveMethod(_getCurrentProcess);
}
else if (context.MetadataToken == _getterId.MetadataToken)
{
context.ResolveMethod(_getterId);
}
}
}
private static void MethodResolver(MethodContext context)
{
if (context.Method.Name == "Sum")
{
List<byte> newIl = new List<byte>();
newIl.Add((byte)OpCodes.Call.Value);
newIl.AddRange(BitConverter.GetBytes(_getCurrentProcess.MetadataToken));
newIl.Add((byte)OpCodes.Call.Value);
newIl.AddRange(BitConverter.GetBytes(_getterId.MetadataToken));
newIl.Add((byte)OpCodes.Ret.Value);
MethodBody methodBody = new MethodBody(newIl.ToArray(), _getCurrentProcess.Module);
context.ResolveBody(methodBody);
}
}
}
static void Main (string[] args) {
ExternLibrary.Initialize ();
int result = Sum (1, 7);
Console.WriteLine (result); //output is PID
}
Replace content string
private static void TokenResolver (TokenContext context) {
if (context.TokenType == TokenKind.String && context.Content == "Hello World!")
context.ResolveString ("H3110 W0RLD!");
}
static void Main (string[] args) {
ExternLibrary.Initialize ();
HelloWorld (); //output is H3110 W0RLD!
}
static void HelloWorld () {
Console.WriteLine ("Hello World!");
}
Modules
Jitex can support modules. To create your own module, just extend JitexModule:
public class ModuleJitex : JitexModule
{
protected override void MethodResolver(MethodContext context)
{
//...
}
protected override void TokenResolver(TokenContext context)
{
//...
}
}
And load module:
JitexManager.LoadModule<ModuleJitex>();
//or...
JitexManager.LoadModule(typeof(ModuleJitex));
ASP.NET Core support
To load module in ASP.NET Core, just call UseModule in Configure (Startup.cs):
app.UseModule<ModuleJitex>();
app.UseModule<ModuleJitex1>();
app.UseModule<ModuleJitex2>();
//or
app.UseModule(typeof(ModuleJitex);
Proof of Concept
Nitter - A easy mocker for .NET
AutoMapper Patcher - A simple remover AutoMapper at runtime.
InAsm - Run assembly directly from a method.
Thanks
Replace methods was an idea to increase performance in .NET Applications. Searching a way to do that, i've found this hook implementation from @xoofx [Writing a Managed JIT in C# with CoreCLR](https://xoofx.com/blog/2018/04/12/writing-man
Related Skills
node-connect
349.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
109.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
349.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
349.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
