30 enero 2012

Seguridad en aplicaciones IOS, Parte III

Continuación de la parte II.

Ahora se procede a ejecutar la aplicación con el debugger y volcar su contenido. Para este proposito se usa gdb y una serie de comandos propios de gdb.

Antes de empezar, se requiere que se calculen previamente un par de direcciones, en concreto, el rango de inicio y final de la memoria a copiar.

El primero se obtiene sumando el la dirección de volcado de la aplicación del segmento __TEXT (decimal, ya que otool la muestra en hexa) con el valor de cryptoff. En este ejemplo: 12288

iPhone:~ root# otool -l /private/var/mobile/Applications/58ED43CF-0D53-4DDC-864C-7F34D34E059C/StupidZombiesDLX.app/StupidZombiesDLX | grep -i cryptoff
 cryptoff  8192
iPhone:~ root# otool -l /private/var/mobile/Applications/58ED43CF-0D53-4DDC-864C-7F34D34E059C/StupidZombiesDLX.app/StupidZombiesDLX | grep -A3 LC_SEGMENT
      cmd LC_SEGMENT
  cmdsize 56
  segname __PAGEZERO
   vmaddr 0x00000000
--
      cmd LC_SEGMENT
  cmdsize 668
  segname __TEXT
   vmaddr 0x00001000
iPhone:~ root# printf "%d\n" 0x00001000 # se convierte a decimal
4096
iPhone:~ root# echo $(( 8192 + 4096 ))
12288

El valor final se saca con la suma de vmaddr, cryptoff y el tamaño del bloque cifrado, mostrado en la variable de cryptsize de otool. El resultado es: 10145792

iPhone:~ root# otool -l /private/var/mobile/Applications/58ED43CF-0D53-4DDC-864C-7F34D34E059C/StupidZombiesDLX.app/StupidZombiesDLX | grep -i cryptsize
   cryptsize 10133504
iPhone:~ root# echo $(( 4096 + 8192 + 10133504 ))
10145792

Con estos datos ya se puede ejecutar el depurador gdb para que haga el volcado de memoria, configurando previamente algunas variables:

iPhone:/private/var/mobile root# gdb -q -e /private/var/mobile/Applications/76E71A40-F6A2-40DC-9A3A-B0633633D659/StupidZombiesDLX.app/StupidZombiesDLX
Reading symbols for shared libraries .. done
(gdb) set sharedlibrary load-rules ".*" ".*" none
(gdb) set inferior-auto-start-dyld off
(gdb) set sharedlibrary preload-libraries off
(gdb) set sharedlibrary load-dyld-symbols off
(gdb) handle all nostop
Signal        Stop      Print   Pass to program Description
SIGHUP        No        Yes     Yes             Hangup
SIGQUIT       No        Yes     Yes             Quit
[.. recorto...]
EXC_SOFTWARE  No        Yes     Yes             Software generated exception
EXC_BREAKPOINT No       Yes     Yes             Breakpoint
(gdb) rb doModInitFunctions
Breakpoint 1 at 0x2fe0ce36
 __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE;
(gdb) command 1
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>dump memory /tmp/dump.bin 12288 10145792
>kill
>quit
>end
(gdb) start
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n])

Starting program: /private/var/mobile/Applications/76E71A40-F6A2-40DC-9A3A-B0633633D659/StupidZombiesDLX.app/StupidZombiesDLX

Breakpoint 1, 0x2fe0ce36 in __dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE
    ()
Kill the program being debugged? (y or n) y
iPhone:/private/var/mobile root# ls -la /tmp/dump.bin
-rw-r--r-- 1 root wheel 10133504 Jan 25 00:16 /tmp/dump.bin

"Copiamos" los dos trozos modificados, sobreescribiendo los originales; la cabecera con  cryptid igual a 0 y el volcado de memoria no cifrado. El parámetro "obs" del segundo comando dd, debe ser igual al cryptoff, y el parámetro "ibs", al tamaño del fichero.

iPhone:/private/var/mobile root# cp /private/var/mobile/Applications/76E71A40-F6A2-40DC-9A3A-B0633633D659/StupidZombiesDLX.app/StupidZombiesDLX /tmp
iPhone:/private/var/mobile root# dd bs=1 conv=notrunc status=noxfer if=/tmp/header.hex of=/tmp/StupidZombiesDLX
iPhone:/private/var/mobile root# dd seek=1 count=1 obs=8192 ibs=10133504  conv=notrunc if=/tmp/dump.bin of=/tmp/StupidZombiesDLX

A partir de este momento, el fichero /tmp/StupidZombiesDLX es funcional y está descifrado, lo que lo habilíta para hacer ingeniería inversa sobre el.

Pongo como ejemplo dos capturas de pantalla de IDA Pro, que desde su versión 6.2 soporta  el análisis de estructuras de metadatos Objective-C y que se puede descargar con limitaciones gratuitamente.

La primera imagen muestra el contenido sin descifrar y la segunda una vez ha sido volcado de la memoria.



 esto es todo (¡por fin!), en la próxima entrada hablaré de las herramientas más comunes de desensamblado de aplicaciones IOS y como se hace en caso de que sea binary fat y con aslr completo. Espero que pese a  los pocos comentarios de las entradas anteriores os haya gustado y recordad que si necesitáis de nuestros servicios, nuestro correo está en la parte de contacto :)


7 comments :

Hans Castorp dijo...

Los artículos técnicos interesan a gente técnica y sobreviven al paso del tiempo porque siempre "están ahí" y salen a relucir tras una búsqueda. No midas la calidad o el interés de tu artículo por la cantidad de comentarios que recibe. Si es eso lo que buscas habla de facebook, whatapps (o como cojones se llame). Es una buena serie de artículos, no comida rápida que se tragará Google en un par de días.

Rodolfo dijo...

Te has currado un supermanual, que como muy bien dicen en el comentario anterior, siempre estará ahí para cuando haga falta.

Invitado dijo...

es muy interesante! ;)

Así como la carpeta que utilizas (crap :P)

murphy dijo...

Felicitaciones a este remate final con la parte de debugging. Ansioso de jugar con ello :) aunque me ha faltado una parte mas grafica en la (arte del calculo de offsets para el memdump.

No obstatnte, gran articulo!

Anónimo dijo...

son iguales las dos últimas imágenes png o me lo parece a mí?
igualmente y aun a riesgo de ser pesado me uno a las felicitaciones.

g0su dijo...

Lo son, ambas están cifradas. Se habrá equivocado subiéndolas.

La pena de esto es que sea Objective-C porque con OllyDump y OllyScript se podría automatizar, pero claro, debería soportar O-C.

Alejandro Ramos dijo...

¡Ups! tenéis razón, ya he cambiado la imagen.

Gracias a todos!