La mayoría de las aplicaciones de Android no se compilan a código nativo, sino que se compilan en Java, lo que hace que se ejecuten en bytecode en una máquina virtual.
Como resultado, es posible tomar el bytecode, y generar código fuente Java que volverá a compilar al mismo bytecode. Cualquier optimización tiene lugar durante la recompilación dinámica a código nativo, que ocurre para cualquier código que se golpea durante la ejecución, y sólo se queda en la VM hasta que el programa termina.
No se recuperan cosas como los nombres de las variables o los comentarios, por supuesto.
Para las Apps nativas en Android, o en una App de iOS, se compilan realmente a código nativo.
Para iOS, si se trata de una App JavaScript que vive en un UIView por lo que se ejecuta más o menos en una ventana del navegador, se puede sacar el JavaScript.
Aparte de eso, una serie de transformaciones en la compilación son tales que no se puede recuperar el código fuente del código compilado.
De hecho, es un problema N-P difícil incluso generar el código fuente, que, si se ejecuta a través de un compilador, resultaría en el mismo código objeto, porque no hay una correspondencia uno-a-uno, hay inlining de funciones, algunas funciones se transforman en el optimizador peephole, puede haber optimización de llamadas de cola que parece una instrucción de salto, pero que es en realidad una llamada sin un empuje de registro al final de una función, y así sucesivamente.
En los viejos tiempos, los compiladores eran bastante malos en la optimización y usted podría trabajar su camino de regreso; hoy en día: no es posible.
Si usted quiere tirar de un programa existente, tendrá que invertir en una herramienta como IDA Pro, y usted tendrá que tirar de él hasta el código ensamblador.
En el lado positivo, el código ARM tiene un tamaño de instrucción de longitud fija, y por lo que es posible distinguir el código de los datos. Esto no es tan fácil en las máquinas de arquitectura x86, con una longitud de instrucción variable, y no necesariamente sabrás lo que estás viendo.
Un PPC también tiene instrucciones de longitud fija, y por lo tanto también es determinista de esta manera.
Pero lo mejor que conseguirás son contratos de la API fuera de las bibliotecas, y puedes encontrarte con problemas al saltar a través de tablas de salto o vtables, donde lo que parece un dato es en realidad un puntero de función.