SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

SET 33

56737 visitas

crack-symbian

      4610

Autor: FCA00000
-[ 0x05 ]--------------------------------------------------------------------
-[ Crack Symbian ]-----------------------------------------------------------
-[ by blackngel ]----------------------------------------------------SET-33--

Crack Symbian
--------------
Para seguir con el tema de symbian, voy a explicar como se pueden modificar
aplicaciones programadas en este sistema operativo.
Esto es valido para cualquier telefono Symbian, no solo el SX1.
Esto incluye n-gage, Sendo, y la mayoria de los Nokias de nueva generacion.
Oficialmente existen 10.000 aplicaciones disponibles, pero a decir verdad
yo no me creo esta cifra; si hay mas de 1.000, me daria por contento.

Las herramientas son:
-un movil Symbian
-una aplicacion que deseemos modificar.
-desensamblador IDA o similar.
-es bueno tener a mano el SDK de symbian. Al menos la documentacion.

Las aplicaciones generalmente se descargan desde la pagina web del
proveedor, y tienen extension  *.sis
Hay otro tipo de aplicaciones hechas en java que se proporcionan como
un fichero *.jar y otro *.jad . Estos son programas en java, y no son
objetivo de este articulo, ya que los explique en un numero anterior de SET.


Lo primero es transferir la aplicacion hacia el movil:
-por el puerto infrarrojos. Esto es lo que yo uso.
-mediante BlueTooth.
-copiandola en la tarjeta MMC usando un lector/escritor en el PC

Este ultimo metodo no es confortable en los Nokia, porque la MMC esta debajo
de la bateria, y para sacarla hay que desmontar el movil. En el SX1 esta en
un lateral y se puede extraer incluso con el movil encendido.

A continuacion se inicia una aplicacion interna al movil llamada instalador.
Esta aplicacion se llama
Z:\System\Libs\InstEng.dll
que sigue las instrucciones que le dice el fichero  *.sis

Para ver el contenido de este fichero podemos usar la aplicacion
SISTool by Alezz, del Z-Team.
Por ejemplo, vamos a analizar la aplicacion  FExplorer1.15 , que creo que
todo el mundo la tiene, puesto que resulta extremadamente util.
Sirve para manejar ficheros: mover, renombrar, transmitir por BlueTooth, ...
Los ficheros incluidos en el instalador son:

1) License.txt
2) !:\system\apps\FExplorer\FExplorer.aif
3) !:\system\apps\FExplorer\FExplorer.app
4) !:\system\apps\FExplorer\FExplorer.rsc
5) !:\system\apps\FExplorer\FExplorer.mbm
6) !:\system\apps\FExplorer\EXETEST.EXE
7) !:\system\apps\FExplorer\keys.txt

Usando SISTool se ve que el primer fichero tiene un indicador que dice que
debe mostrarse durante la instalacion. Ademas presenta las opciones OK y NO
para seguir con la instalacion o cancelarla.
El programa instalador se encarga de la tarea de presentar este texto, hacer
la pregunta, y recoger la respuesta.
No es posible solicitar ningun numero de serie, ni nada que se le parezca.

Los otros ficheros que empiezan por   !:\   indican que se le presentara al
usuario la posibilidad de instalarlo en distintas unidades de disco.
Esto suele ser:
E: para la tarjeta MMC, que es lo que yo voy a usar.
C: para la memoria interna no-volatil.

En nuestro ejemplo, no pide la unidad de destino 6 veces, sino que con la
primera vez le vale.
Existen otras posibilidades. Por ejemplo, una linea del tipo
C:\system\data\FExplorer.dat
siempre se guardara en la unidad C: . Esto es usado comunmente para ficheros
de configuracion, claves de autorizacion, y control de uso. Mas tarde
veremos un ejemplo, paciencia.

Asi que tras responder (3 veces !) a las confirmaciones de instalar la
aplicacion, la tenemos en
e:\system\apps\FExplorer\FExplorer.app

El fichero FExplorer.aif se puede abrir con la aplicacion SISTool by Alezz.
Vemos que contiene
AIF ID = 0x383A0010
App ID = 0xF17B1F10
1 string = "FExplorer"
2 iconos, con identificadores 000 (el dibujo) y 001 (la mascara)

Todo esto sirve para que el menu principal sea capaz de presentar un
icono, y el titulo de la aplicacion.


El fichero FExplorer.mbm se puede abrir con la aplicacion MBMTool by Alezz.
Vemos que contiene 22 dibujos, de los cuales la mitad son iconos, y la otra
mitad son las mascaras.

El fichero FExplorer.rsc se puede abrir con la aplicacion RSCTool by Alezz.
Si todavia no te has convencido de que este tipo es un maestro, no se a
que esperas.
Vemos que contiene 313 objetos, aglutinados en 92 grupos.
Los objetos son de 2 tipos:
-numeros enteros de 4 bytes.
-cadenas de caracteres, que van precedidas por un valor con su longitud.

Existen otros tipos, pero lo normal es encontrarse solo con estos dos.
Este fichero suele contener las palabras y frases que se usan en la
aplicacion.
Por ejemplo, si hay un menu con la palabra "Comprimir Memoria", es casi
seguro que esta en este fichero.
Es frecuente encontrarse que una aplicacion incluye varios
ficheros FExplorer.r01, FExplorer.r02, ... FExplorer.rXX
Cada fichero contiene las frases en un idioma distinto.
El fichero *.r01 se usa cuando instalas la aplicacion en Ingles.
El r02 sirve para Frances, r04 para espanyol, el r56 para Gujarati, del que
puedes obtener mas informacion en 
http://en.wikipedia.org/wiki/Gujarati_language
Por tanto el fichero *.sis incluye muchos lenguajes, pero solo uno de ellos
se instala en el movil.

Lo bueno es que este fichero es facil de modificar. Hay gente que ha
traducido aplicaciones ajenas para adaptarlas a su propio idioma. Si bien
esto no se puede considerar como un acto de crackear el programa, lo cierto
es que es mejor pedirle permiso al autor. Quizas se alegre e incluya la
traduccion en la siguiente version.
Mas interesante es saber que la forma de acceder a uno de tales ficheros
desde un programa Symbian es usar la funcion RResourceFile::OpenL

Para leer los datos dentro de este fichero se usa la clase
TResourceReader::Read_xxx

Para acelerar la carga de menus, Symbian definio un fichero de
extension *.rss
que se compila y se mete en el *.rsc y se lee de un golpe usando la funcion
CEikEdwin::ConstructFromResourceL(menu_ID);
Cada opcion dentro del menu tiene un identificador unico.

Este es un ejemplo de FCA00000.rss

RESOURCE MENU_PANE r_FCA00000_menu
    {
    items = 
        {
        MENU_ITEM {command = 0x0102;  txt = "HacerAlgo";},
        MENU_ITEM {command = 0x0103;  txt = "OtraCosa";},
        MENU_ITEM {command = 0x0104;  txt = "MuchoMas";},
        MENU_ITEM {command = EAknSoftkeyExit;   txt = "Exit";}
        };
    }

Hay otro detalle digno de mencionar: cada aplicacion tambien tiene un
identificador unico. En teoria hay que solicitarselo a la companyia Symbian,
pero es mas comun inventarse uno propio. Si coincide con el de alguna otra
aplicacion, mala suerte.
En particular mi aplicacion tiene el identificador 0xFCA00000

Para obtener el identificador de cada menu simplemente hay que
combinar ambos:
0xFCA00000 + 0x0102 = 0xFCA00102
Por lo tanto en el fichero FCA00000.rsc aparecen los bytes
02 01 0A FC
que son la representacion en little-indian de 0xFCA00102

En el programa habra una intruccion del tipo:
if(menu_elegido==0xFCA00102)
 {
 ......
 }

Este sera un buen punto de inicio para empezar a seguir el flujo del
programa.

Los programas Symbian solo funcionan en procesadores ARM, que usan un
lenguaje ensamblador mas simple que el que encuentras en un ordenador PC.
Para desensamblar los programas, la mejor herramienta que yo conozco es el
IDA-Disassembler. Conoce las instrucciones ARM y saca un listado muy limpio.
Por ejemplo me sorprendio que la secuencia de instrucciones
MOV R0, 0x77
ADD R0, 0x100

la muestra como
MOV R0, 0x177

haciendo que el listado sea mas comprimido que lo que sacan otros
desensambladores. Por favor soporta a sus creadores y compralo: es una
herramiente magnifica.

Una cosa a recordar es que los programas siempre aparecen desensamblados
a partir de la direccion 0x10000000.
Cuando se cargan en memoria se ejecutaran en cualquier otra direccion
de memoria, normalmente 0xFFF?0000 para los primeros 16 programas
que se ejecuten.

Como creo haber dicho en otro articulo, symbian es un sistema operativo
en el que los programas completan el link en tiempo de carga.
Lo explico: cuando compilas el programa que llama a una rutina del sistema
operativo, no sabes a priori en que direccion de memoria esta dicha rutina.
Solo sabes el nombre.
Asi que el programa compilado contiene una referencia a un indicador fijo.
Cuando quieras ejecutar el programa, el sistema operativo lo carga en
memoria, y arranca un cargador (second-phase loader) que ajusta las
direcciones de las rutinas usadas.

Vamos a verlo con un ejemplo:
Este es un trozo de un program escrito en lenguage C/C++ para symbian:
RFile myFile;
myFile.Replace(fileSession, "c:\\myfile", EFileWrite);

se traduce en codigo ensamblador en algo asi:
LDR     R1, [r0+X]      ; en algun sitio existe una referencia a fileSession
LDR     R2, =p_C_myFile ; puntero a un puntero al String "c:\\myfile"
MOV     R3, #0x200      ; EFileWrite es una constante que vale 0x200
BL      stub_RFile_Replace ; rutina que saltara a RFile::Replace, la cual
                           ; necesita 3 argumentos: R1, R2, y R3
......
p_C_myFile DCD C_myFile      ; puntero al String "c:\\myfile"
C_myFile   DCA "c:\\myfile"  ; String "c:\\myfile"

......
stub_RFile_Replace:
LDR     R12, =p_Replace__5RFileR3RFsRC7TDesC16Ui ; direccion que apunta
                                                 ; a la rutina destino
LDR     R12, [R12] ; carga el dato de dicha direccion
BX      R12        ; y salta
......
p_Replace__5RFileR3RFsRC7TDesC16Ui   DCD Replace__5RFileR3RFsRC7TDesC16Ui
Replace__5RFileR3RFsRC7TDesC16Ui     IMPORT Replace__5RFileR3RFsRC7TDesC16Ui
......

por pasos:
-primero se preparan los 3 argumentos necesarios para stub_RFile_Replace 
-luego se llama al stub
-el stub lee en Replace__5RFileR3RFsRC7TDesC16Ui la rutina a la que
 debe saltar
-este dato ha sido rellenado por el Sistema Operativo cuando ha
 cargado en memoria el programa

Visto de otro modo, la rutina stub_RFile_Replace es equivalente a:
int (void *)lista_funciones[];
int R12 = lista_funciones[index_p_Replace__5RFileR3RFsRC7TDesC16Ui];
(void *)funcion = *(R12);
call funcion(R1, R2, R3);


Si no lo has entendido bien, te recomiendo que consultes algun otro
documento en el que explique la carga dinamica de programas; es una
tecnica muy comun en sistemas operativos de disco.

Por eso es posible saber a cuales funciones llama un programa. Esto lo
aprovecha IDA y muestra algo asi:

10003C40 MOV  R0, R5
10003C44 BL   stub_DriveAndPath__C10TParseBase ; TParseBase::stub_DriveAndPath(void)
10003C48 ADD  R3, SP, #0x18

Aunque no sepamos lo que hace este programa en la rutina en 10003C40, sabemos
que llama a TParseBase::DriveAndPath(void), que es una funcion que retorna
la unidad y la ruta en la que esta instalado el programa.
A partir de aqui empieza la tarea de investigacion.

-----------------------------
Como ya es habitual, vamos a trabajar en un caso real.

En el movil SX1 de Siemens es posible actualizar uno mismo el firmware que
viene incluido de serie. No esta al alcance de cualquiera poder alterarlo
para que haga las cosas que uno quiere, pero hay un grupo llamado Z-TeAm
que ha hecho realmente muchos cambios.
En un telefono Symbian existe las unidades:
- Z: que contiene los programas. Es de solo lectura. Ocupa 16 Mb.
- E: que esta en la tarjeta MMC. Obviamente aqui se pueden copiar programas
- C: tambien es de lectura y escritura. Ocupa 4 Mb.
- A: que es de solo lectura. Teoricamente. Ocupa 4 Mb. Hay 1Mb libre

Aqui es donde esta lo bueno: el Z-TeAm ha conseguido que sea posible meter
programas en esta ultima unidad A: , aprovechando el espacio libre.
Pero no se puede escribir desde el propio telefono, sino desde un ordenador.
Basicamente uno tiene que crear una estructura de directorios similar a la
que quiere que vaya a A: , y convertirlo en un mega-fichero de 4 Mb.
Luego se mete en el movil.
La unidad A: contiene unos cuantos programas que no son imprescindibles.
Ademas se pueden meter en la memoria MMC.
Pero en A: queda espacio de sobra para instalar unos cuantos programas.

Uno de los programas mas utiles es el FExplorer 1.15 mencionado
anteriormente.
Asi que seria recomendable tenerlo en la unidad A para que siempre estuviera
accesible aunque cambie la tarjeta MMC.
El problema es que FExplorer se empenya en buscar el archivo de configuracion
en la misma unidad en la que esta instalado. Obviamente no le gusta que
este en A: porque no puede sobre-escribirlo.

La solucion es enganyarlo para que lo lea desde C: y no desde A: .

El archivo de configuracion se llama FEgen.ini
Cargamos FEXplorer.app en el desensamblador IDA y al cabo de 3 minutos
produce el codigo desensamblado.

La palabra "FEgen" la encuentro en:
100195B8 aFegen          unicode 5, <FEgen>,0

y un poco mas abajo, encuentro
100195D0 a_ini           unicode 4, <.ini>,0

busco referencias a estas direcciones:
10003C90 off_10003C90    DCD aFegen

que a su vez viene desde:
10003C74   ADD     R4, R4, #8
10003C78   ADD     R0, SP, #0x10
10003C7C   LDR     R1, =aFegen
10003C80   BL      s__7TPtrC16PCUs ; TPtrC16::TPtrC16(ushort const *)
10003C84   MOV     R0, R4

O sea, que llama a la funcion TPtrC16::TPtrC16 que segun el manual de
Symbian sirve para iniciar una cadena. No es de extranyar que esta rutina
tan comun se llame en 350 sitios distintos a lo largo del programa.

Un poco mas adelante hace:
10003CC0   LDR   R1, =a_ini
10003CC4   BL    s__7TPtrC16PCUs ; TPtrC16::TPtrC16(ushort const *)
10003CC8   MOV   R0, R4
10003CCC   MOV   R1, SP
10003CD0   BL    s_Append__6TDes16RC7TDesC16 ; TDes16::Append(TDesC16 const &)

que sirve para concatenar una cadena a otra. A mi me parece que vamos en
la direccion adecuada.
Ahora falta ver donde le ha antepuesto el nombre del directorio.
Para ello investigo el codigo antes de 10003C74 y me encuentro con:

10003C44   BL      stub_DriveAndPath__C10TParseBase
....
10003C58   BL      s_Copy__6TDes16RC7TDesC16

y la documentacion del API me confirma que TParseBase::DriveAndPath me
devuelve una cadena conteniendo la unidad y el directorio.

Por eso deduzco que el codigo original es algo asi:
String unidad_y_directorio;
String ruta_completa;

unidad_y_directorio = TParseBase::DriveAndPath();
ruta_completa.Copy(unidad_y_directorio);
ruta_completa.Append(String("FEgen");
ruta_completa.Append(String(".ini"));

Ahora, para conseguir eliminar la unidad de disco de la ruta, tengo que hacer
unidad_y_directorio = "C:\" + TParseBase::Path();

es decir, que no llame a TParseBase::DriveAndPath() ,
sino a TParseBase::Path();
lamentablemente no existe la rutina TParseBase::Path();

Pero la solucion mas rapida es hacer que no use en absoluto el nombre
del disco donde esta la aplicacion:

String unidad_y_directorio;
String ruta_completa;

unidad_y_directorio = TParseBase::DriveAndPath();
//ruta_completa.Copy(unidad_y_directorio);  // <--comentar esta linea
ruta_completa.Append(String("c:\FE");  // el archivo es c:\FE en vez de FEgen
ruta_completa.Append(String(".ini"));

En otras palabras: no uso la ruta original de la aplicacion, sino que
el archivo al final sera
c:\FE.ini

?Porque no he usado c:\FEgen ? Pues porque "FEgen" ocupa 5 caracteres, y por
tanto "c:\FEgen" ocuparia 8, lo que me obligaria a hacer hueco en el programa.
Recordar que estoy modificando el archivo binario, no el codigo fuente.
Cuando se altera un binario, no es facil hacer hueco en medio del programa.

Los cambios son:
.....
10003C58   NOP ; inicialmente era    BL s_Copy__6TDes16RC7TDesC16
.....
100195B8 aFegen   unicode 5, <c:\FE>,0   ; inicialmente era <FEgen>
.....

Para los que esten interesados en codigo binario, la instruccion
BL s_Copy__6TDes16RC7TDesC16
tiene codigo
394800EB

y la instruccion
NOP
tiene codigo
0000A0E1

Para probarlo, modifico FExplorer.app y lo transfiero al movil. Inicio la
aplicacion y confirmo que ha creado el fichero c:\FE.ini
Y esta todo listo para meterlo en la unidad A: tal como queria conseguir.

Como veis, no es mucho mas distinto que desensamblar programas para PC.

------------------------------------
Al principio he comentado la estructura de un fichero .sis de instalacion.
Ahora me gustaria anyadir que hay algunas posibilidades mas complejas.
Una de ellas es que se pueden instalar distintos ficheros dependiendo de:
-fabricante: Ericsson, Motorola, Nokia, Panasonic, Psion, ...
-modelo
-velocidad de la CPU
-memoria
-numero de teclas
-numero de luces LED
-tamanyo de pantalla
-lenguajes disponibles
....

Otra funcionalidad es que se puede ejecutar la aplicacion tras la instalacion.
Esto es util cuando el programador desea:
-crear una serie de directorios
-verificar que existe un cierto fichero
-solicitar un codigo de proteccion o numero de serie
-conectarse a una pagina web para obtener algun otro dato
-enviar un SMS para informar al programador
.....
y en caso de que alguna condicion no sea correcta, se devuelve un codigo
de error al instalador, que automaticamente desinstala el programa.

La mayoria de los programas contienen unicamente:
-la aplicacion principal XXX.app
-el icono y nombre del programa en XXX.aif
-los dibujos que usa XXX.mbm
-los sonidos XXX.mid
-los mensajes en XXX.rsc , XXX.r01, XXX.r02 , ...
-archivo de configuracion XXX.ini o XXX.cfg
-ayuda o notas en XXX.hlp o XXX.txt

Algunos programas mas complejos incluyen:
-librerias XXX.dll
-programas servidores XXX.exe para tareas criticas
-reconocedores XXX.mdl
-bases de datos XXX.db o XXX.dat

Son particularmente utiles los ficheros XXX.mdl que se ejecutan cuando se
inicia el movil. Si estas pensando en crear un antivirus (o un virus) , un
protector de pantalla (o un sniffer de teclas), o algo que se parezca a
un LKM (Loadable Kernel Module) debes mirar en esta direccion.

------------------------------------
Dado que este articulo explica como modificar aplicaciones Symbian, voy a
explicar otra tecnica.
Por si no ha quedado claro lo repito otra vez: cada programa, tal como esta
en el disco (MMC o C:), contiene solo referencias a rutinas del sistema
operativo. Cuando se carga en memoria, esas referencias se convierten en
las direcciones especificas de las rutinas. Estas direcciones son distintas
segun el modelo de movil, e incluso segun la version del Sistema Operativo.

Por ejemplo, para el Siemens-SX1 existen mas de 20 versiones distintas de
sistema operativo, segun el idioma con que han sido fabricados: la
version 15 en Espanyol y la version 15 en Ruso tienen distintas direcciones
de rutinas.

Por cada rutina externa que es invocada desde el programa, debe de haber
un "lanzador" hacia ella. Eso se conoce como Stub.

Aqui hay un par de ejemplos:

....
;---------------------------------------------------------------------------
stub_CCoeControl::SizeChanged(void)
 LDR     R12, =SizeChanged__11CCoeControl
 LDR     R12, [R12]
 BX      R12
 off_1001F674  DCD SizeChanged__11CCoeControl ; CCoeControl::SizeChanged(void)
;---------------------------------------------------------------------------
stub_CCoeControl::PositionChanged(void)
 LDR     R12, =PositionChanged__11CCoeControl
 LDR     R12, [R12]
 BX      R12
 off_1001F684  DCD PositionChanged__11CCoeControl ; CCoeControl::PositionChanged(void)
;---------------------------------------------------------------------------
....

Si un programa llama a 200 rutinas externas (creeme, 200 es un
numero normal) entonces hay 200 stubs.

Vamos a analizar uno cualquiera de estos stubs.
-Siempre usa 3 instrucciones y 1 dato ; cada uno de estos elementos
 ocupa 4 bytes, lo cual da 16 bytes
-todos hacen lo mismo; simplemente cambia la direccion desde la que obtienen
 la direccion de la rutina de destino. (Si, es una direccion que apunta
 a otra direccion)
-usan el registro R12, sin importarles lo que hubiera antes. Esto parece
 indicar que R12 es realmente de usar y tirar.


Si recordais otro articulo anterior para el Siemens S45, yo contaba que
seria util hacer un traceador para saber cuales rutinas eran llamadas
por un programa. Vamos a ver si tambien lo puedo hacer para Symbian.

El objetivo es definir una rutina que se llame cada vez que pase algo
interesante, y que diga de donde viene, a donde va, y que datos usa.
?Como se define "sucede algo interesante"? Pues muy facil: cualquier
llamada al sistema operativo es interesante.

Puedo interceptar cada uno de los stubs: en lugar de
stub_XXX(void)
 LDR     R12, =XXX
 LDR     R12, [R12]
 BX      R12
 off_XXX4  DCD XXX ; XXX

lo transformo en
stub_XXX(void)
 LDR     R12, =XXX
 LDR     R12, [R12]
 B       mi_debugger  ; <---- esta es la linea que cambio
 off_XXX4  DCD XXX ; XXX

Hay que tener cuidado en varios aspectos:
1-la rutina   mi_debugger  no puede cambiar ningun registro
2-debe finalizar con     BX  R12   , como en el original
3-el programa original debe modificarse para incluir esta rutina debugeadora.
  Por tanto hay que buscar un hueco libre en algun lugar del programa; por
  ejemplo un string que no se use.
4-debido a la arquitectura ARM, la rutina mi_debugger debe estar en el
  mismo segmento de memoria que stub_XXX

La primera restriccion es facil de cumplir: solo hay que guardar
temporalmente en la pila los registros que necesitemos usar, y al
final hay que recuperar los valores originales.
Lo segundo es trivial.
La tercera condicion obliga a usar un debugger pequenyo. Pero hay un
truco: podemos saltar a cualquier otra rutina. Lo malo es que hay que
actuar manteniendo la cuarta regla.

Ahora, olvidate por un momento de que los programas se cargan en direcciones
de memoria virtuales: suponte que existe una direccion fija (llamada
mi_debugger_grande) y que cualquier programa puede saltar a ella.

(Aviso: el siguiente parrafo solo lo entenderas si sabes de arquitectura ARM)
Para saltar a esta rutina podemos usar la instruccion:
- B (branch) , pero solo permite saltar al mismo segmento de memoria, es
  decir, esta limitado a saltos de maximo 0xFFFF bytes
- BL (branch location), que admite saltos largos pero modifica el
  registro LR
- BX (branch extended), que necesita un registro, en la forma   BX Rb

Usare este tercer modo. Ahora necesito un registro Rb que pueda corromper
sin alterar el programa, por ejemplo R11 porque no he visto ningun programa
que lo use. Es cierto que lo usa el kernel a veces, pero no interfiere.

Entonces queda:
mi_debugger:
 LDR   R11, =mi_debugger_grande
 BX    R11
 off_XXX3  DCD mi_debugger_grande

Y ahora es cuando viene la sorpresa: de verdad existe tal direccion
de memoria ! De hecho existen muchas, por ejemplo 0x85740000.
La explicacion vendra en un parrafo posterior.

Por tanto queda (en pseudo-codigo)
org 0x85740000
mi_debugger_grande:
 guarda_registros
 dump_registros
 dump_direccion_origen
 dump_direccion_destino
 restaura_registros
 BX R12

Si te interesa de verdad este debugger, sigue leyendo.

Para guardar los registros usare la pila. Seguro que modificare los registros
R1, R2, ... R7 asi que los puedo almacenar todos con una unica instruccion
STMFD   SP!, {R1-R7}   ; equivalente a  push R1, push R2, ... push R7

Decido que para almacenar los datos interesantes usare la direccion de
memoria 0x85750000 y siguientes:
LDR R7, =0x85750000

El primer dato de esta zona sera un contador que me dice cuantos datos he
guardado, y me sirve para saber donde meter el siguiente.
LDR R6, [R7]

Ahora debo incrementarlo. Cada vez que se invoca al debugger grabare 8 datos
de 4 bytes. Asi que el contador se incrementa en 32 cada vez.
En hexadecimal 32 vale 0x20
ADD R6, #0x20

y lo vuelvo a meter en 0x85750000
STR R6, [R7]

Ahora debo apuntar al primer byte que esta libre:
ADD R7, R6

y empiezo a meter los datos; primero los argumentos R1, R2, R3 enviados a
la rutina:
STR R1, [R7+#0x00]
STR R2, [R7+#0x04]
STR R3, [R7+#0x08]

El registro R0 tambien es util
STR R0, [R7+#0x0C]

Ahora la direccion origen. En Symbian, las rutinas se llaman con la
instruccion
BL stub_XXX
que hace que el registro LR almacene la direccion a la que se debe retornar.
Por eso lo puedo "dumpear" haciendo
STR LR, [R7+#0x10]

La direccion destino es justamente R12
STR R12, [R7+#0x14]

Y ahora me queda hueco para otros 2 registros: uno es la pila
SP (Stack pointer).
Pero para obtener el valor original debo substraer los 7 datos R1-R7 que he
metido al principio, que ocupan 4 bytes cada uno
MOV R1, SP
SUB R1, #0x07*4
STR R1, [R7+#0x18]

y el otro es el registro PC, que contiene los flags (N, Z, V, I).
El resto de los flags no interesan, pero aun asi los guardo tambien
STR PC, [R7+#0x1C]

recupero los registros de la pila:
LDMFD   SP!, {R1-R7}   ; equivalente a  pop R7, pop R6, ... pop R2, pop R1

y salto a donde debo saltar
BX R12


Para poner todo el tinglado en marcha necesito varios programas:
-Uno en ensamblador ARM con las 20 instrucciones anteriores. Lo compilo
 con GCC-ARM y me genera un mini-fichero de 20*4 bytes.
 Al resultado lo llamo 0x85740000.bin
-Otro en el PC que transfiera este fichero al movil. Dado que tengo
 infrarrojos en el movil y en el ordenador, uso el IrFtp de Windows.
-Otro en el movil que cargue 0x85740000.bin en la direccion 0x85740000 .
 Este programa lo hago en Symbian. Lo explicare en un parrafo posterior
-El programa victima, adecuadamente parcheado
-para eso me hago un programa parcheador. Basicamente:
 -busca
     LDR     R12, [R12]   ; bytes 00C09CE5
     BX      R12          ; bytes 1CFF2FE1
 -y los substituye por
     LDR     R12, [R12]   ; bytes 00C09CE5
     B       mi_debugger  ; bytes xyzt00EA ,donde xyzt depende de donde puedo
                                            meter mi_debugger
 -busca un hueco libre donde escribir el lanzador
   mi_debugger:
    LDR   R11, =0x85740000
    BX    R11
    off_XXX3  DCD 0x85740000
 -como ocupa 3 instrucciones, necesito 3*4 bytes. Estos 12 bytes los localizo
  yo a mano. Normalmente lo que hago es machacar una zona del programa que
  me parezca que no se usa.

-Otro programa que vuelca la traza generada a partir de 0x85750000
-Para transferirlo al PC uso de nuevo el IrFTP
-Hago otro programa para visualizar estos datos. Las rutinas "destino" son
 del sistema operativo, por lo que puedo darles nombre. Lo unico que
 necesito es saber la direccion donde estan almacenadas cada una.
 Las rutinas "origen" son del programa victima, y obviamente no puedo saber
 sus nombres. En esto consiste el arte del desensamblado, ?no?

--------------------------------
Este es el programa Symbian que mete el fichero 0x85740000.bin en la
direccion 0x85740000

RFs fileSession;
TInt open_result, direccion, valor;
TBuf8<4> four_bytes;
_LIT(x85740000_bin,"c:\\0x85740000.bin");

fileSession.Connect(); // conecta con el servidor de archivos
open_result=filep.Open(fileSession, x85740000_bin, EFileRead);
                                     // abre el fichero 0x85740000.bin

if(open_result==KErrNone) // si todo ha ido bien ...
{
 direccion = 0x85740000;
 for(i=0;i<20*4;i+=4) // bucle de 20 instrucciones
  {
  filep.Read(four_bytes); // cada instruccion ocupa 4 bytes, que
                                  //   meto en un array
  valor=four_bytes[0]%256 // y lo meto en un TInt, que ocupa 4 bytes
      + (four_bytes[1]%256)*256
      + (four_bytes[2]%256)*256*256
      + (four_bytes[3]%256)*256*256*256 ;
  Mem::Copy(&valor, direccion, sizeof(TInt)); // lo meto en memoria
  direccion+=4; // y salto a la siguiente direccion
  }
}


El programa inverso que mete las tramas en un fichero es similar, usando 
como origen la direccion 0x85750000 .

-------------------------
Como ejemplo, voy a modificar el programa Spectrian V1.51 by White Cloud.
Esta aplicacion es un emulador de ZX-Spectrum para telefonos moviles.
Lo puedes obtener desde www.whitecloudsoftware.com
Se compone de varios ficheros, y el programa se llama   Spectrian.app

Al ser un programa comercial, necesita un numero de serie, o de lo contrario
caduca a los 30 dias. Simplemente por diversion, voy a intentar eliminar esta
limitacion. Una vez mas te emplazo a pagar por el software que uses.

Primero hay que ver como actua el programa: lo arranco, y veo que si no esta
registrado, aparece un mensaje indicando el modo de registrarlo (pagando,
claro).
Este mensaje permanece durante 3 segundos, que se que hay que transformarlo
en milisegundos, dando la cifra 3000000 , o sea, 0x2DC6C0.


Desensamblo con IDA, y busco los sitios donde se usa el dato 0x2DC6C0.
Lo encuentro en la rutina 1000262C.
Cambio el valor a 1 segundo con mi editor hexadecimal, transfiero el programa
parcheado, y ahora efectivamente el mensaje aparece solo durante 1 segundo.
Pero con esto no consigo eliminarlo.

Asi que voy a usar mi debugger.

Esta aplicacion usa (10020EB8-1001EBB8)/4 = 0x8C0  stubs, desde 

1001EBB8 ; CBase::newL(unsigned int)
1001EBB8         LDR     R12, =newL__5CBaseUi
1001EBBC         LDR     R12, [R12]
1001EBC0         BX      R12
1001EBC4 off_1001EBC4    DCD newL__5CBaseUi
.....
hasta
.....
10020EB8  ; PlpVariant::GetMachineIdL(TBuf<128> &)
10020EB8         LDR     R12, =GetMachineIdL__10PlpVariantRt4TBuf1i128
10020EBC         LDR     R12, [R12]
10020EC0         BX      R12
10020EC4 off_10020EC4    DCD GetMachineIdL__10PlpVariantRt4TBuf1i128

Parcheo estas 2240 rutinas haciendo que salten a la direccion
libre 0x10022550
org 0x10022550
mi_debugger:
 LDR   R11, =mi_debugger_grande
 BX    R11
 off_XXX3  DCD mi_debugger_grande
 mi_debugger_grande  DCD 85740000

Y en la direccion 0x85740000 coloco mi debugger.
Pongo en marcha el programa victima, y una vez que ha salido el mensaje
diciendo que no esta registrado, vuelco la memoria a partir de 0x85750000,
que es donde mi debugger ha escrito la traza de las rutinas interceptadas.

Por ejemplo, una de tales trazas me dice

 R0=00401628  R1=004037C4 R2=00000004 R3=80000368
R12=502801F0  R4=00000000 LR=FFFD3934 SP=00403844

?Como se interpreta esto?
Lo primero es el dato LR=FFFD3934 que indica la direccion del programa desde
el que se ha llamado a la rutina debugeada.
El desensamblador IDA cree que todos los programas se ejecutan a partir de
la direccion 0x10000000.
Esto no es del todo correcto, pues el cargador de Symbian se encarga de
buscar una direccion de memoria libre en el propio telefono. Debido al
sistema de memoria paginada, esto suele ser 0xFFF?0000 , en
nuestro caso 0xFFFD0000
Por tanto
LR=FFFD3934
equivale a la direccion 0x10003934 en el desensamblado.
Vamos a mirar el codigo en esa direccion:

10003928    MOV     R2, #4
1000392C    BL      sub_1001EE78
10003930    ADD     R0, SP, #0x148
10003934    BL      sub_10020EB8  <---- aqui lo hemos interceptado
10003938    MOV     R4, #0
1000393C    ADD     R5, SP, #0x40

Y tambien
10020EB8  ; PlpVariant::GetMachineIdL(TBuf<128> &)
10020EB8         LDR     R12, =GetMachineIdL__10PlpVariantRt4TBuf1i128
10020EBC         LDR     R12, [R12]
10020EC0         BX      R12
10020EC4 off_10020EC4    DCD GetMachineIdL__10PlpVariantRt4TBuf1i128

Combinando con
R12=502801F0
esto quiere decir que
la rutina 
PlpVariant::GetMachineIdL(TBuf<128> &)
esta (en mi modelo de movil) en la direccion 0x502801F0 y Spectrian la
invoca desde 10003934 .
En otros modelos de moviles, estara en otra direccion.
Mas tarde explicare una consecuencia importante de esto.

Siguiendo con la explicacion de la traza, la rutina
PlpVariant::GetMachineIdL
necesita un argumento
TBuf<128> &
que combinado con
R1=004037C4
significa que la variable usada como argumento esta en la direccion
004037C4
Si tuviera un debugger en condiciones podria ver el valor de esta variable.
Lo importante es saber que el segmento
0x00400000
contiene los datos del programa en ejecucion, es decir, toda la zona de
variables completa.

Asimismo, R0=00401628  indica que la zona de variables locales a esta rutina
esta en la direccion 00401628.

El valor
R2=00000004
es consistente con la linea
10003928    MOV     R2, #4

Por hacer un pequenyo resumen:
-valores de   0x0040???? indican variables del programa
-valores de   0x50?????? indican direcciones de rutinas del sistema operativo
-valores de   0xFFF????? rutinas del programa, equivalente a 0x100????? en IDA

Ya que tenemos las trampas preparadas, vamos a ver que atrapamos.

En el programa encuentro la palabra "RegCode2" que parece bastante sugestiva:
1002254C aRegcode2       unicode 8 , <RegCode2>,0

Esto es tipico de Symbian: cada palabra es en realidad una estructura
de datos:
-el primero (ocupa 4 bytes) es la longitud de la palabra
-el segundo es la palabra, donde cada letra ocupa 2 bytes en formato unicode
-el ultimo (2 bytes) es 00 00 , indicando el fin de cadena

A lo que iba: IDA me dice que esta palabra esta referenciada desde
10003384  LDR   R1, =Regcode2
10003388  ADD   R0, SP, #0x28
1000338C  SUB   R0, R0, #4
10003390  BL    Compare__C7TDesC16RC7TDesC16 ; TDesC16::Compare(TDesC16 const &)
10003394  CMP   R0, #0
10003398  BNE   loc_100033B8

O sea, que en
[SP, #0x28]
hay un puntero, y se compara con la palabra "Regcode2"
Si no son iguales, salta a loc_100033B8

Si son iguales, se hace
...
100033AC    BL      Val__6TLex16Rl ; TLex16::Val(long &)
100033B0    LDR     R3, [SP,#0x59C+var_59C]

que sirve para transformar una cadena del tipo "1234" en su valor
numerico 1234.

Bueno, parece que esta es una buena rutina para investigar.
Asi que busco en mis trazas donde se ha llamado a esta rutina
TLex16::Val(long &)

A partir de ahi, con el desensamblado en una ventana, y el traceado en otra,
me hago una idea de lo que hace el programa, y dispongo de la posibilidad de
analizarlo off-line.

Para completar este parrafo, dire que hay un fichero
Spectrian.prf
que contiene la cadena
Regcode2=xxxxxxx

y la rutina previamente analizada se encarga de leerla usando
TFileText::Read(TDes16 &)

 
Mas tarde, se llama a
PlpVariant::GetMachineIdL(TBuf<128> 
para averiguar el numero de serie unico del movil.

Luego se calcula un codigo y se compara con xxxxxxx usando
TDesC16::Compare(TDesC16 const &)const

Si la comparacion no es correcta, entonces se hace:
10000A30     MOV R5, #0
mientras que si el programa esta satisfactoriamente registrado entonces
10000A24     MOV R5, #1
saltando en ambos casos a
sub_10003824
donde se verifica este valor.

Si es distinto de 0, entonces no aparece la pantalla de registro.

Resulta trivial parchear el programa para que evite esta ultima comparacion,
y siempre se piense que el progama esta registrado.
Ahora, a jugar al Saimazoom !


---------------------
Otro programa muy util para Symbian es TomTomCityMaps.
Contiene planos de varias ciudades del mundo. Existe otras versiones
TomTomMobile y TomTomNavigator pero ocupan mucha mas memoria.

El problema con CityMaps es que no funciona en el SX1.
Puedes iniciar el programa, pero se queda en la pantalla de inicio.
Cuando pulsas una tecla da un error, aunque no finaliza el programa.

No tengo ni idea de si podre arreglarlo, pero al menos lo intentare.

La estrategia es la misma: interceptar todas las rutinas para ver lo que
hacen.
Cuento con la ventaja de que el programa funciona en un movil Nokia, por lo
que puedo instalar el programa parcheado en ambos. Si una rutina devuelve un
resultado totalmente diferente (mas alla de lo razonable) entonces habra que
investigar en detalle dicha rutina.

El programa llama a (100624D0-1005F7D4)/4 = 0x0B3F rutinas del sistema
operativo, y hay 12 bytes libres en 100634A0, suficientes para poner
mi_debugger.

Arranco el programa, y en cuanto da el mensaje de error, vuelco la memoria a
partir de 0x85750000.

Una de las ultimas rutinas ejecutadas ha sido:

 R0=0040F838  R1=00407304 R2=100059BE R3=80000368
R12=5015A6DC  R4=00000000 LR=FFF548F0 SP=0040873C

O sea, que se llama desde FFF548F0 (equivalente en IDA a 100048F0)
a la rutina en 5015A6DC.
Segun IDA, la rutina es CListBoxData::Reserved_2(void)

Esto es un poco raro. El codigo desensamblado que precede a 100048D8 no
contiene llamadas a rutinas relacionadas con la clase CListBoxData , sino
que son llamadas a AVKON , por lo que me extranya que se llame a una rutina
que, ademas, tiene el extranyo nombre "Reserved_2".

El desensamblado es:
100048DC       MOV     R1, R0
100048E0       MOV     R6, #0
100048E4       ADD     R4, SP, #0x2C
100048E8       MOV     R0, R4
100048EC       LDR     R2, =(loc_100059BC+2)
100048F0       BL      sub_10060F34 ; CListBoxData::Reserved_2(void)
100048F4       MOV     R0, R4
100048F8       BL      sub_100617F4 ; TRect::Width
100048FC       ADD     R1, SP, #0x1C
10004900       STR     R0, [SP,#0x98+var_7C]
10004904       STR     R6, [R1,#4]
10004908       MOV     R0, R5
1000490C       BL      sub_10061804 ; TSize::TSize


Tambien hay que fijarse en que justo antes de llamar la rutina en 100048F0
se establecen los argumentos R0, R1 y R2, lo cual no es consistente con que 
CListBoxData::Reserved_2(void)
no acepte argumentos.

Esto me hace sospechar que IDA no ha desensamblado bien la rutina.
La manera de comprobarlo es mirar la rutina que hay en R12=5015A6DC

Lo he mencionado en otro articulo, pero merece la pena repetirlo: yo tengo un
listado completo de las direcciones de las rutinas del mi movil Siemens-SX1.
No tengo el codigo fuente de Symbian, pero se el nombre de cada rutina, y
con eso y un poco de imaginacion me hago una idea de su uso.

En particular miro R12=5015A6DC y descubro que es
CPeriodic::Start(TTimeIntervalMicroSeconds32, TTimeIntervalMicroSeconds32, TCallBack)
y no CListBoxData::Reserved_2(void) como IDA me habia dicho.

Esto tiene mejor pinta. Esta rutina admite 3 argumentos, y el tercero es la
direccion de una rutina que se llamara cuando transcurra el tiempo
establecido.

En mi caso esta rutina CallBack se define en
100048EC       LDR     R2, =(loc_100059BC+2)

El codigo
100059BC     MVN     R7, #0
100059C0     LDR     R1, [R5,#0xA0]
100059C4     ADD     R2, R4, R4,LSL#1
100059C8     RSB     R2, R4, R2,LSL#3

parece ciertamente una rutina, pero hay algo intrigante:
?Porque se llama a loc_100059BC+2 ?
Esto significa saltar en medio de la instruccion
MVN     R7, #0
y eso no es posible.
O bien salta a 100059BC, o a 100059C0. Nunca a 100059BC+2

En la arquitectura ARM, las instrucciones estan siempre en direcciones
multiplo de 4. Al menos eso es lo que dice el manual de ARM.

Lo que me extranya es que funcione en un Nokia. Tras posteriores
investigaciones concluyo que el Nokia siempre redondea las direcciones hacia
el multiplo de 4.
Pero el SX1 no lo hace.

Asi que el cambio es evidente: en 100048EC debe apuntar a loc_100059BC en
vez de loc_100059BC+2

Hago el cambio, y el programa ahora funciona ! Ya puedo ir a Valencia sin
temor a perderme por sus calles.

-------------
Como he dicho antes, cada modelo de movil tiene las rutinas del sistema
operativo en direcciones de memoria distintos. La carga dinamica de programas
convierte las direcciones indexadas en direcciones reales, y IDA es capaz de
interpretarlas, aunque a veces se equivoque.

Mi listado del SX1 incluye mas de 30.000 rutinas del sistema operativo,
aunque posiblemente menos del 80% son usadas por algun programa.

En el movil existe una tabla que contiene las direcciones de todas las
rutinas.
En el SX1 esta tabla esta en 0x50F00000 y llega hasta 0x50F25000 , haciendo
un total de 40.000 rutinas.

En el Nokia N70, van desde 0x500FF000 hasta 0x50130000, unas 50.000 rutinas.

Si cambiamos en la ROM la direccion de esta rutina, podemos hacer que salte a
una rutina propia. En los moviles Siemens es posible actualizar la memoria
uno mismo. En los Nokia supongo que tambien, aunque creo que hace falta un
cable especial.

Sea la funcion 
CCoeControl::SetDimmed(int)
que en mi SX1 esta en la direccion 0x5065C93C, referenciada desde 0x50F16340

que sirve para ocultar(1) o mostrar(0) un menu.

Sin duda, se llamara haciendo
LDR     R12, =SetDimmed__11CCoeControli
LDR     R12, [R12]
BX      R12
off_10000F1C    DCD SetDimmed__11CCoeControli

Para saber donde esta ubicada esta rutina en el Nokia N70, hago un programa
en Symbian que oculta el menu. Lo parcheo con mi debugger e intercepto la
llamada a CCoeControl::SetDimmed(int)
Miro el registro R12, que contiene la direccion real de la rutina, y
averiguo que esta en 0x50787148


Supongamos que queremos que nunca se oculten los menus en ninguna aplicacion.
Obviamente puedo parchear la rutina 5065C93C (o 50787148 en el N70), pero es
mas flexible hacer:
-hacer que 0x50F16340 no apunte a 0x5065C93C, sino a 0x5071BE90
-buscar un espacio libre en la ROM, por ejemplo en 0x5071BE90
-desensamblar la rutina en 5065C93C
-modificarla a mi gusto, es decir, haciendo que no considere el primer
 argumento, sino que siempre muestre el menu
-compilarla usando el GCC-ARM o el compilador Kiel
-meter el codigo generado en la direccion 0x5071BE90

Esto me permite modificar el sistema operativo a mi gusto, siempre que sea
capaz de entender lo que hace la rutina parcheada, claro.

---------------------------------------------
Uno de los problemas mencionados es que IDA no es siempre capaz de entender
correctamente las llamadas a rutinas externas.

Un programa Symbian de tipo APP contiene una cabecera llamada E32ImageHeader
o TRomImageHeader definido en el SDK en e32rom.h , definiendo los parametros
del programa, tales como version, fecha de construccion, tamanyo de la pila,
numero de librerias usadas, y nombres de tales librerias.

Por cada libreria hay una lista de las funciones usadas dentro de ella.

Por ejemplo, hago un programa   prueba.app   que llama a
TFindLogicalChannel::Next(TFullName& aResult)
que segun la documentacion del SDK, esta declarado en
e32std.h
y tengo que linkar con la libreria 
euser.lib
que usara
euser.dll

Por eso IDA muestra:
; Segment type: Externs
....
; Imports from EUSER[100039e5].DLL
....
IMPORT Next__19TFindLogicalChannelRt4TBuf1i256
....

Vemos que incluye las palabras  TFindLogicalChannel  y  Next  pero ?que
son todos esos numeros?
Pues son los tipos de argumentos. Por ejemplo, una longitud de TBuf se
llama "i1".

Asi que empezando por el final:
TBuf1i256
quiere decir que el argumento recibido es
(TBuf<256> &)

que es lo mismo que 
TFullName& aResult

Luego, Rt4 es un puntero a TBuf .

Despues, _19T significa que es un metodo publico de la
clase TFindLogicalChannel.

En realidad esto se puede deducir de los ficheros *.h del SDK.

Como IDA no es capaz de entender los argumentos ni los datos de salida,
presenta el nombre largo, y eres tu el que tiene que interpretarlos.

Ahora bien, la palabra "TFindLogicalChannel" no esta dentro de prueba.app ,
asi que la pregunta es ?de donde los saca IDA ?

Si miras el programa   prueba.app   en binario veras que
Next__19TFindLogicalChannelRt4TBuf1i256
esta representado por los bytes
0xFC020000
que pasados a little-indian son
0x000002FC
o sea 764 en decimal.

Ahora vas al directorio del SDK donde tengas
euser.lib
que en mi caso es
C:\Symbian\6.1\Siemens\SX1\bin\epoc32\release\armi\urel
y haces
ar -xv euser.lib ds00764.o

el cual extrae de la libreria euser.lib el fichero ds00764.o 
Dentro de el encuentras la palabra
Next__19TFindLogicalChannelRt4TBuf1i256
como era de esperar.

Asi que IDA debe tener en algun sitio una lista que le dice que
la liberia euser.lib contiene la rutina 0x000002FC y se llama
Next__19TFindLogicalChannelRt4TBuf1i256

Y algunas de las rutinas no contienen el nombre correcto. Por eso se
confunde con alguna rutinas.
Lamentablemente no he encontrado esta lista en IDA, asi que supongo que
esta comprimido.

Pero lo que si puedo hacer es ayudarle:
1-dejo que desensamble el programa (quizas con algun error)
2-lo exporto a un fichero de texto
3-extraigo la zona de rutina importadas
4-miro las librerias, ej. user.dll
5-miro las funciones, ej. 0x000002FC
6-lo paso a decimal: 764
7-extraigo la funcion 764 de user.lib usando "ar"
8-saco el nombre de la rutina desde el fichero extraido ds00764.o
9-saco los nombres de los argumentos con la utilidad   dumpbin
10-los meto en un fichero prueba.idc
11-le digo a IDA que re-lea los nombres de las rutinas desde prueba.idc

Para los pasos 7-9 sigo las instrucciones de Mika Raento en
www.cs.helsinki.fi/u/mraento/symbian/reverse.html
que basicamente explica como obtener los nombres de los argumentos (proceso
conocido como "demangling").

Tambien uso este procedimiento para analizar el listado producido
por mi_debugger. Recordar que
R12 vale la rutina Symbian que es invocada
LR  es la rutina invocante

Mencionar que el SDK incluido en IDA 4.9 permite arreglar estos fallos y
regenerar el archivo que contiene la lista de funciones externas.
Pero esto lo dejo para otro articulo en el que contare cosas sobre IDA.

---------------------------------------------
?Que se puede hacer con esta metodologia?
Uno de los parches que mas me ha gustado hacer es cambiar la unidad Z: por C:
Me explico: las aplicaciones internas del movil estan en el disco Z:, que es
de solo lectura (se pueden cambiar en el SX1 usando un program especial y
re-escribiendo la flash, pero es un rollo hacer esto).
Estas aplicaciones usan ficheros con datos que estan tambien en Z:
Por ejemplo, la aplicacion del reloj (Clock.app) usa unos dibujos que
estan en
Z:\System\Data\Clock.mbm

Si no te gustan estos dibujos, no puedes poner otros.

Pero si consiguiera que busque
C:\System\Data\Clock.mbm
en vez de
Z:\System\Data\Clock.mbm
entonces podria cambiar los dibujos, ya que C: es de lectura y escritura.

?Como se sabe donde buscar?
En principio, la aplicacion Clock.app es la que decide donde estan los
dibujos que va a usar. Normalmente se calcula el directorio donde ella misma
esta instalada (Z:\System\Data\Clock.app) y los busca en su mismo directorio.

Otras veces, sin embargo, incluye la ruta completa, es decir, que
Z:\System\Data\Clock.app
contiene la palabra
Z:\System\Data\Clock.mbm

Es este caso solo hay que parchear la memoria flash usando la unidad C:  , es
decir, en el fichero Z:\System\Data\Clock.app hay que reemplazar
Z:\System\Data\Clock.mbm
por
C:\System\Data\Clock.mbm

Esto es lo que hacen muchos de los parches. Lo malo es que sirve solo para
este programa Clock.app y este fichero Clock.mbm en concreto.

Seria mas flexible hacer un metodo generico.

La manera de abrir un archivo es llamando a la rutina
RFile::Open(RFs &, TDesC16 const &, unsigned int)
donde el segundo argumento es el nombre del fichero, incluyendo la unidad de
disco y el directorio.

Esta rutina esta en 0x50195C1C, referenciada desde 0x50F03C7C
Asi que solo tengo que parchear esta funcion:
-si el nombre del fichero comienza por "Z:" entonces:
 -sustituyelo, poniendo C: al principio
 -busca
 -si no lo encuentra, busca el original (en Z: ) . Devuelve el resultado
 -si lo encuentra, devuelve el resultado (exito)
-si no, llama a la rutina original sin cambiar nada

En lenguage C++/ASM :

org 0x50F03C7C
call mi_RFile::Open       // el original hace call 0x50195C1C

mi_RFile::Open(RFs & mi_RFs, TDesC16 const & mi_archivo, unsigned int mi_flag)
{
TDesC16 & mi_archivo_en_C;
if(mi_archivo.StartsWith("Z:"))
 {
 mi_archivo_en_C=mi_archivo.Replace("Z:", "C:");
 result = original_RFile::Open(mi_RFs, mi_archivo_en_C, mi_flag); // en 0x50195C1C
 if(result<>KErrNone)
   return original_RFile::Open(mi_RFs, mi_archivo, mi_flag);
 else
  return result;
 }
else
 {
 return original_RFile::Open(mi_RFs, mi_archivo, mi_flag);
 }
}

Obviamente esta idea no es nueva: cualquier rootkit de PC en Linux o Windows
hace esto.

No solo he aumentado la flexibilidad; ahora un monton de ficheros no se
obtienen desde Z: sino desde C:  , lo cual libera espacio que puedo usar
para mis propias rutinas.
Es mas, puedo extender esta rutina para que me diga cuales son los ficheros
que se intentan abrir.
Cuando cualquier aplicacion abra un fichero, yo lo sabre. Un sniffer para
moviles similar a Filemon (www.sysinternals.com).

-------------
Hay una aplicacion de pago llamada SystemExplorer by Justek (www.justek.us)
que permite trabajar con ficheros. La diferencia con FExplorer es que puede
mostrar el contenido de ficheros con formato de base de datos.

Por ejemplo el fichero c:\system\data\cdbv2.dat es una base de datos.

Este fabuloso programa (ayuda a sus autores ! ) tiene una proteccion para que
solo se pueda usar durante 15 dias. Luego caduca.

Gracias al parche anterior averiguo que uno de los ficheros que abre es
C:\system\data\lm2004.dat

Desensamblo el programa SystemExplorer.app y veo que efectivamente hace algo
con este fichero.

Asi que cierro el programa, borro el fichero lm2004.dat , lo inicio de
nuevo, y veo con satisfaccion que me permite usarlo durante otros 15 dias. Ha
sido demasiado facil crackearlo.

-------------
Como hemos visto, modificar programas Symbian no es mas complicado que
modificar programas de Windows.
Por supuesto no hay tanta documentacion, pero la tecnica de interceptar
rutinas funciona bastante bien.
Mi agradecimiento a entusiastas como "18+2", Eric Bustarret, MacKam, Mika
Raento, y el Z-TeAm que han hecho accesibles estos conocimientos.
Y por supuesto, tantos y tantos programadores de Symbian repartidos por
todo el mundo. Ellos son los que hacen que cada dia sea mejor que el anterior.


*EOF*