Reverse Engineering the Yik Yak Android App

Every once in awhile, I’ll  come across an app that implements some hardening techniques that make reversing a little more interesting. This was the case when I recently tried proxying the API requests for Yik Yak, a popular social media application exclusively available for mobile platforms that allows semi-anonymous user communication across a 5-mile radius (typically college areas).

Opening the app while performing a self-MitM attack effectively kills all API communication — typically, an indicator of SSL pinning.

After decompiling the APK and reviewing the Java source code, it was clear that the developers had also used an obfuscation tool to optimize/protect their build. Here’s an example method:

Note that the variables, classes, and methods have been renamed from their original, human-friendly forms. As I looked over more of the code, it also seemed like string constants were obfuscated — a feature found in third party tools like DexGuard. While obfuscators are generally a good practice for several reasons, they only marginally delay the reversing process by making the code harder to follow. In my experience, obfuscators also make Java decompilation less reliable, so I’ll mostly be working with smali (examples are in Java when available).

Next, I began grepping the smali source files for strings relating to common SSL pinning implementations. I quickly found what I thought would be the pinning check:

I bypassed the above method by editing it to immediately return void, but after building, signing, and installing the new APK, I had the same “Internet Connection” error as above. After trying a few different edits/builds with the same result, I began to suspect that Yik Yak was using some tamper detection logic (a package signature check) in an effort to prevent reverse engineering. I confirmed this by installing an unmodified, though resigned, APK that resulted in the same error.

In order to bypass the tamper detection, I changed focus and started searching for its decision point. In Android, developers can access the package’s signatures using the PackageManager class like this:

Since signatures are returned as instances of , I searched the source and found the following method:

It was pretty clear that this method was used as a wrapper to fetch the signatures of the current build. Note that on line 12, the value 64  correctly matches the constant value for PackageInfo.GET_SIGNATURES. Searching for usages of this class produced a few results:

Rather than attempt to workaround multiple decision points, I decided to spoof the package signature by altering the above method to return the signature of the official Yik Yak build. In order to do that, I needed to know the signature that the app was looking for. I briefly hunted through the code in the results above, but didn’t find the hard-coded signature (probably due to obfuscation). Instead of further searching (or debugging) the code, I ran a script that extracts the signature from a given APK:

After I had the expected signature, I patched the above smali method to return it:

Here’s that same code in Java:

Now that the package signature check had been bypassed, I installed the new build to test — unfortunately, I had the same error. Since this was likely due to some additional pinning code that I missed, I searched through the sources again and found this method:

Bypassing this method with return-void  finally disabled the pinning implementation, allowing me to successfully proxy the app’s API requests.

The infosec world is full of examples of companies poorly handling software security, but it’s certainly progress to see more efforts to improve such security by organizations like Yik Yak (at least as far as Android is concerned).

Share this: Facebooktwittergoogle_pluslinkedin