Tuesday, June 24, 2014

iOS: Back To The Future

UPDATE (September 17, 2014): Apple has addressed the "iOS: Back to the Future" vulnerability in iOS 8 and it has been identified with CVE-2014-4383.

Apple mobile devices based on the iOS platform, such as iPhones and iPads, implement multiple protection mechanisms and platform restrictions to fulfill several security requirements and support Apple's lucrative business model.

In early 2012 I found a vulnerability that allows the manipulation of a sensitive core default iOS capability, the iOS device update process. The iOS update process is protected by System Software Authorization, which prevents downgrading iOS devices to previous versions of this operating system. This measure can be partially circumvented by freezing the mobile device to its current iOS version.

An attacker in a Man-in-the-Middle (MitM) position (e.g. connected to the same public Wi-Fi hotspot as the victim, or by impersonating one of the legitimate Wi-Fi networks the iOS device wants to connect to)  can intercept the iOS update check traffic of a target device. Through the modification of HTTP requests and/or responses, specifically some dates in the headers, as well as implementing replay attacks, can force the target device to think its current version is the latest iOS version available.

The vulnerability can be used in carefully planned targeted attacks to temporarily or permanently freeze the current version of an iOS device. Before notifying the vulnerability to Apple (on February 6, 2014), the iOS version of Apple's devices could be permanently frozen to any time in the future, effectively setting its iOS version forever. In its current state, the version of iOS 7 devices can be permanently frozen up to the next update, while previous iOS versions still remain completely vulnerable. The temporary attacks still apply to all affected iOS versions.

Once the iOS version has been frozen, this attack facilitates the exploitation of other vulnerabilities potentially targeting a specific version of this mobile platform, such as the 197 vulnerabilities fixed in iOS 6.0, or the 80 vulnerabilities fixed in iOS 7.0 (plus all the others fixed between major iOS versions). It is scary to think how many potential victims could have been attacked by this vulnerability during the last two and a half years, allowing both massive device manipulation attacks as well as stealthier and targeted attacks (that can also be reverted back silently).

The design flaw affects the multiple Apple mobile devices (iPhone, iPad, iPad mini, iPod Touch..) since iOS version 5 up to the latest iOS 7 version (7.1.1). In iOS 5, Apple introduced new wireless capabilities to perform specific operations Over the Air (OTA), actions that previously required the usage of USB cables, such as iCloud backups, iTunes data synchronization and backups over Wi-Fi, or iOS software updates. This behavior introduced the aforementioned vulnerability, which can be exploited in iOS 5, 6 & 7 by applying core principles from movies like Back to the Future, Star Wars or Matrix ;)

Although the flaw was discovered in early 2012, it has remained private while researching and evaluating first hand the current immature and controverted vulnerability disclosure models, the real interests of modern vulnerability markets and brokers, as well as other vulnerability discovery implications, topics that have also been discussed during my talks.

I disclosed this vulnerability this year both at the 5th anniversary of the RootedCON 2014 conference (Madrid, Spain, March 2014) and at the 1st anniversary of the "new" Area 41 conference (Zurich, Switzerland, June 2014). More information about the vulnerability is available on both slide decks, as well as in the associated videos, with exploitation demos. They include the overall impact of the vulnerability, all the associated technical details surrounding System Software Authorization and how the iOS update process works, the vulnerability behavior in iOS 5, 6 and 7, and its history, limitations, and complementary tools used during the research process, such as iCamasu (new 0.42 version released):

NOTE: The video is currently available only in Spanish from RootedCON. The English version of the video (and presentation) from Area41 will be released in a few weeks. Follow @dinosec for updates.

Unfortunately, due to the fact the vulnerability has not been completely addressed by Apple yet, the iProxy tool and the archive of previous iOS software update plist files mentioned in the talks are not going to be publicly released. These two allow weaponizing its exploitation in real-world scenarios. However, it is crucial for organizations at this point to know about this vulnerability in order to take proactive countermeasures, such as verifying their managed iOS devices are running the latest, or expected, iOS version via their MDM solution.

My hope is that the vulnerability will be fixed in iOS 8 later this fall, but still several unanswered questions remain open: Why Apple didn't use HTTPS (and certificate pinning) for the iOS update check process? Was it due to performance reasons? Even in this case, it is crucial to differentiate between the update check process (to verify if there is a new version available) and getting the update contents, that is, the update process itself (to download and install the new available version).

We definitely do not learn from the past and repeat the same mistakes, again and again, regarding how to use technology in a secure way... Perhaps due to its increasing complexity or perhaps, wait... intentionally... Once again, the debate opens the door to reflect on the current technologies and the inherent weaknesses of our modern information society, sophisticated but vulnerable.

Wednesday, June 4, 2014


For the iOS updates security research I presented at both RootedCON and Area41 this year (more details will be published in an upcoming blog post... still waiting for a fix!), I processed and analyzed (several times and in multiple ways over the last 2.5 years) the PLIST files used by Apple devices to check for new iOS updates. Since iOS 5, and due to the new OTA (Over-the-Air) update capabilities introduced with that version, every time a new iOS update is available, a new file containing the list of official iOS versions and the mobile devices supported by each of them is published at http://mesu.apple.com/assets/com_apple_MobileAsset_SoftwareUpdate/
com_apple_MobileAsset_SoftwareUpdate.xml, together with the associated iOS documentation file, available at http://mesu.apple.com/assets/com_apple_MobileAsset_SoftwareUpdateDocumentation/

iCamasu, iOS com_apple_MobileAsset_SoftwareUpdate, is a Python-based tool that parses and extracts multiple details from Apple iOS software update PLIST files,"com_apple_MobileAsset_SoftwareUpdate.xml" (BTW, the tool does not parse the associated documentation files).

iCamasu provides multiple parsing options to select the input file (-f), extract the minimum (-m) and maximum (-M) iOS versions currently available, show a brief summary (-s or -S) including the SHA-1 hash for the file and its size, the number of assets or entries, devices, and iOS versions, and allows classifying the current iOS versions by device (-D) or iOS version (-I). Additionally it includes search capabilities by device (-d) or iOS version (-i), and a more verbose output and extended details via the "-v" and "-F" options.

iCamasu usage examples:

If you plan to do any iOS research related with new updates or iOS versions, I hope you find iCamasu useful to easily dig deeply into the PLIST file contents. As usual, the tool is available at DinoSec's Lab (where future major versions will be published too) and also in the new DinoSec GitHub repository, in case you want to contribute updates and feedback. The first public version is 0.41, as for the Area41 conference where it was released, and runs on Linux, OS X and Windows.

Thursday, February 20, 2014

DinoSec Challenge 0: Solution and Winners

This article provides details about the solution and winners of "DinoSec Challenge 0" (... and also explains how you can ruin a challenge trying to publish a nice blog post with images that fit on the web page ;)


The original goal of the challenge was to use the three images referenced by the "DinoSec Challenge 0", called "dinosec1.png", "dinosec2.jpg"and "dinosec3.jpg". However, due to the large size of some of these images, and in order to publish a nice looking blog post, I decided to use a reduced version of them for the challenge description, called "dinosec1_blog.png", "dinosec2_blog.jpg"and "dinosec3_blog.jpg", as you can see in the source code of the web page:

Google allows you to search for images by using terms (text) or 'Search By Image' capabilities, via URLs (pointing to image files) or by uploading local image files, both manually or using drag & drop. In the following video you can see how, depending on the web browser you are using, the Google Images search behavior varies. For example, when using Safari, the full URL of the image file pointed by the link (that is, the URL in the "<a href=…>" HTML tag, such as "http://.../dinosec1.png") is loaded into Google Images. As a result, Google cannot find any reference to any of the three images apart from the DinoSec challenge blog post (this was the expected behavior for this challenge). However, when using Chrome or Firefox, the reduced image used for the publication within the blog post (such as "dinosec1_blog.png", 320x212 pixels) is used instead. As a result, for images 1 and 3 Google is capable of finding direct references to the original images (in the case of the first one, even pointing to the original source, commons.wikimedia.org: 1, 2 & 3) and, therefore, helping to directly and easily solve the challenge:

As a result, I ended up trying to identify the reasons behind the described behavior. When creating that reduced version of the images for publication, I probably used derivatives of the original images, an obviously, none of the SHA1 hashes of the different files match. On the one hand, Google is capable of visually matching image 1 (in PNG format, 320x212 pixels) with the original source image 1 (in JPEG format, 4,288x2,848 pixels). However, image 2 is not found by Google. On the other hand, image 3 (in JPEG format, 320x212 pixels) is also matched with the original image 3 on a third-party website (same format but 4,288x2,848 pixels) and with another JPEG image of a different size (780x518 pixels) on another website. You can read some of the details regarding reverse image and photo search from multiple articles around the web, based on mathematical models, computer vision and machine learning technologies, combined with EXIF metadata and web pages context.

Although this was designed as an introductory challenge, the idea for it was not to be so easily solved, unless you were really lucky searching for dinosaur images through the web. Instead, it was designed to be solved by inspecting the raw images, finding and decoding a few artifacts added on purpose.

Images 2 and 3 ("dinosec2.jpg" and "dinosec3.jpg") are JPEG files with 4,288x2,848 pixels. If you look inside their metadata you can find a couple of messages.

The "IPTC-NAA data (IIM)" metadata section for image 2 contains a "RAW File Info" field with the following obfuscated message: "NTQ0OTUwMzEzYTIwNTc2ODZmMjA2NDY5NjQyMDYzNzI2NTYxNzQ2NTIwNzQ2ODY5NzMyMDYzNjg2
MTZjNmM2NTZlNjc2NTNmMjA0ZDcyMmUyZTJl". If it is decoded as base64 and that output is decoded again as ASCII hex, you get the first ASCII message: "TIP1: Who did create this challenge? Mr...". The image bellow shows the decoding process using Burp Decoder, but other tools or scripting languages can be used to obtain the same result:

The "IPTC-NAA data (IIM)" metadata section for image 3 contains a "RAW File Info" field with the following obfuscated message: "56456c514d6a6f67535851675a57356b63794231634342336158526f4948526f5a53423362334a6b49
434a7a5958567964584d6949446f744b513d3d". If it is decoded as ASCII hex and that output is decoded again as base64, reverting the decoding process for image 2, you get the second ASCII message: "TIP2: It ends up with the word "saurus" :-)". The image bellow shows the decoding process using Burp Decoder, but again, other tools or scripting languages can be used to obtain the same result:

Putting together the answer for both tips you can solve the challenge: Silessaurus. Yes, indeed, it is my oldest ancestor I'm aware of :)

Image 1 ("dinosec1.png") is a JPEG file with 800x531 pixels, that still contains a hidden message. Although the message is not required to solve the challenge, I'm not going to disclose how to obtain it, so that the inquisitive reader can still play around with it :) (tip: stego)


This challenge winners are Juan Manuel Fernández (@TheXC3LL), with a very fast and correct answer using search engines, and @neosysforensics, with a correct technical answer based on decoding the image files metadata. Based on the details and epic fail previously explained, and although initially I thought on having a single winner, I decided it was fair this time to select two winners, one for the first correct answer (even when using the easy path :-), and a second one for the first technical answer. The winners books are on its way, "Apply Security Visualization" and "File System Forensic Analysis", both related somehow to the techniques used to solve the challenge.

Honorable mentions go to other participants like Ricardo, José Manuel, Román, Daniel, and David, that also provided a valid answer by using Google, TinEye (reverse image search engine), or technical analysis using base64 and Python. Thanks for all your submissions!

Lessons Learned

Designing a challenge is always tough, specially finding the right balance between difficulty and affordability. Even for introductory challenges, never underestimate the minor details, manage them as more advanced and complex challenges, and always give a much higher priority to the challenge than to its publication :-) Seriously, in order to solve this first challenge speed of submission was a key factor, especially if you followed the easy path. Thus, in this case the "luck" of been aware of the existence of the challenge influenced a fast and timely response. Therefore, future challenges will be published in advance, with a well known deadline, and all submissions will be evaluated based on their quality, accuracy, creativity, and technical contents.

Besides that, prizes will be announced in advance too, so that you can evaluate your participation based on them. Quite honestly, if you participate because of the prizes and not the enjoyable learning experience, I'm sure you will find wealthier challenges and CtFs out there... although I cannot think of an easiest way of winning a security book than dragging & dropping an image into Google :-D

Follow the @dinosec Twitter account and this blog... and get ready for the next challenge!!

Monday, February 10, 2014

DinoSec Challenge 0: What is the name of this dinosaur?

At the end of last year, during the CCN-CERT conference, I challenged the audience when I reached my speaker bio slide. There, I showed "my picture" and how I "look like" nowadays as a member of DinoSec :-) The question was: "What is the name of this dinosaur?". Nobody answered it...

Throughout my professional career I've really learned a whole lot and enjoyed both participating and creating security challenges. Thus, I would like to start posting again security challenges from time to time using the DinoSec blog. As I don't like unanswered questions to last forever, this is the first introductory challenge where you need to use your investigative, exploratory, and digital paleontologist skills to be able to get the generic name of this dinosaur. To help with its identification, I have provided you three pictures, so that you can see the dinosaur physiognomy and details:

I will hand over prizes for the winner(s) of these challenges, like information security books or other gadgets. In this case, the challenge does not have a deadline. It will be open until someone answers the question and submits the right generic name for this dinosaur. Please, send your submissions to info @AT@ dinosec .dot. com, with the title "DinoSec Challenge 0", and briefly describing in a couple of paragraph how you "guessed" the dinosaur name.

Suggestion if you have kids: If I were you (as Josh Wright educated me sometime ago) I would teach them to start counting at zero! They will express gratitude for it forever :-) Now, you know why this is challenge number zero :-)

Monday, December 9, 2013

Removing the Android Device Lock from any Mobile App

Shameless plug: I will be teaching the 6-day SANS SEC575 training, "SEC575: Mobile Device Security and Ethical Hacking", in AbuDhabi, UAE (Apr 26, 2014 - May 1, 2014) and Berlin,Germany (Jun 16-21, 2014).

The "SANS SEC575: Mobile Device Security and Ethical Hacking" training is one of the most entertaining and challenging courses I have ever taught, with enhanced coverage of Android, iOS, Windows Phone, and BlackBerry. The last couple of times I run it at the end of this year I travelled around the world with six different mobile devices, including Android 2.x & 4.x plus iOS 4.x, 5.x, 6.x & 7.x, my other production mobile devices, two laptops, Wi-Fi access points plus multiple USB cards and antennas, a Pineapple, a portable stand camera and a few other gadgets... This makes crossing airport security quite challenging too, a kind of extra social engineering exercise for a pen-tester . Yes, I get stares. :-)

Last week, a new Android vulnerability was disclosed: "CVE-2013-6271: Remove DeviceLocks from Android Phone". It affects Android Jelly Bean (JB) 4.3 devices, as well as earlier version based on my own testing, such as Android Ice Cream Sandwich (ICS) version 4.0.3. The flaw allows any mobile application (from now on referred to as an "app") to remove the passcode or lock protection of Android mobile devices, no matter the lock mechanism in place: PIN code, password or passphrase, dot pattern or gesture, or face unlock. That's pretty huge.
Android implements an Inter Process Communication (IPC) mechanism through messages, called Intents. About a year ago, we started covering in Day 3 of the SEC575 class Android Intents analysis via the Mercury framework,  developed by MWR InfoSecurity. You can read all about Mercury in a Chris Crowley's previous article on the SANS Pen-Testing blog, "Intentional Evil: A PenTester's Overview of Android Intents". The SEC575 training has been recently updated with its replacement tool, called Drozer. As the Drozer framework is explicitly mentioned in the PoC section of the CVE-2013-6271 vulnerability, I thought this vulnerability was a great opportunity to show on this blog how to dissect an Android app, and offer a quick step-by-step overview of the methods and tools we can use as pen-testers and security researchers to discover and analyze, in depth, this kind of still very common Android app weakness.
A more detailed analysis of the various Android app components (Activities, Services, Receivers, etc.) and their relationships, app attack opportunities, and components exposure are covered in Day 3 of SEC575, including live demos, hands-on exercises and details of real vulnerabilities, such as a similar vulnerability affecting the AndroidFacebook app, v.1.8.1 (I was not aware of my artistic skills after Björn took a picture of my screen during SANS London 2013 after going through the vulnerability details :-):
The attack vector that can be leveraged to take advantage of the CVE-2013-6271 vulnerability is based on having an offending app installed on the victim mobile device, previously installed by the user or installed by exploiting any other vulnerability in the Android platform. In order to send an intent to a public Activity, the offending app does not require any special permission in the Android platform. This increases the device exposure, as the most benign looking apps, or even future app updates, could be used now to unlock the Android device (even those apps requesting no permissions at all; BTW, these are the ones really suspicious to me :-)
The SEC575 Android static analysis section mainly focuses in the evaluation of third-party mobile apps from a corporate perspective, such as the ones you can get from Google Play (the official Android app store) or any other source or third-party store. When you need to analyze a default system Android app, such as the Settings app in the case of the CVE-2013-6271 vulnerability, there are a couple of differences that influence the analysis process.
NOTE: The analysis process described uses Windows 7 as the host operating system and the Android emulator as the target mobile environment, although the same steps apply when using a real Android mobile device or a different host operating system.
Android App Static Analysis
In order to analyze any Android app, the first requirement is to get a copy of the corresponding Android package (.apk file) from Google Play or from within an Android device. An Android package is a compressed ZIP file, so it can be easily inspected. Inside you can find resources and certificates information, as well as the two most relevant files for Android apps: AndroidManifest.xml (which includes the permissions required by the app and the components publicly exported by it, among others), and classes.dex (the app binary in Dalvik EXecutable , or DEX, format):
However, the default system Android apps are optimized to speed up their performance when loading and running, and as a result, the corresponding .apk file does not contain a classes.dex file. Instead, the binary has been extracted out of the .apk file and has been converted to an .odex file (Optimized DEX file).
The CVE-2013-6271 vulnerability affects the default system Settings app (identified as "com.android.settings"). The Settings app is located in the "/system/app/" directory of Android devices, split in two files: Settings.apk and Settings.odex. The adb tool available in the Android SDK can be used to extract these two files:

As the .apk file does not contain the app binary, our analysis will focus on the .odex file. The .odex file has to be deoptimized and disassembled for inspection, a process known as deodexing. The baksmali tool helps to deodex the file and requires four arguments; the Android API level (-a), the target .odex file (-x), a directory containing all the framework libraries (-d), and an output directory to save the disassembled Smali code from the app (-o).
C:\> baksmali -a 18 -x Settings.odex -d framework -o Settings
The API level is based on the Android version and can be easily obtained from the Android  "Codenames, Tags, and Build Numbers" webpage. As we are using an Android 4.3 target device, the corresponding API level is 18.

The directory containing all the framework libraries can be created by checking the value of the BOOTCLASSPATH environment variable from the Android 4.3 device. Again, adb can be used to retrieve its value:

You can copy and paste the BOOTCLASSPATH variable contents in a single line into a text file ("BOOTCLASSPATH-jar.txt") and process that file in Windows to obtain (via adb pull) all the Android framework libraries from the device, plus the associated .odex files. The following commands will streamline the process (see the "Additional Resources" section below to get the "BOOTCLASSPATH.bat" script):
C:\> set /p BCPJAR= < BOOTCLASSPATH-jar.txt
C:\> echo %BCPJAR:.jar=.odex% > BOOTCLASSPATH-odex.txt
C:\> set /p BCPODEX= < BOOTCLASSPATH-odex.txt
C:\> echo %BCPJAR% && echo %BCPODEX%
C:\> FOR %a in (%BCPJAR::= %) do @echo %a >> BOOTCLASSPATH-jar-lines.txt
C:\> FOR %a in (%BCPODEX::= %) do @echo %a >> BOOTCLASSPATH-odex-lines.txt
C:\> mkdir framework
C:\> cd framework
C:\> FOR /F %i in (..\BOOTCLASSPATH-jar-lines.txt) DO adb pull %i
C:\> FOR /F %i in (..\BOOTCLASSPATH-odex-lines.txt) DO adb pull %i
The "framework" directory can now be used as the input for the baksmali "-d" argument.
After running the baksmali command, a new "Settings" directory will be created containing the Settings app Smali code. The smali tool can be used then to reassemble the Smali code into a Dalvik EXecutable file (.dex file). The tool simply requires two arguments, the previously created "Settings" directory and the output DEX filename (-o):
C:\> smali Settings -o Settings.dex
As a result, a new "Settings.dex" file will be created containing a deoptimized binary version of the Settings app. This file would be similar to the "classes.dex" file available in the APK file for third-party apps. At this point, the dex2jar tool can be run on this DEX file to decompile the Dalvik EXecutable and extract the corresponding Java bytecode (.class files):
C:\> dex2jar Settings.dex
The dex2jar tool will create a new "Settings_dex2jar.jar" file that contains the Java bytecode for the Settings app. Through a Java decompiler, such as JD-GUI, it is possible to open this .jar file and obtain the Java source code for the target app, or an approximate representation of it.
Android App Dynamic Analysis
The Drozer framework provides advanced capabilities to interact with Android apps and their different components. After installing the Drozer agent in the target Android device, which will act as the offensive app, it is possible to establish a communication between the Drozer  console and the agent. From the Drozer console, all the packages associated with the "settings" term can be listed, trying to identify the target Android Settings app ("com.android.settings"):

Drozer provides multiple modules to perform a deeper inspection on the components exposed by the Settings app, and in particular, the potentially vulnerable Activity from the total 104 Activities exported by the app, named "com.android.settings.ChooseLockGeneric":
At this point, the JD-GUI decompiler can be used to open the Settings app Java bytecode (.jar file) and inspect the specific class we are interested in, via the CVE-2013-6271 vulnerability details and the Activity name previously identified,  "com.android.settings.ChooseLockGeneric". By inspecting this class source code, we can see how at the Activity creation time (inside the "onCreate()" function) the "confirm_credentials" extra boolean parameter, is extracted and evaluated from the Intent, trying to determine if a confirmation is required from the user:

Additionally, an extra "lockscreen. password_type" integer parameter is expected from the Intent associated to the Activity used to update the lock preferences:

The app will call then the "updateUnlockMethodAndFinish()" function that contains the final vulnerable code if the value of the previously mentioned parameter is equal to 0 (after going through the "upgradeQuality()" function and the associated code):

After inspecting the source code, it is possible to identify the two extra parameters required by the "com.android.settings.ChooseLockGeneric" Activity to be able to execute the vulnerable code. The Drozer frameworks facilitates the creation of a new Activity and the submission of the Intent with these two extra parameters against the target component:

If the target Android 4.3 device is protected with a passcode (e.g. PIN code), after sending the Intent with the appropriate extra parameters from the Drozer agent to the target Settings app, the vulnerable code previously mentioned will run and the lock protection will be immediately removed from the device as shown below:

When the lock is removed, it's quite startling to see the open device. The combination of both static and dynamic analysis techniques have allowed to identify the vulnerable code and to exploit it to remove the lock protection from the Android device.

Countermeasures Implemented in Android 4.4

When the same analysis is performed in Android 4.4, and Drozer is used to exploit the vulnerability, the behavior observed is the expected one for a non-vulnerable device. Before the user or an app can change or remove the lock or passcode protection, the mobile device prompts the user for confirmation by requesting the previous lock value (e.g. the user has to enter the previous PIN code):
An in depth analysis of the new Settings app in Android 4.4 reveals how the vulnerability was fixed in the latest Android version. The default system Settings app in Android 4.4 is stored in a different location, "/system/priv-app/", the new default location for Privileged Apps (instead of the old default location for all System Apps in previous Android versions, "/system/app"):

The new APK location can be obtained, for example, through the package inspection capabilities available in the Drozer framework, that provide extensive information about any app:

The Settings.odex file can be inspected in-depth following the same analysis process previously described for Android 4.3. The main difference is the extended set of libraries used by the default Android 4.4 framework, as the BOOTCLASSPATH value denotes:

As a result, the following three main differences help to fix the vulnerability and make Android 4.4 not vulnerable to the same attack. The source code of the "com.android.settings.ChooseLockGeneric" class includes a new "InternalActivity" subclass at the bottom of the source code:

A quick comparison of the "ChooseLockGeneric" class source code between Android 4.4 and Android 4.3 exposes the new code introduced in version 4.4. The "onCreate()" function now verifies that the Activity is an instance of the new "InternalActivity" class, to limit its creation from other external apps:

Finally, the AndroidManifest.xml file for the Settings app has been changed from Android 4.3 to Android 4.4 in order not to publicly export the new "InternalActivity" Activity. This XML file is in binary format, so the AXMLPrinter2 tool can be used to convert it to text for in-depth inspection:
C:\> AXMLPrinter2 AndroidManifest.xml > AndroidManifest.txt
Again, the combination of both static and dynamic analysis techniques have allowed to confirm that Android 4.4 is not vulnerable and identify the fixes introduced in the new code to ask for confirmation before removing the lock protection from the Android device.

Tool References
AXMLPRinter2: http://code.google.com/p/android4me/
dex2jar: https://code.google.com/p/dex2jar/
Drozer: https://labs.mwrinfosecurity.com/tools/drozer/
JD-GUI: http://jd.benow.ca/#jd-gui
smali/baksmali: https://bitbucket.org/JesusFreke/smali/

NOTE: The different tool commands used during the analysis process are Windows batch scripts that simply invoke the corresponding Java tool, such as baksmali, executing in reality the "java -jar baksmali-2.0.2.jar %*" command.

Additional Resources
BOOTCLASSPATH.bat: Windows batch script that creates a 'framework' directory with all the Android framework libraries (both .jar & .odex files) specified in the local "BOOTCLASSPATH-jar.txt" file, extracted via "adb pull" from a local Android device or Android emulator (AVD).
BOOTCLASSPATH-jar_4.3.txt: Default Android 4.3 framework libraries.
BOOTCLASSPATH-jar_4.4.txt: Default Android 4.4 framework libraries. 
This article has been cross-posted in the SANS Pen-Testing blog.