{"id":13607700,"url":"https://github.com/knah/Il2CppAssemblyUnhollower","last_synced_at":"2025-04-12T14:31:03.885Z","repository":{"id":37759037,"uuid":"253941573","full_name":"knah/Il2CppAssemblyUnhollower","owner":"knah","description":"A tool to generate Managed-\u003eIL2CPP proxy assemblies","archived":true,"fork":false,"pushed_at":"2024-07-01T18:28:45.000Z","size":1595,"stargazers_count":504,"open_issues_count":29,"forks_count":87,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-10-31T20:28:11.534Z","etag":null,"topics":["il2cpp","il2cppdumper","modding-games","modding-tools","unity3d"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/knah.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING.LESSER","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-08T00:09:18.000Z","updated_at":"2024-10-22T09:50:28.000Z","dependencies_parsed_at":"2023-01-19T13:16:42.096Z","dependency_job_id":null,"html_url":"https://github.com/knah/Il2CppAssemblyUnhollower","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knah%2FIl2CppAssemblyUnhollower","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knah%2FIl2CppAssemblyUnhollower/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knah%2FIl2CppAssemblyUnhollower/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/knah%2FIl2CppAssemblyUnhollower/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/knah","download_url":"https://codeload.github.com/knah/Il2CppAssemblyUnhollower/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248581061,"owners_count":21128098,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["il2cpp","il2cppdumper","modding-games","modding-tools","unity3d"],"created_at":"2024-08-01T19:01:20.846Z","updated_at":"2025-04-12T14:31:03.185Z","avatar_url":"https://github.com/knah.png","language":"C#","funding_links":[],"categories":["C# #"],"sub_categories":[],"readme":"# Archival note\nThis repository has been unmaintained for a while and will be archived soon. Consider using [BepInEx/Il2CppInterop](https://github.com/BepInEx/Il2CppInterop/) as a replacement.\n\n# Il2CppAssemblyUnhollower\nA tool to generate Managed-\u003eIL2CPP proxy assemblies from\n [Il2CppDumper](https://github.com/Perfare/Il2CppDumper )'s output.\n\nThis allows the use of IL2CPP domain and objects in it from a managed domain. \nThis includes generic types and methods, arrays, and new object creation. Some things may be horribly broken. \n \n## Usage\n  0. Build or get a release\n  1. Obtain dummy assemblies using [Il2CppDumper](https://github.com/Perfare/Il2CppDumper)\n  2. Run `AssemblyUnhollower --input=\u003cpath to Il2CppDumper's dummy dll dir\u003e --output=\u003coutput directory\u003e --mscorlib=\u003cpath to target mscorlib\u003e`    \n       \n Resulting assemblies may be used with your favorite loader that offers a Mono domain in the IL2CPP game process, such as [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader).    \n This appears to be working reasonably well for Unity 2018.4.x games, but more extensive testing is required.  \n Generated assemblies appear to be invalid according to .NET Core/.NET Framework, but run fine on Mono.\n\n### Command-line parameter reference\n```\nUsage: AssemblyUnhollower [parameters]\nPossible parameters:\n        --help, -h, /? - Optional. Show this help\n        --verbose - Optional. Produce more console output\n        --input=\u003cdirectory path\u003e - Required. Directory with Il2CppDumper's dummy assemblies\n        --output=\u003cdirectory path\u003e - Required. Directory to put results into\n        --mscorlib=\u003cfile path\u003e - Required. mscorlib.dll of target runtime system (typically loader's)\n        --unity=\u003cdirectory path\u003e - Optional. Directory with original Unity assemblies for unstripping\n        --gameassembly=\u003cfile path\u003e - Optional. Path to GameAssembly.dll. Used for certain analyses\n        --deobf-uniq-chars=\u003cnumber\u003e - Optional. How many characters per unique token to use during deobfuscation\n        --deobf-uniq-max=\u003cnumber\u003e - Optional. How many maximum unique tokens per type are allowed during deobfuscation\n        --deobf-analyze - Optional. Analyze deobfuscation performance with different parameter values. Will not generate assemblies.\n        --blacklist-assembly=\u003cassembly name\u003e - Optional. Don't write specified assembly to output. Can be used multiple times\n        --add-prefix-to=\u003cassembly name/namespace\u003e - Optional. Assemblies and namespaces starting with these will get an Il2Cpp prefix in generated assemblies. Can be used multiple times.\n        --no-xref-cache - Optional. Don't generate xref scanning cache. All scanning will be done at runtime.\n        --no-copy-unhollower-libs - Optional. Don't copy unhollower libraries to output directory\n        --obf-regex=\u003cregex\u003e - Optional. Specifies a regex for obfuscated names. All types and members matching will be renamed\n        --rename-map=\u003cfile path\u003e - Optional. Specifies a file specifying rename map for obfuscated types and members\n        --passthrough-names - Optional. If specified, names will be copied from input assemblies as-is without renaming or deobfuscation\nDeobfuscation map generation mode:\n        --deobf-generate - Generate a deobfuscation map for input files. Will not generate assemblies.\n        --deobf-generate-asm=\u003cassembly name\u003e - Optional. Include this assembly for deobfuscation map generation. If none are specified, all assemblies will be included.\n        --deobf-generate-new=\u003cdirectory path\u003e - Required. Specifies the directory with new (obfuscated) assemblies. The --input parameter specifies old (unobfuscated) assemblies. \n```\n\n## Required external setup\nBefore certain features can be used (namely class injection and delegate conversion), some external setup is required.\n * Set `ClassInjector.Detour` to an implementation of a managed detour with semantics as described in the interface \n * Alternatively, set `ClassInjector.DoHook` to an Action with same semantics as `DetourAttach` (signature `void**, void*`, first is a pointer to a variable containing pointer to hooked code start, second is a pointer to patch code start, a pointer to call-original code start is written to the first parameter)\n * Call `UnityVersionHandler.Initialize` with appropriate Unity version (default is 2018.4.20)\n\n## Known Issues\n * Non-blittable structs can't be used in delegates\n * Types implementing interfaces, particularly IEnumerable, may be arbitrarily janky with interface methods. Additionally, using them in foreach may result in implicit casts on managed side (instead of `Cast\u003cT\u003e`, see below), leading to exceptions. Use `var` in `foreach` or use `for` instead of `foreach` when possible as a workaround, or cast them to the specific interface you want to use.\n * in/out/ref parameters on generic parameter types (like `out T` in `Dictionary.TryGetValue`) are currently broken\n * Unity unstripping only partially restores types, and certain methods can't be unstripped still; some calls to unstripped methods might result in crashes\n * Unstripped methods with array operations inside contain invalid bytecode\n * Unstripped methods with casts inside will likely throw invalid cast exceptions or produce nulls\n * Some unstripped methods are stubbed with `NotSupportedException` in cases where rewrite failed\n * Nullables have issues when returned from field/property getters and methods\n\n## Generated assemblies caveats\n * IL2CPP types must be cast using `.Cast\u003cT\u003e` or `.TryCast\u003cT\u003e` methods instead of C-style casts or `as`.\n * When IL2CPP code requires a `System.Type`, use `Il2CppType.Of\u003cT\u003e()` instead of `typeof(T)`\n * For IL2CPP delegate types, use the implicit conversion from `System.Action` or `System.Func`, like this: `UnityAction a = new Action(() =\u003e {})` or `var x = (UnityAction) new Action(() =\u003e {})`\n * IL2CPP assemblies are stripped, so some methods or even classes could be missing compared to pre-IL2CPP assemblies. This is mostly applicable to Unity assemblies.\n * Using generics with value types may lead to exceptions or crashes because of missing method bodies. If a specific value-typed generic signature was not used in original game code, it can't be used externally either.\n\n## Class injection\nStarting with version 0.4.0.0, managed classes can be injected into IL2CPP domain. Currently this is fairly limited, but functional enough for GC integration and implementing custom MonoBehaviors.\n\nHow-to:\n * Your class must inherit from a non-abstract IL2CPP class.\n * You must include a constructor that takes IntPtr and passes it to base class constructor. It will be called when objects of your class are created from IL2CPP side.\n * To create your object from managed side, call base class IntPtr constructor with result of `ClassInjector.DerivedConstructorPointer\u003cT\u003e()`, where T is your class type, and call `ClassInjector.DerivedConstructorBody(this)` in constructor body.\n * An example of injected class is `Il2CppToMonoDelegateReference` in [DelegateSupport.cs](UnhollowerRuntimeLib/DelegateSupport.cs)\n * Call `ClassInjector.RegisterTypeInIl2Cpp\u003cT\u003e()` before first use of class to be injected\n * The injected class can be used normally afterwards, for example a custom MonoBehavior implementation would work with `AddComponent\u003cT\u003e`\n \nFine-tuning:\n  * `[HideFromIl2Cpp]` can be used to prevent a method from being exposed to il2cpp\n \nCaveats:\n * Injected class instances are handled by IL2CPP garbage collection. This means that an object may be collected even if it's referenced from managed domain. Attempting to use that object afterwards will result in `ObjectCollectedException`. Conversely, managed representation of injected object will not be garbage collected as long as it's referenced from IL2CPP domain.\n * It might be possible to create a cross-domain reference loop that will prevent objects from being garbage collected. Avoid doing anything that will result in injected class instances (indirectly) storing references to itself. The simplest example of how to leak memory is this:\n```c#\nclass Injected: Il2CppSystem.Object {\n    Il2CppSystem.Collections.Generic.List\u003cIl2CppSystem.Object\u003e list = new ...;\n    public Injected() {\n        list.Add(this); // reference to itself through an IL2CPP list. This will prevent both this and list from being garbage collected, ever.\n    }\n}\n```\n\nLimitations:\n * Interfaces can't be implemented\n * Virtual methods can't be overridden\n * Only instance methods are exposed to IL2CPP side - no fields, properties, events or static methods will be visible to IL2CPP reflection\n * Only a limited set of types is supported for method signatures\n \n## Injected components in asset bundles\n Starting with version 0.4.15.0, injected components can be used in asset bundles. Currently, deserialization for component fields is not supported. Any fields on the component will initially have their default value as defined in the mono assembly.\n\n How-to:\n * Your class must meet the above critereon mentioned in Class Injection.\n * Add a dummy script for your component into Unity. Remove any methods, constructors, and properties. Fields can optionally be left in for future deserialization support.\n * Apply the component to your intended objects in Unity and build the asset bundle.\n * At runtime, register your component with `RegisterTypeInIl2Cpp` before loading any objects from the asset bundle.\n\n## Implementing interfaces with injected types\nStarting with 0.4.16.0, injected types can implement IL2CPP interfaces.  \nJust like previously, your type can't implement the interface directly, as it's still generated as a class.  \nHowever, you can pass additional interface types to `RegisterTypeInIl2CppWithInterfaces`, and they will be implemented as interfaces on the IL2CPP version of your type.  \nInterface methods are matched to methods in your class by name, parameter count and genericness.  \nKnown caveats:   \n * `obj.Cast\u003cInterfaceType\u003e()` will fail if you try to cast an object of your injected type to an interface. You can work around that with `new InterfaceType(obj.Pointer)` if you're absolutely sure it implements that interface.\n * Limited method matching might result in some interfaces being trickier or impossible to implement, namely those with overloads differing only in parameter types.\n\n## PDB generator\nUnhollowerPdbGen builds an executable that can be ran to generate a Microsoft PDB file (debug symbols) for GameAssembly.dll based on unhollower-generated names.  \nThis can be useful for analyzing code of obfuscated games. For unobfuscated games, using [Il2CppInspector](https://github.com/djkaty/Il2CppInspector) would provide way better results for code analysis.  \nGenerated PDBs were tested with windbg, lldb, WPA viewer/ETL performance analysis and IDA.  \nGenerated PDBs only include generated methods, and don't include type info, generic method info and IL2CPP internals.   \nYou need to manually copy the following Microsoft-provided libraries from Visual Studio (or other build tools) for this to work - I'm not redistributing them as license on them is not clear.  \n * `mspdbcore.dll`\n * `msobj140.dll`\n * `tbbmalloc.dll`\n\nThese need to be placed next to the built .exe file. Use file search to find `mspdbcore` in VS install. \n\n## Upcoming features (aka TODO list)\n * Unstripping engine code - fix current issues with unstripping failing or generating invalid bytecode\n * Proper interface support - IL2CPP interfaces will be generated as interfaces and properly implemented by IL2CPP types\n * Improve class injection to support virtual methods and interfaces\n * Improve class injection to support deserializing fields\n\n## Used libraries\nBundled into output files:\n * [iced](https://github.com/0xd4d/iced) by 0xd4d, an x86 disassembler used for xref scanning and possibly more in the future\n\nUsed by generator itself:\n * [Mono.Cecil](https://github.com/jbevain/cecil) by jbevain, the main tool to produce assemblies\n\nParts of source used:\n * [microsoft-pdb](https://github.com/microsoft/microsoft-pdb) for the PDB generator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknah%2FIl2CppAssemblyUnhollower","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknah%2FIl2CppAssemblyUnhollower","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknah%2FIl2CppAssemblyUnhollower/lists"}