-[ 0x05 ]--------------------------------------------------------------------
-[ Protocolo MetroTRK ]------------------------------------------------------
-[ by FCA00000 ]-----------------------------------------------------SET-35--


@.@------------------@.@
 $ Protocolo MetroTRK $ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{ by FCA00000 }
@.@------------------@.@


En este mismo nmero he contado que es posible sobrepasar la seguridad de
telfonos Symbian usando el debuger MetroTRK. Este debuger se maneja desde
un entorno grfico, normalmente:

      - Carbide.c++
   o
      - MetroWorks.

Sin embargo, para facilitar que todos los usuarios puedan aprovechar esta
vulnerabilidad, he hecho un programa que simula este entorno.

Para ello he necesitado destripar el protocolo usado. Esta es la historia
de los acontecimientos.

Las herramientas necesarias son:

   1.- Un mvil con Symbian S60v3, por ejemplo N78, E61, N95, 6220classic, ...
       Yo he usado un N80.

   2.- Un ordenador. Yo he usado uno de color negro.

   3.- Un cable USB de tipo CA-20 , que une ambos. Tambin es de color negro.

   4.- El programa MetroTRK para mviles, conocido como S60_App_TRK.sisx.
       He usado la versin 2.6

   5.- Drivers de Nokia para tratar el puerto USB como si fuera un puerto serie.

   6.- El programa Carbide.c++ para PC, versin 1.1 pro.

   7.- Un sniffer de puerto serie, por ejemplo Serial Port Monitor de Eltima
       Software.

   8.- Algo para hacer tus propios programas. Yo eleg Python, pero Java o C++
       tambin valdran.

Lo primero es poner en marcha todo el tinglado: instalar Carbide.c++ en el PC,
MetroTRK en el mvil, verificar que el sniffer funciona.

La primera prueba consiste en usar Carbide.c++ en el PC para hacer un programa
para el mvil. Existe un directorio con ejemplos que se pueden compilar sin
mucho esfuerzo.

Usando este mismo entorno se transfiere el programa al mvil, y hay que
aprender a poner breakpoints, leer la memoria, y saber cmo transferir
archivos. El siguiente paso es sacar todas las trazas con el sniffer, y
ponerse a analizarlas.

Es conveniente sacar varias trazas del mismo proceso. Para ello lo mejor es
resetear el entorno completo, hacer una prueba, guardar la traza, y empezar
reseteando otra vez. Con esto se consiguen trazas ms o menos constantes.
En particular esto permite discernir si se usa algn timestamp , dependiendo
de la hora a la que se ejecuta la prueba.

A partir de ahora usar el smbolo '>' para datos desde el PC al mvil, y '<'
para la otra direccin. Cada dato es 1 byte en formato hexadecimal.

Veo que el primer comando que Carbide.c++ manda es:

   > 7E 00 00 FF 7E

a lo que el mvil responde:

   < 7E 80 00 00 7F 7E

El siguiente comando es:

   > 7E 01 01 FD 7E

con respuesta

   < 7E 80 01 00 7D 5E 7E

El tercero es:

   > 7E 05 02 F8 7E
   < 7E 80 02 00 7D 5E 00 4F 5F 01 00 00... 80 03 97 7E

Bueno, parece que todos los comandos empiezan y acaban con 0x7E . Tanto los
que van, como los que vienen.

Si nos fijamos en el tercer byte, parece ser un nmero secuencial. En la
primera trama vale 0x00 , en la segunda vale 0x01, y la tercera dice 0x02.

Ms cosas: la respuesta del mvil tiene siempre el segundo byte a valor 0x80.
El tercer byte es el mismo nmero secuencial que se le ha enviado.

Con esto ya puedo sacar las primeras conclusiones:

   -> Cada mensaje va dentro de una trama con cabecera 0x7E y finalizada
      con 0x7E. Esto ayuda a separarlos.

   -> El PC manda un mensaje con un identificador secuencial, y el mvil
      responde con el mismo nmero. Esto ayuda a saber si un mensaje se
      ha perdido.

   -> El mvil responde con un cdigo 0x80. El PC no parece tener un
      cdigo asignado para cada pregunta.

As que empiezo a hacer mi programa.

Simplemente abro el puerto serie y empiezo a mandar exactamente lo mismo que
Carbide.c++ . Tras algunos apaos menores empiezo a recibir las mismas
respuestas.

   **************************************
   * ser = serial.Serial(7)	# COM8  *
   * ser.write(chr(0x7E))               *
   * ser.write(chr(0x00))               *
   * ser.write(chr(0x00))               *
   * ser.write(chr(0xFF))               *
   * ser.write(chr(0x7E))               *
   * s = ser.read(6)                    *
   * print ord(s[0])                    *
   * print ord(s[1])                    *
   * print ord(s[2])                    *
   * print ord(s[3])                    *
   * print ord(s[4])                    *
   * print ord(s[5])                    *
   **************************************

Ahora tengo que averiguar el significado del resto de los datos. Sospecho
que hay varios comandos, en funcin de lo que se haga desde el entorno grfico.

Empiezo a hacer varias acciones en Carbide.c++ , tales como:

   -> Leer memoria
   -> Escribirla
   -> Poner breakpoint
   -> Quitarlo
   -> Detener programa
   -> Ejecutar 1 paso
   -> Leer registros
   -> Ponerlos

y veo que manda distintos comandos, identificados por el byte en la posicin 1.
Por ejemplo, leer memoria en la direccin "0x6404D1E0", resulta en el comando:

   > 7E 10 03 05 01 00 64_04_D1_E0 00 00 00 00 00 00 00 01 CC 7E

Ya sabemos que:

   - 7E es la seal de cabecera
   - 10 es la orden para leer memoria
   - 03 es el nmero secuencial
   - 05 ni idea
   - 01 ni idea
   - 00 ni idea
   - 64 04 D1 E0 es justamente la direccin que quiero leer
   - 00 00 00 00 ni idea
   - 00 00 00 01 puede que sea el valor 1 , pues quiero leer 1 byte
   - CC ni idea
   - 7E es la marca de fin

Ahora viene una tcnica tpica de anlisis inverso: voy a mandar un comando
ligeramente distinto al anterior. Para ello leo la memoria de la direccin
"0x6404D1E4" , que es la misma que antes, 4 bytes ms adelante, pero tomo
la precaucin de resetear el entorno, includo el mvil. La razn es que
quiero que el nmero secuencial se inicie de nuevo, para que sea 0x03, igual
que antes.

Y veo que se manda el comando:

   > 7E 10 03 05 01 00 64 04 D1 _E4_ 00 00 00 00 00 00 00 01 _C8_ 7E

o sea, igual que el comando anterior excepto 2 bytes que han cambiado:

   - E4 en lugar de E0 . Normal, pues he ledo "0x6404D1E4"
     en lugar de "0x6404D1E0"

   - El penltimo dato es ahora C8, y antes era CC

Notar que CC-C8= 0x4 . Es decir, que ha cambiado en la misma medida que la
direccin de memoria.

Podra ser la direccin final que hay que leer? Bueno, yo me inclino ms
por un checksum. La razn es que este penltimo dato est presente en todos
los comandos, y me sorprendera si un protocolo no incluyera algn tipo de
verificacin.

As que recupero el comando inicial:

   > 7E 00 00 FF 7E

y lo modifico ligeramente para mandar un checksum distinto:

   > 7E 00 00 F1 7E

y recibo:

   < 7E FF 07 05 F4 7E

que intuyo que significa que ha habido un error.

Bueno, al menos ya s lo que pasa cuando el protocolo es incorrecto.
Fijaos bien que el comando inicial, eliminando el checksum y los 0x7E de
cabecera y final, es: "00 00" y tiene checksum: FF

El segundo mensaje es:

   >7E 01 01 FD 7E

Si quito tambin el checksum y los 0x7E, queda: "01 01" que resulta en
checksum: FD

El tercero es:

   > 7E 05 02 F8 7E

que contiene datos: "05 02" y checksum: F8

No veis algo aqu? Lo pondr ms claro:

      00 + 00 + FF = FF
   y
      01 + 01 + FD = FF
   y
      05 + 02 + F8 = FF

es decir, que la suma de todos los datos (excepto cabecera y final) tiene
que sumar 0xFF. Esto se denomina checksum de complemento: el penltimo dato
es el valor que hace que la suma de todos los bytes de la trama resulte 0xFF.

Lo verifico con otras tramas y parece ser correcto ... excepto en algunos casos.
La verdad es que esto que voy a explicar tiene sentido visto en retrospectiva,
pero inicialmente me confundi.

La pregunta clave es:

Qu pasa si quiero mandar el dato 0x7E dentro de la trama?

Por ejemplo, si necesito leer la memoria en "0x7E7E7E7E". Si intento mandar
manualmente el comando:

   > 7E 10 03 05 01 00 7E 7E 7E 7E 00 00 00 00 00 00 00 01 AD 7E

creer que el segundo 0x7E (byte sptimo) indica el final de trama y resultara
la trama parcial:

   > 7E 10 03 05 01 00 7E

que es incorrecta (el checksum debera ser 00 , que en realidad no es el
checksum)

Es decir, que el valor 0x7E no se puede mandar 'tal cual' porque el protocolo
se har un lo. Para eso se usa la tcnica de 'escapar' los datos de control.

Para saber cmo se aplica este mtodo, le digo a Carbide.c++ que quiero leer
la memoria "0x7E7E7E7E" y resulta el comando:

   > 7E 10 03 05 01 00 7D_5E 7D_5E 7D_5E 7D_5E 00 00 00 00 00 00 00 01 ED 7E

o sea, que manda "7D_5E" en vez de "7E".

Y si quiero mandar 0x7D? En este caso veo que se mandan como "7D_5D"

Entonces creo que ya s cmo construir las tramas:

   1.- Averiguar el comando, por ejemplo 0x10 para leer la memoria.
   2.- Obtener un nmero secuencial. Ponerlo a continuacin.
   3.- Poner el resto de parmetros. Para leer la memoria, es necesario la
       direccin y el tamao.
   4.- Calcular el checksum, sumando todos los valores. Ponerlo al final.
   5.- Sustituir 7D_5D en lugar de 7D, y 7D_5E en lugar de 7E
   6.- Poner las cabeceras 7E y el finalizador 7E
   7.- Mandarlo.
   8.- Esperar respuesta.

Ahora queda saber cuales comandos se pueden mandar. Por ejemplo la trama:

   > 7E _00_ 00 FF 7E

es la primera que se manda, por lo que podra ser una especie de saludo.

La siguiente es:

   > 7E _01_ 01 FD 7E
que no s lo que significa.

As que, en mi propio programa, puedo tomar 2 decisiones:

   a) mandarlo. No hace dao

   b) no mandarlo, y ver qu pasa.

Pruebo la opcin b) y parece que todo funciona bien. Posiblemente sea un
comando para que Carbide.c++ sepa la versin de MetroTRK que est instalada.

Para aprovechar la vulnerabilidad que encontr en Symbian S60v3 lo que necesito
es leer la memoria y escribirla, as que me voy a centrar en esos comandos.
Ms o menos s que para leer la memoria uso el comando 0x10 y uno de los datos
es la direccin de memoria, escrita como 4 bytes en big-endian.

Ahora lo que me interesa es saber qu datos me enva el telfono. La respuesta
es algo as como:

   < 7E 80 03 00 01 00 10 12 34 56 78.....

Ya s que:

   - 7E es la cabecera
   - 80 significa que todo ha ido bien
   - 03 es el nmero secuencial de comando

Luego hay otros 4 bytes que indican la cantidad de bytes ledos. Y los datos
siguientes son justamente el contenido de la memoria.

Nota: al igual que en los mensajes enviados, es necesario des-escapar los
valores "7D_5E" y "7D_5D" .

Por ejemplo, esta trama recibida indica que:

   - 0x6404D1E0 contiene valor 0x12
   - 0x6404D1E1 contiene valor 0x34
   - 0x6404D1E2 contiene valor 0x56
   - 0x6404D1E3 contiene valor 0x78

Para saber el comando para escribir en la memoria, le digo a Carbide.c++ que
modifique 0x6404D1E0 para el valor 0x33 y el comando es:

   > 7E 11 04 08 00 04 64_04_D1_E0 00_00_00_00 00_00_00_01 33 ...

en el que se pueden ver los datos:

   - 11 que sirve para escribir en memoria
   - 64_04_D1_E0  que es la direccin de destino
   - 00_00_00_00 que no s lo que significa
   - 00_00_00_01 para escribir 1 byte
   - 33 , que es el valor del byte que quiero escribir

Fcil, no? Ahora slo tengo que generar este comando en mi programa.
Recordar que la direccin a escribir es 0x64000148 con el valor 0x10,
as que el comando es:

   > 7E 11 04 08 00 04 64_00_01_48 00_00_00_00 00_00_00_01 10 ...

y ya est: simplemente con mandarle estos bytes al mvil, se abren
todas las puertas. La proteccin de Symbian est rota.

Puedes encontrar el resultado buscando hack_perms_s60v3.py en foros
sobre telfonos mviles Nokia.

Una vez hecho el esqueleto, podra haberlo ampliado para hacer un entorno
grfico, o bien integrarlo con mi propio debuger, pero no lo hice porque
Carbide.c++ ya es lo suficientemente bueno como para no necesitar mejoras.

Tras publicar este descubrimiento fui contactado por Ilfak Guilfanov, el
creador del desensamblador IDA, para compartir ideas. El resultado es:

http://hexblog.com/2008/03/symbian_apptrk.html

Yo tambin pens en integrarlo con el debuger GDB de linux, pero dado que
no hay compiladores para Symbian que funcionen en Linux, no le veo ningn
beneficio.

Ms tarde encontr varios documentos y utilidades que habran hecho mi tarea
ms fcil:

   1.- En Carbide.c++ es posible ver las trazas que se le mandan a MetroTRK.
       No incluye la cabecera, pero explica los argumentos necesarios para
       cada comando. En particular explica los distintos cdigos de error.

   2.- Un documento que explica cmo funciona MetroTRK y cmo adaptarlo a
       otros procesadores y otros sistemas operativos.

   3.- Desensambl el propio MetroTRK en el mvil para ver qu otros comandos
       se pueden mandar. Casi todos se pueden probar desde Carbide.c++ pero
       alguno no, por ejemplo sacar el listado de libreras.

Este conocimiento fue compartido con gente a lo largo del mundo, y sirvi para
que algunos crackers elaboraran un sistema para piratear juegos de N-Gage. No
digo que est bien ni mal; slo lo quera mencionar.

Los fabricantes de MetroTRK, liderados por Nokia y Symbian, se apercibieron de
la situacin e idearon un mecanismo para anular este truco en las nuevas
versiones de firmware.

Este anti-hack consiste en instalar una versin limitada de MetroTRK, lo cual
impide instalar la versin vulnerable. Obviamente no afecta a aquellos que ya
la han aprovechado para abrir sus mviles, pero impide que nuevos usuarios
tengan acceso total a sus propios telfonos.

A da de hoy se siguen buscando nuevas vulnerabilidades para romper las nuevas
protecciones impuestas. Y si una nueva puerta se abre, las empresas involucradas
las cerrarn de nuevo.

As una y otra vez...

*EOF*