• Touhou 6 New Classic Score Attack Ongoing!

    Read the submission rules, prizes and everything inbetween here:

    Good luck!

    Also check out the community art event here! Everyone is welcome!

Is there any way to still play Touhou Danmaku Kagura on the phone?

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.
 
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.
 
Hello. Since I’m Japanese, I’m using a translation tool to send this message, so I apologize if it’s a bit clunky.
I’m currently looking at the Python files for this game’s server and working with Claude to edit the application and server files.
However, the security is stricter than I expected (such as detection of app modifications), and since I’m not an expert to begin with, I’m having a hard time with this.
As far as I understand:
GRPC is embedded within the application.
LCX (-iOS) is not included in the application.
The cause of the error is a public key error.
That’s all I know.
Since this game is originally in Japanese, I can read its error messages better than people overseas, so if everyone is trying to get it back up and running, I’ll help with translations as well.
Thank you.
 
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.
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.
 
omg!?
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?
 
Last edited:
omg!?
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?
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 concept
 
It'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.
 
It'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.
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
 
Thank you.
I'll give it my best shot on my own. 😉
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)
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.
 
Back
Top