Amazon Echo or Google Home. Perhaps this development has been enough to push people from privacy cynicism toward what media scholar Ian Bogost, writing in the Atlantic, has described as full-blown “privacy nihilism,” which presumes an omnipresent regime of surveillance that we can no longer resist and may as well not bother to try. He points to experiences of what we might call the data uncanny — “someone shouts down the aisle to a companion to pick up some Red Bull; on the ride home, Instagram serves a sponsored post for the beverage” or “two friends are talking about recent trips to Japan, and soon after one gets hawked cheap flights there” — that have led users to erroneously conclude that their phones are listening in on their conversations.
As Bogost observes, this is not yet technically feasible, but the fact that this belief persists is itself revealing. Having surrounded ourselves with cameras, microphones, and a panoply of sensors, we now find ourselves enclosed in our own personal panopticon. It doesn’t matter whether anyone is actually watching or listening as long as we can’t be sure that they aren’t. Once the apparatus of surveillance is considered a fait accompli, then some measure of cynicism, apathy, or nihilism may present itself as the only reasonable response.
In theory web apps should be much easier to reverse engineer because there’s technically no “compiling" process, more information is preserved from the original source code. Unless the developer uses an obfuscater, the original program symbols (function names, variable names, etc) are preserved in the final app package. And, because they’re just web technologies, we should be able to just debug them using modern browsers’ amazing debugging tools.
In practice, we need a way to extract the web app part out before we can do anything with it. This doesn’t seem to be a common operation so google doesn’t give you a straight answer, but now I’ve figured it out and find it quite easy.
Note that I have no experience in Android app development, nor Cordova, so there might be more straightforward ways to do things that I don’t know. But so far these methods have served my needs well.
Using apktool or jadx we can easily extract the web part of the source code. Cordova apps usually place them under resources/assets/www.
Running in Browser
To make the app run under normal browser, I took idea from Cordova’s app development tutorial.
First create an empty app project:
cordova create hello com.example.hello HelloWorld
Add browser and Android platform. Some plugins will fail to install if android platform wasn’t added:
Copy the extracted source files from the app over:
cp -r ~/apk/targetapp/resources/assets/www .
Run in browser:
cordova run browser
This should allow the app to at least start initializing, though if the app uses any Cordova plugins that we haven’t installed yet there will be an error and the initialization would fail. Next step would be to install missing plugins.
Add Missing Plugins
In this step, we need to look at the error messages from the browser console to see what plugins are missing. Below is my example, but each app will use different plugins so the process will vary.
Error: Uncaught ReferenceError: device is not defined
I noticed www/plugins/ contains all plugin files, and the directory names are conveniently the name of the plugin. So I can just use xargs to install all of them:
ls www/plugins/ | xargs cordova plugin add
This way all plugins included in the app are installed.
Remote Debugging with Chrome
If you connect the phone running the app to you computer and enable Android’s USB debugging, you can use Chrome’s built-in inspector at chrome://inspect to remote debug the app. This only works for apps that declares themselves to be “debuggable" in AndroidManifest.xml. However, if the app is not debuggable, you can still use this Xposed module to make the WebView debuggable without needing to modify the app.
If an app fails to load in browser, check browser console for error messages. This section notes all error messages I’ve encountered and the solutions.
“Could not find cordova.js script tag. Plugin loading may fail."
And in www/ both cordova.xxx.js and cordova.js exist.
So I simply changed the src in index.html to cordova.js and the app loaded successfully.
Analyzing API Usage
One important part of security auditing apps is to see what system APIs it accesses, under what condition, and what it does with the obtained data.
So to answer the above questions, here’s the high level process that I usually take:
Use jadx to look for Java code that calls interesting system APIs
Note down the Java package name containing the code block of interest, for example: org.apache.cordova.file.FileUtils or com.rohithvaranasi.callnumber.CFCallNumber
Read their documentation and look for the global object name encapsulating the plugin’s functions, or the function names of interest. For example, CordovaCallNumberPlugin offers only one function here: window.plugins.CallNumber.callNumber
TODO: Tweak CORS
If the app wants to send any HTTP request to external servers (other than localhost, most likely due to the app calling API servers), in the browser it will fail from CORS requirements.
I didn’t investigate to fix this because I didn’t need to inspect the server response. But this should be fixable by tweaking the CORS header sent by cordova run browser .