Analyzing Multiple APKs At Once

This falls into that series of things where I had to make something work when there wasn’t a pre-built package, so I’m documenting it here in case (1) I ever need to do this again, or (2) someone else can benefit from it.  Let’s say you’re looking into a device that runs on Android, and it has a bunch of APKs that you have no clue what to do with… why not use some common tools to quickly process all of those files?

The Disclaimers

Usual disclaimers apply here… in this case I was doing everything on a fully patched (as of the date of this writing) Ubuntu 18.04.2 LTS system.  As most of this doesn’t require one to be root, watch those prompt titles to make sure you know who is supposed to be running stuff.

The design goal is to be able to toss a pile of APKs that have been pillaged/looted/tactically acquired into a single directory, then automatically process them all such that we can quickly step from one to the other.

The Tools

I’m not going to reinvent any wheels here, so I’ll be using apktool and Reverse-APK to do the heavy lifting.  Let’s get both of them (and their dependencies) installed.  First up, the easiest one (apktool).  Just use apt-get directly:

root@system:~# apt-get install apktool

Okay, now for something a bit tougher.  Reverse-APK uses two tools (smali and baksmali) to do its magic, but there’s no clean package for Ubuntu to get that (there is on Kali, however: smali).  Let’s fake that part out.  First up, download the latest versions of both from JesusFreke’s download page.  As of this writing that’s 2.2.7.

Next, we’ll make a directory to host both of them:

root@system:~# mkdir /usr/share/smali

Copy the two .jar files here:

root@system:~# cp /home/user/Downloads/*smali.jar /usr/share/smali

Of course, we’ll need Java as well for smali/baksmali (and since, you know, Android), so if you don’t have that already add it to the system:

root@system:~# apt-get install openjdk-11-jdk

The Reverse-APK tool expects to call those natively, so we’ll use the helper script approach that JesusFreke specifies and create two files in /usr/local/bin.

root@system:/tmp# cat << 'EOF' > /usr/local/bin/baksmali
> #!/bin/bash
> cd /usr/share/smali/ && java -jar baksmali-2.2.7.jar "$@"

root@system:/tmp# cat << 'EOF' > /usr/local/bin/smali
> #!/bin/bash
> cd /usr/share/smali/ && java -jar smali-2.2.7.jar "$@"

Getting close!  Now let’s pull down Reverse-APK and install that.

root@system:~# cd /tmp
root@system:/tmp# git clone
Cloning into 'ReverseAPK'...
remote: Enumerating objects: 60, done.
remote: Total 60 (delta 0), reused 0 (delta 0), pack-reused 60
Unpacking objects: 100% (60/60), done.
root@system:/tmp# cd ReverseAPK/
root@system:/tmp/ReverseAPK# ./install

\______   \ _______  __ ___________  ______ ____  
 |       _// __ \  \/ // __ \_  __ \/  ___// __ \ 
 |    |   \  ___/\   /\  ___/|  | \/\___ \  ___/ 
 |____|_  /\___  >\_/  \___  >__|  /____  >\___  >
        \/     \/          \/           \/     \/ 
                                           _____ __________ ____  __.
                                          /  _  \______   \    |/ _|
      --=[( by 1N3@CrowdShield )]=--     /  /_\  \|     ___/      <  
   --=[( )]=--  /    |    \    |   |    |  \ 
                                        \____|__  /____|   |____|__ \
                                                \/                 \/

 Installing reverse-apk...

Reading package lists... Done
Building dependency tree

Okay, we’re ready to automate this!

The Automation

I like scripts.  In particular, I like Bash scripts because they work pretty much everywhere… so a Bash script it is!

# Program  :
# Author   : Brian Mork ("Hermit")
# Date     : 2019-06-07
# Contact  :
# Requires : smali/baksmali (
#            apktool        (
#            Reverse-APK    (
#            openjdk-11-jdk

PURELS=`which ls`

# Make something pretty
showHeader() {
	echo "+--------------------------+"
	echo "|    apk-process (v${VERSION})    |"
	echo "|         by: Hermit       |"
	echo "+--------------------------+"

# Show errors in a consistent way, using our pretty header
showError() {
	echo "ERROR!"
	echo $1
	exit 1

# Check for an installed pre-requisite, show error and exit if not found
checkDep() {
	which $1 > /dev/null 2>&1
	# If previous returned error, it wasn't found and we should exit
	if [ $? -ne 0 ]; then
		showError "Missing $1"

# Did we get two arguments?
if [ $# -ne 2 ]; then
	showError "Syntax: [apk-directory] [results-directory]"
# Does the specified source directory exist?
elif [ ! -d ${SUBAPKD} ]; then
	showError "The specified source APK directory does not exist!"
	APKDIR=$(cd $PWD/$1 && pwd -P)

# Get the number of files with ".apk" in their name from the source directory
declare -i APKCHK=`find ${APKDIR} -type f -iname '*.apk' -print 2>/dev/null | wc -l`
# If no APK files were found, we have nothing to do
if [ ${APKCHK} -lt 1 ]; then
	showError "No APKs were found in ${APKDIR}"

# Checking for required programs
checkDep smali
checkDep baksmali
checkDep reverse-apk
checkDep apktool

# Check if the output directory exists, and make it if not
if [ ! -d ${SUBOUTD} ]; then
	mkdir -p ${SUBOUTD}
	echo "  [+] INFO: Created ${SUBOUTD}"
OUTDIR=$(cd ${PWD}/${SUBOUTD} && pwd -P)

# Check for apktool directory, and create it if it doesn't already exist
if [ ! -d ${OUTDIR}/apktool ]; then
	mkdir -p ${OUTDIR}/apktool
	echo "  [+] INFO: Created apktool directory in ${OUTDIR}"
	echo "  [-] WARNING: The apktool directory already existed in ${OUTDIR}!"

# Check for reverse-apk directory, and create it if it doesn't already exist
if [ ! -d ${OUTDIR}/reverse-apk ]; then
	mkdir -p ${OUTDIR}/reverse-apk
	echo "  [+] INFO: Created reverse-apk directory in ${OUTDIR}"
	echo "  [-] WARNING: The reverse-apk directory already existed in ${OUTDIR}!"

# Looks like we're ready to rock. :)
# First fire off apktool, which helpfully allows us to specify an
# output directory... hint hint reverse-apk!
# Then we'll run reverse-apk, which unfortunately only takes the APK as an input, and stays in whatever
# directory... and uses the relative path to output, so we end up with a dumb situation where we have to
# either update the script itself (not very sustainable) or do the garbage we're going to
# do below with linking to fake it out. :)
for FILE in `${PURELS} ${APKDIR}/*.apk`; do
	FILESPLIT=`echo ${FILE} | awk -F'/' '{print NF}'`
	BASEFILE=`echo ${FILE} | cut -d '/' -f ${FILESPLIT}`
	FOLDER=`echo ${BASEFILE} | cut -d . -f 1`
	echo "  [+] INFO: Processing ${FILE}"
	echo -n "     [-] INFO: Processing ${FILE} with apktool... "
	apktool d ${FILE} -o ${OUTDIR}/apktool/${FOLDER} >> ${OUTDIR}/apk.log 2>&1
	echo "DONE"
	echo -n "     [-] INFO: Processing ${FILE} with reverse-apk... "
	mkdir ${RAPKDIR}
	cd ${RAPKDIR}
	ln -s ${FILE} ${BASEFILE}
	reverse-apk ${BASEFILE} >> ../../reverse-apk.log 2>&1
	unlink ${BASEFILE}
	echo "DONE"
	echo "  ---------------------------------------------------------"

Or grab a copy from my GitHub. 🙂

The #Victory.  Good hunting!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Website Powered by

Up ↑

%d bloggers like this: