Bad Daemons

Cómo sacar el código de un apk

Una de las cosas buenas que tienen las aplicaciones para android, es que permiten que se examine el código fuente, sin que la licencia que tiene importe demasiado. Evidentemente, de hacerlo y querer modificarlas, no se podrian distribuir (supuestamente), ya que esto iria, de ser privativas, en contra del copyright. Es posible que ni siquiera sea legal examinarlo, ya se sabe cómo son con estas cosas. Pero cómo no pueden evitarlo, al lío.

Las órdenes estarán pensadas para usar en Ubuntu 16.04. "Oh dios mío, Ubuntu, que te ha pasado, tu antes molabas." La vida. El motivo de usarla es que encontré la manera de hacerlo apuntando a Ubuntu concretamente, y dado que lo he hecho usando docker, me da bastante igual la distribución. En teoria deberia ir con cualquier distro, adaptando los paquetes a cómo se llamen en esa. Por cierto, aquí está el link al repositorio git en el que tengo el Dockerfile para poder construir esa imagen. Si os da igual el cómo, podéis seguir el README y en 10 minutos estar descompilando apk. Para las que tienen curiosidad en la vida, ahí va.

Desde el propio Ubuntu, primero de todo actualizar e instalar todos los paquetes que seran necesarios. Es posible que varios ya lo estén:

su -c "apt-get update; apt-get install  --no-install-recommends ca-certificates net-tools openssh-server unzip openjdk-8-jdk mercurial gradle patch wget"

Ahora, se descargaran dos herramientas básicas para darle al tema. La primera, dex2jar. Se descarga, descomprime, enlace simbolico y permisos de ejecución.

cd ~/
wget https://sourceforge.net/projects/dex2jar/files/dex2jar-2.0.zip/download -O dex2jar.zip
unzip dex2jar.zip
rm dex2jar.zip

Ahí va la primera. Esta herramienta lo que hace es pasar del formato .dex, que es lo que usa la máquina virtual java de Android (Dalvik) y lo pasa a un formato jar, lo que permite que se ejecute o se manipule con openjdk.

La segunda herramienta es procyon (luego me quejo de los nombres de mis programas), que es un conjunto de herramientas de metaprogramación (su definición). Tiene un montón de cosas que nos dan muy igual, sólo nos interesa una de ellas, el decompiler. Ahora se clona el repositorio.

cd ~/
hg clone https://bitbucket.org/mstrobel/procyon
cd procyon

Un pequeño parón aquí. Hay que quitar todas las líneas en las que salga "sign" del archivo build.gradle. Lo podéis hacer a mano o podéis guardar el siguiente bloque de código con el nombre de parche en el directorio procyon y aplicarlo con patch < parche en el directorio del programa.

diff -r 1aa0bd29339b build.gradle
--- a/build.gradle      Sat May 21 11:20:43 2016 -0400
+++ b/build.gradle      Tue May 31 12:11:49 2016 +0000
@@ -59,7 +59,6 @@

 subprojects {
     apply plugin: 'maven'
-    apply plugin: 'signing'

     archivesBaseName = 'procyon-' + it.name.split("\\.")[1].toLowerCase()

@@ -91,10 +90,6 @@
             archives sourcesJar
         }

-        signing {
-            sign configurations.archives
-        }
-
         uploadArchives {
             repositories.mavenDeployer {
                 beforeDeployment { MavenDeployment deployment ->

Solo queda compilar el programa. Puede que de algún warning, es un poco quejica. Pero si no es más que eso, deberia funcionar correctamente:

gradle fatJar

Y con esto, ya podemos empezar a descompilar apk. El proceso viene a ser, pasar los .dex a .jar y descompilarlo sin más. Las órdenes serian:

# aquí tenemos el apk, por ejemplo
cd ~/apk
mv com.ejemplo.apk com.ejemplo.apk.zip
unzip com.ejemplo.apk.zip
dex2jar classes.dex
mkdir ~/src
java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.jar -jar classes-dex2jar.jar -o ~/src

Y con esto ya esta. Es bastante sencillo. Pero un poco coñazo, sobretodo si se piensa que esto no se hace de manera habitual (yo no tengo por costumbre descomprimir apk). Si se hace muy de vez en cuando, cada vez que se haga habra que remirar este articulo, o unos apuntes o lo que sea. Por ello, vamos a dejarlo bonico der to con un par de enlaces simbolicos y algunos scripts.

ln -s ~/dex2jar-2.0/d2j-dex2jar.sh /usr/local/bin/dex2jar
chmod +s ~/dex2jar-2.0/d2j-dex2jar.sh ~/dex2jar-2.0/d2j_invoke.sh

El siguiente script, se meterá en /usr/local/bin/decompiler y se le dará permisos de ejecución con chmod +x /usr/local/bin/decompiler. Aviso: hay que tener en cuenta que en ambos scripts se da por supuesto que los programas están en la raiz de /home/$USER. Si no está ahí, deberia adaptarse.

#!/bin/bash

if [ -z "$1" ] || [ -z "$2"]
then
    echo "You need to pass the apk path and the output pasth as an argument. Exiting..."
    exit
fi

java -jar ~/procyon/build/Procyon.Decompiler/libs/procyon-decompiler-0.5.32.jar -jar "$1" -o "$2"

Lo mismo con el siguiente, pero con el nombre de /usr/local/bin/automatic-decompile y se le dará permisos de ejecución con chmod +x /usr/local/bin/automatic-decompile. Este nombre no tiene por que ser así, pero el anterior si que debe llamarse decompiler, ya que está hardcodeado en el siguiente.

#!/bin/bash

if [ -z "$1" ]
then
    echo "You need to pass the apk path as an argument. Exiting..."
    exit
fi

mkdir -p ~/tmp/"$1"
cp "$1" ~/tmp/"$1"/"$1".zip
cd ~/tmp/"$1"/

echo "Unziping apk..."
unzip "$1".zip > /dev/null

echo "Executing dex2jar..."
dex2jar classes.dex 2> /dev/null

echo "Decompiling jar..."
mkdir -p ~/src/"$1"
decompiler classes-dex2jar.jar ~/src/"$1" > /dev/null
echo "Done. The source code is under ~/src/$1/. You can delete ~/tmp."

Y ale. De este modo, para descomprimir un apk sólo habrá que ejecutar:

automatic-decompile /ruta/al/apk

Entonces, se crearán dos directorios, ~/tmp/ ~/src/. El código estará disponible en el segundo, el primero, cómo su nombre indica, se podrá borrar. Más sencillo de recordar entre uso y uso, creo yo.