Ingeniería inversa en Android: Descompilación, modificación de Smali y refirmado de APK

El proceso de ingeniería inversa en Android permite analizar el comportamiento de una aplicación, auditar su seguridad o incluso realizar modificaciones funcionales mediante la manipulación de su código intermedio. Para llevar a cabo este procedimiento de manera efectiva, es necesario contar con un conjunto de herramientas específicas y comprender el flujo de trabajo desde el binario hasta el código legible.

Herramientas esenciales

  • Apktool: Utilizada para decodificar recursos y reconstruir el archivo APK. Permite obtener el código en formato Smali.
  • dex2jar: Convierte archivos .dex (Dalvik Executable) en archivos .jar para facilitar la lectura del código fuente en Java.
  • JD-GUI: Un visor gráfico que permite explorar el código Java contenido en los archivos JAR generados.
  • jarsigner / apksigner: Herramientas incluidas en el JDK o el Android SDK para firmar digitalmante el APK modificado, requisito indispensable para su instalación.

Creación de un escenario de prueba

Para ilustrar el proceso, supongamos una aplicación básica llamada LaboratorioApp. En su actividad principal, cuenta con un botón que, al ser presionado, envía un mensaje al log del sistema.

public class EditorActivity extends AppCompatActivity {
    private static final String LOG_TAG = "APP_DEBUG";
    private Button btnEjecutar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_editor);

        btnEjecutar = findViewById(R.id.btn_test);
        btnEjecutar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(LOG_TAG, "Evento de clic detectado");
            }
        });
    }
}

Fase 1: Descompilación y extracción de recursos

El primer paso consiste en extraer los archivos del APK original utilizando Apktool. Esto genera una estructura de directorios que incluye el manifiesto, los recursos (XML, imágenes) y el código Smali.

java -jar apktool.jar d base_original.apk -o proyecto_descompilado

Si necesitamos analizar la lógica de negocio en Java, convertimos el archivo classes.dex (obtenido al descomprimir el APK como un ZIP) a un formato legible por JD-GUI:

d2j-dex2jar.sh classes.dex

Fase 2: Aálisis del código Smali

El código Smali es una rperesentación legible por humanos del bytecode de la máquina virtual Dalvik/ART. Al abrir EditorActivity.smali, localizamos el método que gestiona el clic:

.method public onClick(Landroid/view/View;)V
    .locals 2
    .param p1, "v"    # Landroid/view/View;

    .prologue
    const-string v0, "APP_DEBUG"
    const-string v1, "Evento de clic detectado"

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    return-void
.end method

Fase 3: Modificación e inyección de código

Si deseamos alterar el comportamiento (por ejemplo, mostrar un Toast en lugar de un log), una estrategia eficiente es escribir el código deseado en Java en un proyecto aparte, compilarlo y extraer su representación en Smali. Supongamos que queremos inyectar el siguiente método:

public void mostrarAlerta() {
    Toast.makeText(this, "¡Sistema Modificado!", Toast.LENGTH_SHORT).show();
}

Tras descompilar nuestra aplicación de prueba, obtenemos el bloque Smali correspondiente al Toast y lo insertamos en el archivo EditorActivity.smali del proyecto original, sustituyendo la llamada al Log por una llamada a nuestro nuevo método o directamente por la lógica del Toast:

# Lógica inyectada para mostrar un Toast
const-string v0, "\u00a1Sistema Modificado!"
const/4 v1, 0x0
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V

Fase 4: Reempaquetado y firma

Una vez modificados los archivos Smali, procedemos a reconstruir el archivo APK utilizando nuevamente Apktool:

java -jar apktool.jar b proyecto_descompilado -o app_modificada_sin_firmar.apk

El sistema Android rechaza cualquier aplicación que no esté firmada. Por lo tanto, debemos aplicar una firma digital. Si no se dispone de una llave existente, se puede generar una nueva con keytool y luego aplicarla:

jarsigner -verbose -keystore mi_llave.jks -signedjar app_final.apk app_modificada_sin_firmar.apk alias_llave

Tras completar estos pasos, el archivo app_final.apk estará listo para ser instalado en un dispositivo o emulador, ejecutando el código modificado con éxito.

Etiquetas: Android Reverse Engineering Smali Apktool Cybersecurity

Publicado el 6-7 23:53