Keypoints
- Harmony is an in-memory .NET hooking library that patches, decorates, or replaces methods at runtime without touching disk files.
- Primary Harmony patch types are Prefix (run before), Postfix (run after), Transpiler (modify IL), Finalizer (exception handling), and Reverse Patch (create callable original copy).
- Bootstrapping requires running code inside the target process—achieved via Reflection-based loaders or external injectors (e.g., ExtremeDumper) to install Harmony patches.
- Manual patching uses reflection/AccessTools to locate runtime methods; Prefix patches use ref parameters and can skip originals by returning false and setting __result.
- Transpilers operate on IEnumerable to change IL (e.g., replace add with sub + ldc.i4.1), enabling fine-grained runtime logic changes.
- Practical application: patching Assembly.GetCallingAssembly() to return the obfuscated assembly enables automated decryption of ConfuserEx2-protected constants (ConfuserEx2_String_Decryptor); dnSpyEx Watch Window can invoke InstallHook/UninstallHook to control patches from the debugger.
MITRE Techniques
- No MITRE ATT&CK techniques are explicitly mentioned in the article.
Indicators of Compromise
- [Domain] Article/source – research.checkpoint.com
- [File name] Loader/target examples – Example.exe, Captain_HooK.dll
- [Repository URL] Tools referenced – https://github.com/Dump-GUY/ConfuserEx2_String_Decryptor, https://github.com/pardeike/Harmony, and other referenced repositories
To instrument .NET code at runtime, load the target assembly into a bootstrapper (either via Reflection from a loader process or by injecting a DLL into the target process) and initialize Harmony with a unique instance ID. Use Reflection or Harmony’s AccessTools to resolve MethodInfo objects for the runtime types/methods you want to patch (e.g., AccessTools.Method(“Example.Program:Sum”) for methods in loaded assemblies). Install patches by calling harmony.Patch(target, prefix: new HarmonyMethod(pre), postfix: new HarmonyMethod(post), transpiler: new HarmonyMethod(transpiler)) as needed. Prefix methods receive arguments by ref to modify inputs and can skip the original by returning false and setting ref __result; Postfix methods receive ref __result to modify return values after execution; Transpiler methods must return IEnumerable and are used to transform IL sequences (insert/substitute opcodes) at runtime; Reverse Patches create callable, unmodified snapshots of originals (CreateReversePatcher) and Harmony.Unpatch/UnpatchAll can remove applied patches.
Key implementation details include using ref parameters to change method arguments, adding ref __result to alter or provide return values while skipping execution, and iterating CodeInstruction lists to find and replace IL opcodes in Transpilers. When the target method resides in a loaded runtime type, avoid typeof()/nameof() and resolve via reflection/AccessTools. For unpatching while inside a patch, call UnpatchAll() from the patch code to restore subsequent calls to the original implementation.
For practical deobfuscation, load the obfuscated assembly into memory (store in a static Assembly variable like LoadedAssembly) and install a Prefix patch on System.Reflection.Assembly.GetCallingAssembly() that sets ref Assembly __result = LoadedAssembly and returns false to bypass ConfuserEx2’s Assembly.GetExecutingAssembly().Equals(Assembly.GetCallingAssembly()) checks. Combine this with a parsing pass (e.g., AsmResolver) to enumerate constant decryption call sites and invoke decryption methods via Reflection to recover strings; the resulting tool is ConfuserEx2_String_Decryptor. For precise runtime control, compile a small Harmony hook library exposing InstallHook() and UninstallHook(), then from dnSpyEx’s Watch Window evaluate expressions such as ((Assembly.LoadFile(@”C:Captain_HooK.dll”).GetType(“Captain_HooK.HooK”)).GetMethod(“InstallHook”)).Invoke(null, null) to install/uninstall hooks at chosen breakpoints or moments during debugging.
Read more: https://research.checkpoint.com/2024/net-hooking-harmonizing-managed-territory/