Tags: renpy
Rating:
Title: Doki Doki Anticheat | hack.lu 2023
Date: 2023-10-18 21:38
Category: Writeup
Authors: florian0
Tags: Jeopardy, Misc
> Challenge author: m0ezk
>
> Heyo stranger,
> I really need ur help! My PC hasn't been working for the past few days and the only thing I'm left with are my
> savefiles (I always have them on my USB-Stick, just in case). I need to know what's next in my favorite video game,
> could you please load these savefiles and tell me the following dialogue, please, I can't wait any longer!
>
> Here's a link to the game, you can even run it easily on Linux: https://teamsalvato.itch.io/ddlc
>
> I don't know how to contact you, so just text me the dialogue as a flag, ok?
> So if the dialogue says:"Sayori, what is up with you.." Then just send `flag{Sayori,_what_is_up_with_you..}`
> I'd be really REALLY thankful if you'd do that!
The challenge features the game Doki Doki Literature Club. The task is simple. Load up the save game and paste the
content of the next dialog.
We have never touched Doki Doki before. I in particular have no even seen it on YouTube or Twitch. What you get in this
writeup is the full experience of starting a challenge with zero knowledge.
![The archive contains two files. A .save file that is probably the save file, and a persistent file of unknown use](https://zeroflagsinc.gitlab.io/images/doki-doki-archive.png)
A quick online search reveals that the save games live in our user home folder. For linux
that's `~/.renpy/DDLC-1454445547` (where `DDLC-1454445547` like a unique id of the game).
When we just run the game, it will create the folder for us, and place a `persistent` file in it. So that seems to be
like a game config file of some kind.
When we save the game, it will create a .save file.
Placing the challenge files in this folder brings up the save game in the *Load Game* screen.
![Load Game screen in Doki Doki. There is one savegame with a preview picture that shows the Valorant Hacker Detected screen](https://zeroflagsinc.gitlab.io/images/doki-doki-game.png)
However loading the save game brings up the message "The save file could not be loaded. Are you trying to cheat?",
followed by a monologue of a girl named "Monika" mocking us.
![Monika is telling us that simply loading the game does not solve the challenge.](https://zeroflagsinc.gitlab.io/images/doki-doki-monika-mocking-us.png)
Fair enough. The game seems rather well known. There surely is a community for it and the anti cheat is should already
been defeated, right?
A quick search for *Doki Doki Anticheat* brings up a couple of results. Even some people that got this screen, but no
solution. And no in-depth details, which was astounding. The closest we could find was:
https://icecrownserver.fandom.com/wiki/DDLC_Anticheat
This describes the anti cheat as following:
> The game stores a save-irrespective persistent anticheat value, and a save stores a separate anticheat variable. These
> are compared to check for cheating. To ensure that a player doesn't accidentally trigger the anti-cheat event, save
> files are deleted whenever the anticheat variable is updated.
## Dissecting the savegame
We concluded that this means one value is in the save game and one is in the persistent file. Not knowing any of the
formats, we started looking for a save game editor. *Doki Doki Savegame Editor* resulted in nothing, but *Renpy Savegame
Editor*
gave a couple of online editors. Great! We used:
https://saveeditor.online/
The save game has a lot of values. Searching for *anticheat* will give two results:
![Two search results for anticheat. A boolean and a numeric value.](https://zeroflagsinc.gitlab.io/images/doki-doki-save-game-open.png)
At this point we assume that one anticheat value `420`.
> From reading other writeups, we now know that we could have unticked the box and anticheat would have been disabled.
> We did not have that idea. Probably due to a mixture of anime school girl overflow and lack of sleep.
## Dissecting persistence data
We read through the [*Persistent Data* documentation of RenPy](https://www.renpy.org/doc/html/persistent.html), but it
did not reveal anything about the format of that file.
We found hints to a `UnRen.bat`, but we were lacking the Windows environment to run it and did not feel like messing
with wine.
In some gist I am now unable to find again, we found this snippet:
```bash
python -c "import zlib; open('persistent.pickle', 'wb').write(zlib.decompress(open('persistent', 'rb').read()))"
```
This lead to us believing that it might be just a zlib compressed pickle file. And sure enough, it was. Using
pickletools on the decompressed file was a success.
```bash
python3 -m pickletools persistent.pickle | less
```
![pickletools showing the value of the anticheat](https://zeroflagsinc.gitlab.io/images/doki-doki-persistent-anticheat.png)
The other anticheat value seems to be `1337`.
## Fixing the savegame
According to the Wiki Entry we found, these values need to be the same. We already have the save game open in a savegame
editor. Patching the save game sounds like the easiest way right now.
![The save game is loaded successfully and displaying the text "...There is no way I'm going to your club."](https://zeroflagsinc.gitlab.io/images/doki-doki-solved.png)
That's it. The flag is `flag{...There_is_no_way_I'm_going_to_your_club.}`.