Thank you for the mod. How did you go about implementing the hook into the game?
Been trying to get some IL2CPP games working with my CubiLink plugin.
But the API/metadata encryption/protection most of them have makes it impossible for BepInEx to even load. Did you recover the relevant GameAssembly methods manually or use some tool?
Thanks. For this game, I did not use a normal BepInEx workflow.
The game has both IL2CPP API obfuscation and encrypted/obfuscated global-metadata.dat, so BepInEx could not load normally. My solution was closer to a native DLL hook approach: I used a runtime IL2CPP dumping method, fixed the IL2CPP API lookup problem first, generated a usable dump.cs, then used the dumped method info to hook the relevant GameAssembly methods directly with MinHook.
For IL2CPP protected games, I think there are two separate cases:
1. Only global-metadata.dat is encrypted or obfuscated
In this case, BepInEx may still start and show a console, but Il2CppInterop/Cpp2IL fails when generating the interop assemblies under:
BepInEx\interop\
Usually the error will mention encrypted or invalid global-metadata.dat.
A quick check is to open global-metadata.dat in a hex editor. If the first four bytes are:
AF 1B B1 FA
that is usually a good sign that the metadata is not heavily obfuscated, although it is not a guarantee.
If the metadata is protected, you can inspect GameAssembly.dll in IDA and look around the normal IL2CPP initialization chain:
The game’s metadata decryption or loading logic is usually somewhere around there.
This article explains the general idea well:
Another approach is to search process memory for the AF 1B B1 FA metadata magic after the game has started, then dump the decrypted metadata from memory.
Once you have a valid global-metadata.dat, you can use:
to generate usable IL2CPP information.
2. IL2CPP API exports are also obfuscated
This is worse. In this case, BepInEx may not start at all, often with no console.
Unity loads IL2CPP APIs from GameAssembly.dll through GetProcAddress, so you can inspect UnityPlayer.dll in IDA and search for the GameAssembly.dll string to find the loading logic.
Another practical way is to hook or log GetProcAddress and observe the API lookup order at runtime.
After that, check the Unity version from UnityPlayer.dll properties, then compare the expected IL2CPP API order for that Unity version against the obfuscated export strings being requested. This lets you map names like:
il2cpp_domain_get
il2cpp_init
...
to their obfuscated export names.
To make BepInEx work, you would then need to patch the places where BepInEx loads IL2CPP APIs, for example by changing the P/Invoke EntryPoint values to the obfuscated export names. The proxy/preloader side may also need fixes, especially anything that checks or loads il2cpp_init.
What I did for this mod
For this game, I used a runtime IL2CPP dumper approach instead of fully fixing BepInEx.
A possible route is to adapt something like:
or use a Windows port/fork of a runtime IL2CPP dumper. If it can generate dump.cs, then the IL2CPP API problem is either absent or already solved. If it cannot, you need to patch the dumper’s IL2CPP API loading to use the correct obfuscated export names.
After I had a usable dump.cs, I located the relevant game methods and hooked them directly by address/RVA using MinHook.
So, no, I did not manually recover every GameAssembly method. I mainly solved enough of the runtime IL2CPP API/metadata problem to get a dump, then used the dumped method addresses for native hooks.
For CubiLink, since it is already a BepInEx plugin, the direct native hook route may not be immediately compatible. You would probably either need to repair BepInEx’s IL2CPP API loading for the target game, or create a separate native bridge/loader that reproduces the data CubiLink expects.
For games like Moka Love ReLive, BepInEx/MelonLoader proxies seem to get picked up, but the managed loader never starts, so most likely the IL2CPP API exports are obfuscated there as well.
I’ll see if I can hook relevant GameAssembly methods directly and bridge the data back into CubiLink.
It seems this game uses Live2D assets from virtual streamers. Maybe they encrypted them to prevent the assets from being leaked? In any case, it’s really frustrating that games like this use such complex encryption and obfuscation methods—you’d expect to see that kind of encryption in large-scale Unity games. I don’t understand whether they’re using encryption for anti-cheat purposes or to prevent piracy. For games on DLsite, since they can run simply by copying the files to another computer, what role does encryption even play in this process? Aside from creating unnecessary trouble for mod creators, what’s the point?
Dammit, I JUST 100% this game! I highly recommend it and will still grab the mod for good times! Thank you for the effort, it sounds like it was more troublesome then usual to mod.
Hello, my device is a Linear one and can connect to Intiface Central. However, when the mod tries to connect to Intiface Central, it throws an error, and the device cannot sync with the game. In the device sync section, after I click connect or scan IC, Intiface Central shows that the client is connected. But the device sync section shows it is connected to IC with no available device. The error reported in IC is:
Client connected: HypnoApp2 Hook
68.058 Error serializing message: “[{"Error":{"ErrorCode":3,"ErrorMessage":"{\"ButtplugMessageError\":{\"MessageSerializationError\":{\"JsonSerializerError\":\"[{\\\"DeviceList\\\":{\\\"Devices\\\":[{\\\"DeviceIndex\\\":0,\\\"DeviceMessages\\\":{\\\"LinearCmd\\\":{\\\"FeatureCount\\\":1},\\\"stop_device_cmd\\\":{}},\\\"DeviceName\\\":\\\"ServeU\\\"}],\\\"Id\\\":2}}] is not valid under any of the schemas listed in the ‘anyOf’ keyword\"}}}","Id":0}}]”
Thank you very much! Also, would you consider adding UDP connection support for T-code? Some OSR2 devices may have Wi-Fi capability and could connect via UDP.
I’m having trouble with the game actually launching after the Bepin consle for ItemModel_penis Hook Console loads and shows the intiface connection to my Handy 2 Pro was succesful. Has anyone else had similar issues and know how to resolve?