Fulgeratorul02
Onshi
Ever since I found out about the game I was wondering if I could still play it. I tried downloading from a few sites but they didn't work.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Huh didn't know he uploaded this. I have a fully functional game that he privately distributed to my phone. I forgot how to launch and am also not sure how to run it any longer, but I can confirm it still works. The save file is still defaulted though.The official server of this game is shut down, so it is impossible to launch in normal way. But it looks like it is possible to launch a local server ( https://github.com/RainbowUnicorn7297/dankagu-local ), but I am afraid it would require to modify game files to make it possible to connect to it. I didn't try it though.
There may be some other ways how to launch it, but I don't know about them.
I actually don't know how to bypass it and stuff since I don't make it, RainbowUnicorn did, and hes been out of contact for a great while. So it's mostly lost art right now, but it the server still seems largely operable, I'll give it a try if I have free time (probably never) as a proof of conceptomg!?
I can't believe you'd already figured out how to open it.
I also came up with a method using Frida, but I just couldn't find a way to bypass the server check and open it.
If neither of you has any objections to teaching, would it be possible for you to teach us?
Nope, i do not have permission to send it, it'd be up to rainbow himself but i havent seen anything moving in a whileIt's fine if there's no problem, but if you're using a modified APK file, could you send it to me?
If you don't want it made public, I can give you my Discord username, but it's okay if you don't want to share it.
Thank you.Nope, i do not have permission to send it, it'd be up to rainbow himself but i havent seen anything moving in a while

I made a independent Android implementation with a mock local server (based on recently released https://github.com/xapenny/dankagu-reborn) and it's working on most functions except shop emulation & event/gacha timeline emulation (or more)Thank you.
I'll give it my best shot on my own.![]()
Me and AI both forgot somethingI made a independent Android implementation with a mock local server (based on recently released https://github.com/xapenny/dankagu-reborn) and it's working on most functions except shop emulation & event/gacha timeline emulation (or more)
TLDR:
Using a less limited AI (eg I use deepseek and it made it within only 3 days)
Using only Frida is not enough, disassemblers can boost your work
Also for iOS you may find something interesting in https://estertion.win/2021/08/touhou-danmaku-kagura/
Below is what AI said
---
Your public key error is probably not my error. I hit 30008-1000 App_SecurityError and Check2/CheckGameStart, not a public-key path. But the shape is the same: the client refuses to go on before it ever talks to a server. So here's how I got an unmodified client to reach the main screen, one line per conclusion.
libil2cpp.so is entry-level hashed. Any byte change anywhere in .text aborts in four to five seconds, regardless of meaning, even inside unreachable padding.
So do not patch it at all. This is not difficulty, it's impossibility. Every .text patch looks like it works for four seconds.
It is not a section hash and not semantic detection. It's a per-zip-entry checksum over the whole lib/arm64-v8a/libil2cpp.so.
libmobageemoji.so is outside that scope. Patching it is safe, and that's where all client-side work goes.
The surviving config is libil2cpp.so 100 percent pristine, zero bytes changed. That is also the best config for distribution since users install the stock APK.
If the process dies before any request reaches your server log, it's the integrity check, not your protocol work.
The gate has two layers and both must pass or you get 30008. Layer one is CheckGameStart calling getCodeDigest, which resolves the icall into libmobageemoji.so.
Layer two is the server-side SecureHash lookup against ODMGeneric_SecureHash that the server itself sends.
Layer two only checks ContainsKey, not the value. So return an empty digest and register the empty key server-side, and it passes.
Send a structurally valid JSON array with empty Value strings. Empty bytes or malformed JSON makes the client retry 549 times.
In libmobageemoji.so, four bool getters become mov w0,#0;ret, and four string getters must return a malloc'd empty string.
Never return a .rodata address from the string getters. The wrapper calls il2cpp_free on it, and free on a static address is glibc abort. Return heap memory even if it's one byte.
For finding the PLT, do not use index formulas. Resolve icall strings from .rodata through adrp+add, then .plt to .got to the real slot. Otherwise you patch the wrong function and get a silent no-op.
With that, the boot chain is TOUCH TO START, then name entry, then the asset download from 0 to 100 percent, then the prologue, then the main screen at Hakurei Shrine.
Everything after that is server-side. 227 declared RPCs, 207 implemented. The server is the game, the client is a dumb renderer.
Frida loads fine but config must contain on_load resume, and scripts must write to a File because send() has no native host in gadget mode. Use it to find the gate, don't ship it.
Things that waste time, I burned days on these. Patching libil2cpp .text never works. Patching std::terminate gives SIGBUS. Patching anti-cheat booleans in libil2cpp is irrelevant because the hash kills you first.
More time sinks. Sending empty bytes for SecureHash triggers the 549 retries. Returning .rodata strings from the emoji getters aborts. Debugging crypto with block 0 is useless because the IV makes any key look correct, use block 1.
And the big one: a string in the il2cpp literal table does not mean it's thrown from C#. Mine was thrown from Java smali. Check .smali before decompiling 112 MB of ARM64, or you'll chase the wrong layer for a day.
If your error turns out to be the 30008 path, the two-layer part is your answer. If it's genuinely a public-key mismatch, post the exact error ID, it's a different subsystem and I'd rather not guess.
Tested on Touhou Danmaku Kagura 2.1.0, Android 16 arm64, real device. Client is stock APK with libil2cpp.so sha256 8bd066c1 unmodified. Only libmobageemoji.so is patched, eight patches, outside libil2cpp's hash scope. Server is a reimplementation with 207 of 227 RPCs.
would be nice if you could figure out save filesI made a independent Android implementation with a mock local server (based on recently released https://github.com/xapenny/dankagu-reborn) and it's working on most functions except shop emulation & event/gacha timeline emulation (or more)
TLDR:
Using a less limited AI (eg I use deepseek and it made it within only 3 days)
Using only Frida is not enough, disassemblers can boost your work
Also for iOS you may find something interesting in https://estertion.win/2021/08/touhou-danmaku-kagura/
Below is what AI said
---
Your public key error is probably not my error. I hit 30008-1000 App_SecurityError and Check2/CheckGameStart, not a public-key path. But the shape is the same: the client refuses to go on before it ever talks to a server. So here's how I got an unmodified client to reach the main screen, one line per conclusion.
libil2cpp.so is entry-level hashed. Any byte change anywhere in .text aborts in four to five seconds, regardless of meaning, even inside unreachable padding.
So do not patch it at all. This is not difficulty, it's impossibility. Every .text patch looks like it works for four seconds.
It is not a section hash and not semantic detection. It's a per-zip-entry checksum over the whole lib/arm64-v8a/libil2cpp.so.
libmobageemoji.so is outside that scope. Patching it is safe, and that's where all client-side work goes.
The surviving config is libil2cpp.so 100 percent pristine, zero bytes changed. That is also the best config for distribution since users install the stock APK.
If the process dies before any request reaches your server log, it's the integrity check, not your protocol work.
The gate has two layers and both must pass or you get 30008. Layer one is CheckGameStart calling getCodeDigest, which resolves the icall into libmobageemoji.so.
Layer two is the server-side SecureHash lookup against ODMGeneric_SecureHash that the server itself sends.
Layer two only checks ContainsKey, not the value. So return an empty digest and register the empty key server-side, and it passes.
Send a structurally valid JSON array with empty Value strings. Empty bytes or malformed JSON makes the client retry 549 times.
In libmobageemoji.so, four bool getters become mov w0,#0;ret, and four string getters must return a malloc'd empty string.
Never return a .rodata address from the string getters. The wrapper calls il2cpp_free on it, and free on a static address is glibc abort. Return heap memory even if it's one byte.
For finding the PLT, do not use index formulas. Resolve icall strings from .rodata through adrp+add, then .plt to .got to the real slot. Otherwise you patch the wrong function and get a silent no-op.
With that, the boot chain is TOUCH TO START, then name entry, then the asset download from 0 to 100 percent, then the prologue, then the main screen at Hakurei Shrine.
Everything after that is server-side. 227 declared RPCs, 207 implemented. The server is the game, the client is a dumb renderer.
Frida loads fine but config must contain on_load resume, and scripts must write to a File because send() has no native host in gadget mode. Use it to find the gate, don't ship it.
Things that waste time, I burned days on these. Patching libil2cpp .text never works. Patching std::terminate gives SIGBUS. Patching anti-cheat booleans in libil2cpp is irrelevant because the hash kills you first.
More time sinks. Sending empty bytes for SecureHash triggers the 549 retries. Returning .rodata strings from the emoji getters aborts. Debugging crypto with block 0 is useless because the IV makes any key look correct, use block 1.
And the big one: a string in the il2cpp literal table does not mean it's thrown from C#. Mine was thrown from Java smali. Check .smali before decompiling 112 MB of ARM64, or you'll chase the wrong layer for a day.
If your error turns out to be the 30008 path, the two-layer part is your answer. If it's genuinely a public-key mismatch, post the exact error ID, it's a different subsystem and I'd rather not guess.
Tested on Touhou Danmaku Kagura 2.1.0, Android 16 arm64, real device. Client is stock APK with libil2cpp.so sha256 8bd066c1 unmodified. Only libmobageemoji.so is patched, eight patches, outside libil2cpp's hash scope. Server is a reimplementation with 207 of 227 RPCs.
Corrections #2would be nice if you could figure out save files
:~thread() (sym 2189) to std::bad_array_new_length::~bad_array_new_length() (sym 618), which makes that destructor a no-op. I tested this properly: reverted those two bytes to stock, rebuilt, signed, installed. The client still reached the title screen, but aborted the moment I tapped TOUCH TO START. So if you skip this patch, that is where it dies.