It brings back memories of when I spent six months fighting a company (one person doing the work) writing a cheat package for our game by trying to make his life hell in our binary. Both obfuscation and the opposite are amazingly fun to work on; you have to understand both ends to be effective. Eventually, I made the guy give up as it was too much work for insufficient money (the cheat cost more monthly than we charged for the game, but in reality most people did not use it). In my case, it was not Python (our game was C/C++), but the difficulty was similar. It's hard to cheat in WO* games as the server validates everything.
These are both great. The original RotP is no longer being actively developed, but there are a couple of forks on GitHub that stay in sync with one another and have continued building on the base.
Post author here. Thanks to the folks who read through my rambling. There was another trick I discovered a couple days after writing this blog post while trying to fix a file that was decompiling with just empty output. The code pattern that tripped it up was something like the following:
SOME_VALUE = {value: key for (key, value) in Foo.__dict__.iteritems() }
Which at a bytecode level expands to something like:
def <dictcomp>(input):
result = {}
for (key, value) in input:
result[value] = key
return result
SOME_VALUE = <dictcomp>(Foo.__dict__.iteritems())
The name `<dictcomp>` is intentional here. Decompilers (or at least uncompyle) relies on the function name to figure out what composition syntax the function is for (or a lambda, or generator). The python compiler emits `<dictcom>`, `<setcomp>`, `<listcomp>`, `<genexpr>`, and `<lambda>` depending on the type of function. The obfuscator renamed this function of course and causes the decompiler choke on a whole file if this appears at a module level.
The game developers also reached out to me and others after seeing this post appear on the /r/WorldofWarships subreddit. They want to understand why we would need to introspect these files for mod creation or data mining.
I already explained some of this in the post, but at a mod level the API docs are _really_ bad and actually no longer exist since the developers migrated away from a standard forum to Discord for all comms and killed the forum. For ModAPIv2 which is heavily restricted to pre-approved mod developers there are no docs at all!
Additionally, they rely on a community-created tool for rendering replays to an MP4 for their tournament match recaps: https://github.com/WoWs-Builder-Team/minimap_renderer. The replay format is entirely undocumented and relies on data mined from this tool and other resources for parsing some data structures.
There are a _ton_ of community-developed resources that have only been made possible through reverse engineering of some shape that are critical for understanding the game. I do appreciate them reaching out for hopefully a positive dialog.
"my patches and additions on top of Ian's code are licensed under the ABSE ("Anyone But Stefan Esser") license. note that an additional exception to the license is added, forbidding use/redistribution of said content to his trainees as well, but only when in a 5 mile radius from "Stefan Esser" or while holding any sort of (video)conference/chat with him."
Stefan esser was a bit infamous in the iOS jailbreak scene for being a bit of an ass and trolling the community to try to get people to pay for his iOS security lessons.
This was before my time but my understanding was he would teach people things and then get upset for “leaking” his materials if they talked about them externally.
as someone who works on static analysis of (regular, non-obfuscated) python bytecode, that was super interesting. if this sort of thing were more common, i could see people developing interactive tools that let you iteratively poke at the pyc files to help the decompiler along, and in the process hopefully identify patterns you could then automate.