Out of nostalgia and dismay at the lack of Classic knowledge left in the community, I have been trying to retrieve the source code of old RuneScape Classic bots. Saevion’s deobfuscator is woefully inadequate to the task; I hacked it beyond the point of reason before deciding that it would be simpler to write my own program. Having overcome my colossal apathy toward potentially time-consuming projects, I wrote a string decryption component last night.
Everyone knows that the official RuneScape client is subjected to minimal obfuscation in the interest of compatibility. You are probably aware that Zelix Klassmaster has various options for encrypting constant strings within a class, and that cheat authors often use this in conjunction with the highest control-flow mangling. If you have made a particular study, you are most likely aware that it is a weak XOR cipher.
Usually, ZKM copies all string constants to a static String array and runs them through an XOR algorithm using a randomly generated key array. It then replaces string push instructions with references to the static array. The array is initialized and decrypted inside a static initializer, which contains ZKM’s inlined decryption code. My program works against classes mangled in this way: it copies the keys and strings from the initializer, decrypts them, and replaces the array references with push instructions for whatever string.
First problem: some classes have multiple string arrays or use a decryption method instead of inlining. I don’t know what triggers Zelix to use these, but countering them should be trivial once I know how to detect them efficiently. I doubt anyone has looked at Zelix in depth, but if you happen to know what distiguishes classes to the string encryption routine, I would appreciate the information.
Secondly, a side effect of including decrypted string constants is a bloated constant pool - the now-unused encrypted constants remain in the pool, sometimes adding kilobytes of size. I know of no efficient method for removing a pool entry and correcting reference indicies. If there is a better way to compress a constant pool than comparing a list of all reference indicies with the constant pool itself, I would appreciate that information as well.
Finally, I have attached the source code to this post - just in case anyone feels like commenting on, improving upon, or using my code