Reverse engineering Cordova apps

Cordova allows you to develop cross-platform mobile apps using web technologies. Traditional way of decompiling Android apps using tools like jadx wouldn’t give you much useful information when dealing with Cordova apps, since most of the logic and interface is implemented in HTML and Javascript.

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.

Extracting

Using apktool or jadx we can easily extract the web part of the source code. Cordova apps usually place them under resources/assets/www.

For the app I’m working on, simply opening index.html in a normal browser will lead to it running infinite loop in Javascript.

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
cd hello

Add browser and Android platform. Some plugins will fail to install if android platform wasn’t added:

cordova platform add browser
cordova platform add android

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

Quick Googling gave me this answer:

cordova plugin add cordova-plugin-device

Add Missing Plugins – a better way

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.

Errors

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."

I noticed in index.html there was this line:

<script type="text/javascript" src="cordova.93551f4e1f7af4ca1581.js"></script>

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.

In Cordova, most system API access require plugins. The app logic in Javascript would call respective plugins’ Javascript API, and in turn call the Java part of the plugin, then from there call system Java APIs.

So to answer the above questions, here’s the high level process that I usually take:

  1. Use jadx to look for Java code that calls interesting system APIs
  2. Note down the Java package name containing the code block of interest, for example: org.apache.cordova.file.FileUtils or com.rohithvaranasi.callnumber.CFCallNumber
  3. Google for these plugins’ documentation on their Javascript API. Using the above plugins as examples, I found:
    1. cordova-plugin-file : https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/
    2. CordovaCallNumberPlugin: https://github.com/rohfosho/CordovaCallNumberPlugin
  4. 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
  5. Go back to the app’s Javascript source code, grep for use of 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 .

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s