Continuación de Parte I.
El siguiente paso es descifrar el binario, ya que cuando un desarrollo es terminado por sus autores y enviado a Apple para añadirlo a la Apple Store, este es analizado y examinado. Si supera los tests, será cifrado y firmado, complicando que se haga ingeniería inversa sobre el.
Para descifrarlo tan solo hay que ejecutarlo y con gdb se vuelca la memoria del proceso. Tal y como se haría genéricamente para desempacar un binario en otra plataforma.
Antes de hacer esto, es recomendable que se conozca un mínimo la estructura de un binario Match-O, que en muy grandes rasgos se representa en este gráfico:
- El fichero contiene una cabecera donde se identifican distintos aspectos como si es fat o en la arquitectura en la que corre.
- Tras la cabecera se encuentran los comandos, en los que se definen otras características como la localización de la tabla de símbolos, o los nombres de las librerías compartidas que son importadas en su ejecución.
- Finalmente los datos que son divididos en segmentos y estos en secciones. Los dos segmentos más importantes son:
- __TEXT, donde se encuentra el código de la aplicación y otros datos de solo lectura y
- __DATA, donde la aplicación podrá escribir e intercambiar datos.
Volviendo al binario, para comprobar si está cifrado se puede consultar si el flag "cryptid" del comando LC_ENCRYPTION_INFO es igual a 1, además de otros valores como el tamaño del bloque cifrado "cryptsize"
Con la herramienta otool se obtienen estos valores:
iPhone:~ root# otool -l /private/var/mobile/Applications/58ED43CF-0D53-4DDC-864C-7F34D34E059C/StupidZombiesDLX.app/StupidZombiesDLX | grep crypt
cryptoff 8192
cryptsize 10133504
cryptid 1
Como se va a descifrar el binario, hay que cambiar el valor de cryptid a 0, para esto es necesario parchearlo modificando la cadena del comando LC_ENCRYPT_INFO, que contiene los valores: 0000002100000014......................01 por 0000002100000014......................00, donde los puntos representan valores (11) que pueden variar.
La forma más sencilla de cambiar este byte es copiando el binario con DiskAid a la estación de trabajo para usar editor hexadecimal, buscar por la cadena hexadecimal 0000002100000014, contar 11 bytes más y modificar el 01 por 00. Guardar y dejar el fichero en el iPhone en un fichero temporal.
Otra opción es leer la cabecera del fichero en hexadecimal, hacer la modificación y posteriormente guardarlo en un fichero. Esto se puede hacer con estos dos comandos dentro del teléfono:
iPhone:/tmp root# hex=`dd bs=4096 count=1 if=/private/var/mobile/Applications/58ED43CF-0D53-4DDC-864C-7F34D34E059C/StupidZombiesDLX.app/StupidZombiesDLX 2>/dev/null| od -A n -t x1 -v | tr -d ' ','\n' | sed -e 's|0000002100000014\(.\{22\}\)01|0000002100000014\100|' | sed -e 's|\(..\)|\\\\x\1|g'`
iPhone:/tmp root# echo -ne "$hex" > /tmp/header.hex
Se verifica que cryptid ahora es igual a 0:
iPhone:/tmp root# otool -l /tmp/header.hex | grep -i crypt
cmd LC_ENCRYPTION_INFO
cryptoff 8192 (past end of file)
cryptsize 10133504 (past end of file)
cryptid 0
WIN!
Si aun no te has cansado, continuamos la semana que viene con las instrucciones necesarias para el volcado final.
5 comments :
Excelente tutorial!! Espero impaciente al próximo. ¿Dónde aprendistes todo esto? Muchas gracias por compartirlo con todos!
Pues esperaremos a la semana que viene para el nuevo capítulo (como quien espera por Dex)
Muy buen trabajo, está todo muy bien explicado :)
Hay algo que no entiendo. Para poder usar gdb y ver el código y tal, es necesario que el ejecutable permita el depurado y se pueda hacer un attacht al proceso no?
Y en cuanto al cifrado, tan fácil cambiarlo a no cifrado?
Supongo que todo esto es posible solo para terminales rooteados (No me acuerdo como se dice para los Iphone xD)
De cualquier manera, te felicito, no tengo Iphone pero estoy siguiendo estos post.
Un saludo.
Buenas Alex,
Para usar gdb, el código da igual como esté, ya que gdb es un debugger. Lo que se trata aquí (y en la primera y última parte) es como descifrar el binario para desensamblarlo posteriormente y poder interpretar su contenido, independientemente de que se ejecute o adjunte con gdb el proceso.
Esto que se ha cambiado aquí, solo es un byte que indica que está cifrado, si le dices que no está cifrado y lo está, no funcionará. Falta la última parte donde se descifra definitivamente. Es decir, esto solo es la primera parte para descifrarlo "de verdad".
Gracias.
Gracias, me he confundído, pensaba que lo que se quería hacer era depurar el programa.
Un saludo.
Publicar un comentario