Well, I'm Vietnamese, but I'm writing this post in English because it's pretty deep in tech/reverse engineering and I think who have enough tech experience to read this would also have decent English skill, mine isn't great though, but hope that most of you could understand the points.

So because of a private project, I need to gather some of Reddit's API. I planned myself 3 options:

  1. Web app's API (unofficial): Easy to capture, easy to replicate, probably quite large rate limit if there is, but most of the time I'll have to deal with HTML data & cookies for session handling. Boring and not so convenient. I haven't even looked into it.
  2. Developer API (official): Easy to use, fixed rate limit of 60 requests/minute, beautiful JSON data, likely being banned if you use it for spamming. I slightly looked into this, but didn't clearly understand the authorization flow.
  3. Mobile API (unofficial): Hard to research & replicate, probably quite large rate limit if there is, beautiful JSON data, should be hard being banned since most of users couldn't touch those API. Most of the time researching, I see that mobile API have more advantages & less limitations than the others.

Because I'm already had some experiences with reverse engineering mobile API and wanted something challenging, I chose the 3rd way.

First, I got a latest working Reddit apk version from Downapk, and opened it using jadx-gui

Meanwhile I also setup burpsuite SSL pinning on my Nox player to see how Reddit apk working underneath. This is a request sample I got from the register function:

After some researches, I realized that some API function need to have the header X-hmac-signed-body and X-hmac-signed-result

So I went back to the jadx window opened ealier, after digging on the apk source code for a while I found the request builder class, which have the function calls to set above headers. Also it have a KeyUtil class which called the decryptSigningKey function.

So I opened the KeyUtil class to see how they decrypted the key

Well, they're loading a native library, but I haven't got the skill to RE native library. So I couldn't really tell what's happening under native code level.

But luckily, they're decrypting the signing key, which prevent users to get the key directly from the decompiled source code. But I havent a bit of smali patching skill which would allow me to convert the decrypted signing key to base64 and then log them out.

So I used apkstudio to decompile the source code onto smali, find the corresponding class and patched them like this (blocks that I added are between those added block <x>, end of added block <x> comments.

After that I built & signed the patched version and install it on my Nox player.

It worked like a charm. And here I the result I have when testing the login function and grab the log with adb logcat | grep "T-Rekt"

So now I have the decrypted signing key in base64, it's broken onto 2 lines, here it the key I got after assembling and base64 decoded:

8c7abaa5f905f70400c81bf3a1a101e75f7210104b1991f0cd5240aa80c4d99d

Because I got both the encryption key, the raw and signed data, I could easily verify to see if it's the right one. So I wrote this small script on RunKit:

So "Bingo" means yes and "Oh no :(" means no. And the result is....

After further researching I realized that some API requires Basic authorization header with their fixed client id and client secret, some requires signatures above, some requires Bearer authentication with users's access_token. It's quite long and hard to explain in a single blog post. So I went to write this quick implementation, which includes the authentication flow (login, authorization, getting access_token,...), register, send and reply messages.

Here it is: https://github.com/t-rekttt/reddit_unofficial

I'll add further explanation & development if there is enough interest.

Thanks for reading.