Reverse engineering a fraudulent app: How we spotted the most sophisticated form of mobile fraud yet
Posted Dec 10, 2017
Last week on the blog, we walked through the reasons for Google’s new Play Referrer API. The API will provide additional data that gives us what we need to fight click injections, and we’re thrilled about that.
We dug a little deeper and conducted an investigation into an app that we suspected was bypassing the default method of click injections. We hypothesized that the app in question was sniffing out the Google Play Store downloads ‘repository’ (called the ‘Content Provider’ in Android terminology) to run clicks in the background even before the app finishes its installation.
This is a new approach to click injections. In the past, a more straightforward approach was to listen for any newly installed apps, wait for a new app to be installed, and then run clicks. It was the most straightforward because Android provided an out-of-the-box way for an app to know if a new app was installed in the system (through the PACKAGE_ADDED broadcast). This way had a lot of flaws, mainly that the timestamp between a completed install and the beginning of the download was mismatched, which made it a very easy type of fraud to detect.
In this article, we analyze how a fraudulent app listened for newly-installed downloads before the app completed its installation. Until now, this has been a more effective method of committing mobile ad fraud, as detecting timestamp differences was not possible, since the difference would be minuscule.
Environment and Methodology
The methods we used for this experiment were:
- Static code analysis with two different decompilers
- The attachment of an active debugger during interaction with the Google Play Store
The following scenarios were tested on an unrooted OnePlus One device. I used two decompilers to verify results and findings. For privacy reasons, we will not disclose the app’s name. Hereafter, we will call it AppZ. One noteworthy fact we can share is that AppZ currently has over 500 million downloads.
Below is my attempt to make assumptions based on what I found. The codebase is over 100 classes long (which is considered to be very, very long) and the de-obfuscator could not extract most method names. Because the codebase is unreadable, these findings are not concrete and the assumptions I make below are assumptions. Please keep that in mind as you read on.
After running a traffic analyzer, it appears that calls to multiple APIs fire immediately after a package installs successfully. This means that the app is making some connections under the table with an unknown server without informing the user at all. The logic for AppZ is also selective: some apps would fire to different networks. Below is a screenshot from a Charles Proxy that shows the sequence of calls after a successful install for Subway Surfers, followed by one for the gaming app Gems & Genies:
Access to Google Play's Content Providers
When the user installs a new app, the Google Play Store places the install data in what's called a Content Provider. A Content Provider can be thought of as a single-table SQLite database.
The URI for the Content Provider that the Google Play Store uses is content://downloads/my_downloads/. . Our assumption is that AppZ observes this Content Provider to get information from recently installed apps from the Google Play Store. Here's a screenshot from AppZ’s decompiled source code, which proves that AppZ has clear knowledge of the Google Play Store Content Provider:
It would require a constant background service, which AppZ has running at all times on the user’s device in the form of a notification, to be able to listen to the Google Play Store Content Provider all the time.
To repeat, a Content Provider is basically a wrapper for a single-table SQLite database. Google Play’s Content Provider for downloads is 'content://downloads/my_downloads', which is the Content Provider that Google Play Store uses to store any downloaded data right after the user presses the download button.
The mentioned observer that AppZ utilizes can be seen in the following screenshot:
Here, registerContentObserver() is used to listen on any changes to a content provider and invoke a callback.
But what does AppZ actually do with the data it observes from Google Play Store Content Provider?
From the following screenshot, we can see that AppZ implements a parsing logic that extracts the name of all recently downloaded apps. It can be seen in line 86 of the following screenshot.
To summarise, it’s clear that AppZ has a sophisticated logic to observe and query information from recently downloaded apps. This knowledge gives it the ability to launch click injections before the app has a chance to fully download.
Fraudsters often come up with new approaches to committing ad fraud. From what we observed, it’s very clear that AppZ has found a way to conduct malicious click injections using a weak aspect of the user’s device. The above findings suggest that not only is such an idea possible, but is probably already in practice by many apps like AppZ.
The concept of running advertisement clicks from a legitimate environment without the user’s consent has seen many implementations in the past. The above methods we discovered are sophisticated. However, the good news is that Google’s new Referrer API should set the bar higher for click injection schemes. For more info about click injections and mobile ad fraud, please check out this piece by Andreas Naumann, Adjust’s fraud expert. And for more on ad fraud in general, our mobile fraud guide is packed full of insights to help you understand where it comes from and how you can fight it.