Hello once again everyone and welcome to the 5th chapter of my blog post chain about reverse engineering and Supercell.
Lot of news and cool stuffs happened since my last post and… I’m getting excited just by thinking the word to use to write this blog post.
During the last week I got invited from Supercell, in Finland, to speak at Disobey about all of the things posted in the blog chain and generally about reverse engineering on Android and mobile games.
Everything was quite above the expectation, starting from the awesomness I saw at Supercell HQ, the guys I spoke with and later my talk at Disobey as well.
First… I think I’m going to start bother him with all of these thanks, but… Thanks again to -A, at first, but also to -J, the Disobey owner -B, and the orgazination which made all of this possible. I went over there with 3 good friends which I’m training to work with me and they can say as well that what we saw and lived was something really magic.
We are really proud to what we took at Disobey, giving an overall understanding of my methodologies and a first class on Android Reverse Engineering. We also can’t wait to see our face when we started the demo and frida was somehow crashed in background. I felt really nervous and shy at the beginning but once I get in the flow I did just spoke about what I do and what I know… good challenge won!
Some guys over there made us heavy congratulations for what they saw also appreciating the fact that doing 40 minutes of live demo and speaking with memory is hard even if this is not your first talk in front of so much people.
I’ve met A LOT of awesome people during this journey and I’m taking this as a begin to something new and cool that I’m sure will come in the near future.
According to Supercell, another guy from somewhere around the world managed to break the commercial LLVM based protection which is now living in all the games. Permission given, I’m going to post the solution of the Clash of Clans challenge, which is mostly what i showcased at Disobey.
- Well known commercial LLVM protection (arxan 99,99999999%) has been added to Clash Royale and Clash of Clans
- Frida detection (specially for me)
- Clash of Clans encryption change
Making theories as usual is the first step of reverse engineering which later we need to validate. Validated theories usually result in 2 things: 1, the solution of the challenge, 2, thousand of questions and theories more.
The first approach was step debugging high level functions to understand if some sort of math operation was done before encryption.
As you can see from this lovely christmas tree (first block of encryption full procedure – not the unique), it was a pretty bad idea since:
- you can’t have a proper understanding of the program flow. The obfuscation make very hard to understand it with hundred of conditional jumps which basically turn frida not really useful for this context.
- even if I kept debugging it with frida, probably I would reach it in any case, or maybe not, in any case one of our first task is to make our life simple, no joke… more then 150 offset under frida interceptor. I left just some in the code to remind my self all the effort I put into this and maybe to go for some other better way in a similar scenario.
- doing things in runtime is awesome but sometimes you just need a break. There are a lot of tricky way to break the code with frida.. never tried once but I would guess that writing a BKP instruction on the next address and save in memory the replaced instruction will make the job, but also there are some other way probably at lower level?
Even if strings encryption looks pretty solid, didn’t dig so much into it but looks a xor and should happens at some point before jni_OnLoad (so, during loading time), all of them are visible in memory and pretty easy to dump using a common hex editor as well.
Killing frida detection with frida
Understanding where was the frida detection was pretty easy as well if you think (know) at how frida works. Initial theories pointed me to a check through the socket or a memory scan (where and how? pretty hard to develop in any case) to detect frida gadgets.
The pretty easy patch come with frida itself and just consists in replace the register R0 to something like 0xFF before the attempt of the client to connect frida socket for the further check. Attaching to the plt “socket” from libc also highlighted that the client was attempting to connect to it.
Frida + Unicorn = Hard Pwn
Yeah… and this applies for any context and any possible scenario as both frida and unicorn runs on multiple arch and os’s.
I don’t personally know either, why I spent time into this (mostly because of fun, challenge and love for learning new stuffs) and why i used that fancy (functional) approach.
What was the successful idea was to build a debugging environment to properly understand the procedure flow, I like to call it a timeless environment since everything was developed in order to cycle into the same function with the same memory layouts.
For this purpose, frida was very helpful at the beginning. A simple interceptor on login encryption entry point (after jumping through arxan memory CRC with a sort of bruteforce on memclr call to understand the right moment to detach, skip the crc and and re-attach).
Once the hook was hit, I’ve coded it to dump all the memory layouts involved or not involved including stackpointer (obviously allocated by the game) and log relevant addresses and registers.
The unicorn journey
Here I’m probably going to highlight my lack of knowledge about unicorn and so, someone would probably have better ways for doing the same thing with less steps, but since this was my first approach to it (I won’t consider the ones i had before which consists in just emulating simple asm functions and setup a couple of shits).
#Side-Note: all of this was also possible thanks to my understanding of Supercell library before obfuscations and protections. An important “key” in all of this was understanding through memory copy and memory clear patterns that we were still talking about sodium and whatever was modified was deep in the library or once again some sort of maths on keys/nonce/payloads. This is not a special skill, it’s using the brain.
- Reaching the end of the encryption was the first sub-challenge. Unicorn, by default, is giving you just the context to work with (which is awesome) and doesn’t pre-load any kernel or libcutils or nothing. A lot of NOP was required in order to make it works, for instance on all memory copy and clear at first or some stack checkguard all-around.
Your next question after looking at the scripts will be: Why you didn’t patched 3 instructions later in order to have 1 patch only instead of 50?
-> Was cool to have a better understanding of the flow and was really helpful later to compare with the Clash Royale emulator clone i built to have a better understanding of the change.
- Once the end of encryption has been reached and I saw the same result of the real client, it was already a partial win. It required a bit of more effort also due to my stupidity. I did totally forget about strings encryption. Salsa xor is actually using the sigma, which is an hardcoded string, and due to this I was having different results between client and emulator (which is not decrypting the strings as we are just emulating encryptions blocks – d’oh. so much time on this). Once figured this out (some more work to frida to dump the memory area with unencrypted content), what followed was an hard analysis through all the instructions, which was pretty hard also due to the amount of obfuscations code but still do-able since the flow was linear.
- Going backward to understand what changed wasn’t yet enough. I mean… it was, but I wasn’t really intended to spend 3 weeks on static analysis, so the worth move was spend 4/5 hours to build another emulator for Clash Royale, with another frida script to dump relevant memory layouts and emulator.
- Not happy, to simplify even more my work and gain more time was good to tweak more the Clash of Clans emulator and feed it with Clash Royale payload, keys and nonce.
- What follow than was at first, understand the right spot to begin tracing instruction by instruction and possible interrupt the emulation as any run of the emulation was barely taking 7 minutes on my environment (mostly because of all the debugging code), and later inspect the stackpointer of both the emulator. The relevant spot has been found after the chain of memcpy and right before the 3 memclear which follow scalarmult. This highlighted even more that the change was made inside hsalsa/salsa functions.
- A step I named ‘exploit everything you have’ during my talk at Disobey was the next move. Exploit, take advantage of, even if it could sounds really bad and noob (just… who the f**ks care). I took node and python sodium libraries and full-fit them of console.log and print to check any single math operations which was pretty enough to understand that what was touched was the number of rounds.
When I ran the proxy and I saw it working for the first time I screamed so hard… also because 4/5 of the talk i had prepared was just gone.
I really enjoyed follow that debugging flow and I believe that something more abstract would be helpful in similar context. So that, me and my colleague, are creating an unicorn based debugger with runtime functionalities similar to gdb. Project is opensourced here. We still didn’t test a real usage case also because it’s something pretty new and we were really busy preparing the demo for Disobey. We will keep it up and remove the WIP very soon!
Conclusion and POC
So and so, this is a semi-detailed list of the reverse…
I’m so fucking proud of myself for all of this and thanks to this adventure in Finland I learnt something really important… that I know a shit and I have a lot to learn from others. I’m mostly sure that I’m going to push me into deep learning during the 2018 and do a lot of other good stuffs to showcase. For sure, I’m going to bring my girlfriend this summer to Helsinki to let her see with her eyes all the awesomeness I saw and all the wizards I met at Supercell HQ, in the hope they will still be ok to take a coffee with us!
To TL;DR, we just can’t wait to learn more stuff to discuss and showcase.
I still invite everyone interested in the topic to visit and meet us in our Discord, we always appreciate people that want to share their knowledge, as we love to do so!
I was really sad about hooking recv and send. Touch from input manager was bother a lot so… why the damn we don’t just hook getaddrinfo but most… why I didn’t think this before :'((((. Also, new little trick to make it works properly on a middle-box. Writing secret key into public key memory address does the job.
GG. Thanks, Supercell. Thanks -A, -J, -B and -M which didn’t steal anything from my phone that i forget at SC + his guys at the team and all the people which we met!
Waiting the next move! :)) stay sure that I’m gonna try whatever if this is going to take me there once again for another coffee with you!
Some pics from our journey!
I love your write ups, can I ask what kernel your referring to that you used in Android? Also are you still active