miércoles, 27 de junio de 2012

Historia de un Rooteo ( y todo lo que aprendi en el proceso)

Hace unos dias descubri una forma de rootear las ROMs 2.3.6 del Motorola Milestone 2 que di por llamar preinstalameEsta.
Esto es un recorrido por como lo fui haciendo, de donde saque las ideas, y todo lo que aprendi en el proceso. Pensado como una guia para los que no somos ÜberHackers que quieran ver de rootear su celular

Como cai con la rom 2.3.6:

Cuando lo compre el celular me vino con 2.2 que era una reverenda garcha, y que prontamente lo rootie y le puse Argen2stone y luego cuando salio, CM7.
Durante el verano entre arena y demas se me despegaron un par de "letras" del teclado (es un plastiquito piojoso). Lo lleve al service oficial (que tardaron una banda porque no tenian repuestos) y cuando me lo devolvieron descubro que habian flasheado la 2.3.6. La cual 15 minutos de googleo despues descubro que no se puede rootear (NOOOOOOOO ESTAMOS EN LA B!)

Inicio del recorrido:

Un par de meses de frustracion, y muchas horas browseando en XDA y grupoandroid luego, aparecio este metodo de rooteo para el motorola PRO que rapidamente llego al foro del MM2. No funciono pero el testeo dejo un par de datos interesantes sobre el celular, el firmado de particiones y el sistema de flasheo.
El metodo lo que planteaba era:
1) Hacer un dump de la particion userdata (que en el filesystem del celular se monta en /data)
2) Modificar el default.prop para setearle la property que hace que el adb shell "se loguee" como root (mas data sobre esto mas abajo)
3) Flashearla en el telefono

Este metodo por no funciono en el MM2, paso a explicar porque.
Dentro de las ROM's (tambien llamadas sbf por el formato) oficiales de los celulares, vienen la data que se va a flashear en cada una de las particiones del telefono + el RamLoader que es un programa que se carga en el celular al inicio del flasheo y sabe que particiones tiene que flashear (lease, las que vienen en la ROM).
Sumado a eso hay particiones que estan firmadas, es decir, sobre las cuales solamente se pueden flashear particiones firmadas por el OEM (En este caso motorola).
En el caso del Motorola Pro, la particion userdata (que dentro del sbf se llama CG37) era una de las que el RamLoader flashea, y no estaba firmada, con lo cual se la podia reemplazar durante el proceso de flasheo y flashear lo que quisieramos.
Al tratar de probarlo en el Milestone 2 nos dimos cuenta de que la particion CG37 no esta en el RamLoader de nuestras ROM's (el flasheo hay que hacerlo con el RamLoader que corresponde sino explota todo), con lo cual no se podia flashear, y ese metodo de rooteo quedo descartado.
Pero mientras que lo probaba descubri el sbf_flash que es una herramienta de flasheo para linux/mac (similar al RSD lite para windows). Entre sus funcionalidades tiene 2 muy importantes:
1) Extraer las particiones del sbf
2) Mostrar la tabla de particiones del telefono con cierta data extra (entre ellla, si esta firmada o no)
3) Flashear todo el sbf, o particiones individuales (de las que estan en el SBF y que el RamLoader acepta)
En el caso de la Rom de Personal (y calculo que el resto de las ROM de las otra operadoras seran iguales), las particiones que bienen adentro del sbf son:


CG31
CG32
CG33
CG34
CG35
CG37
CG39
CG42
CG45
CG47
CG61
CG64
CG65
CG66


Y la data que me da de la tabla de particiones sobre ellas es la siguiente (reducida para que no ocupe tanto espacio):


CG_num: 64
CG_name: mbr
signature_start_addr: 0x83003800
signature_end_addr: 0x83003fff

CG_num: 65
CG_name: ebr
signature_start_addr: 0x83013800
signature_end_addr: 0x83013fff

CG_num: 31
CG_name: cdt.bin
signature_start_addr: 0x89073800
signature_end_addr: 0x89073fff

CG_num: 34
CG_name: lbl
signature_start_addr: 0x80d03800
signature_end_addr: 0x80d03fff

CG_num: 42
CG_name: logo.bin
signature_start_addr: 0x86f6f800
signature_end_addr: 0x86f6ffff

CG_num: 61
CG_name: devtree
signature_start_addr: 0x8910f800
signature_end_addr: 0x8910ffff

CG_num: 45
CG_name: bpsw
signature_start_addr: 0x644ff800
signature_end_addr: 0x644fffff

CG_num: 35
CG_name: boot
signature_start_addr: 0x818ff800
signature_end_addr: 0x818fffff

CG_num: 47
CG_name: recovery
signature_start_addr: 0x818ff800
signature_end_addr: 0x818fffff

CG_num: 33
CG_name: cdrom
signature_start_addr: 0x8bdbf800
signature_end_addr: 0x8bdbffff

CG_num: 39
CG_name: system
signature_start_addr: 0x9efbf800
signature_end_addr: 0x9efbffff

CG_num: 32
CG_name: prek
signature_start_addr: 0x8a71f800
signature_end_addr: 0x8a71ffff

CG_num: 66
CG_name: preinstall
signature_start_addr: 0xffffffff
signature_end_addr: 0xffffffff


De ahi se ve claramente ( y sino para eso estan los colores :P) que la unica particion que se flashea en el celular y que no esta firmada es la CG66 tambien conocida como preinstall, cuyo punto de montaje es /preinstall, que solo es escribible por root desde el adb shell, con lo cual modificandola y flasheandola podriamos poner data nuestra donde desde el celu no se puede.
Esa particion, como descubri despues, es donde van las aplicaciones "precargadas".
Lo cual tiene sentido, si sos motorola no queres que las operadoras te rompan las bolas para que les firmes la particion si quieren hacer una promo que te regalan alguna app con el celular, entonces la dejas sin firmar y que desde la operadora le pongan lo que quieran.
Por otro lado deberia haber algun proceso que se fije que hay en esa particion y lo instale en algun momento.
Con esa idea, revisando el logcat del celular (el logueo de todo, o mejor la mayoria de las cosas, que pasan en el celular, que te deja android para debuguear), encontre que estaba corriendo durante el booteo un script, /system/bin/loadpreinstalls.sh y que estaba escribiendo un log en /data/preinstall_md5.

Previo a esto, habia estado leyendo de un par de metodos de rooteo aca, y  revisando el filesystem del celular desde el adb shell a ver si encontraba algo similar a lo que cuentan en ese blog, no encontre nada entrable de una, pero si encontre que, no solo que la mayoria de los archivos del celular tenia los permisos muy estrictos (lo cual esta bien desde el punto de vista de Motorola), sino que habia un par de directorios, entre ellos /data, que para los usuarios que no eran root o system,  tenian permiso solo de ejecucion, lo cual es extraño porque (para los que no estan muy duchos con los permisos de archivos de linux) no te deja listarlos ni escribirlos, pero si acceder a lo que esta adentro.

Con lo cual yo desde el adb podia acceder a lo que este adentro de /data, siempre y cuando conociese el nombre del archivo/carpeta.
Con lo cual encontrar lo del script de preinstall era doblemente bueno, no solo porque ahora sabia quien preinstalaba las aplicaciones, sino porque encontre el nombre de una carpeta adentro de /data.
Entrando a la carpeta via el shell, encontre otra cosa, que a esa carpeta tenia permisos de escritura todo el mundo, lo cual seria favorable luego, y tambien que me estaba dejando un archivo de log cuyo dueño era el root, lo que implicaba que ese script corria como root.

Resumiendo hasta este punto. Encontre una particion sin firmar sobre cuya data el usuario root ejecuta un script que escribe a una carpeta escribible por el todo el mundo. Hasta aca me siguen, buenisimo!

Un par de cuestiones generales antes de seguir.

1) Normalmente los metodos de rooteo buscan escribir en /data/local.prop y setear una propiedad que hace que el adb shell te brinde acceso como root, en el caso de motorola la propiedad y el valor que tiene que tomar es:
ro.sys.atvc_allow_all_adb=1

2) En linux, existe algo que se llama symbolic link (link simbolico en español) que es algo asi como un acceso directo en windows. con la salvedad de que si vos lees/escribis/ejecutas ese archivo, en realidad estas operando sobre el archivo/carpeta al cual apunta.
Hay 2 tipos de symbolic link, el hard link que apunta al inodo (que a groso modo seria el lugar en el disco donde esta almacenado el archivo) donde esta el archivo y soft link que apunta al path.

Volviendo:

Al script ese tenia acceso de lectura asi que me lo baje y me lo puse a leer (esta en http://pastebin.com/NjZjjnY8 si lo quieren ver, pastearlo me rompia todo el identado)

Algo que ya habia visto antes era que estaba escribiendo un log de lo que hacia en /data/preinstall_md5/log.txt con lo cual, si lo borraba y ponia un symbolic link apuntando a local.prop y controlaba de alguna forma lo que logueaba el archivo podria escribir lo que yo quisiese en local.prop.

Mirando el script, vi que levantaba de /preinstall/app (en realidad de /system/preinstall/app, pero /system/preinstall es un symblic link a /preinstall) y /preisntall/md5 la lista de apps que tenia que levantar, por lo tanto, si mi app se llamaba "ro.sys.atvc_allow_all_adb=1" o similar me iba a escribir eso en el local.prop y magia soy root.


Por suerte la particion de preinstall fue facil de modificar, ya que es una particion ext3 y en linux es muy facil de montar (mount CG66.img algun/lado/). Asi que la podia montar, modificar lo que quisiese, desmontarlo, y flasheaerlo con el sbf_flash.
Hice eso, cree 2 archivos, "app/ro.sys.atvc_allow_all_adb=1#" y "md5/ro.sys.atvc_allow_all_adb=1#.md5",  dentro de la particion de preinstall, y la flashee via sbf. El resultado se puede ver aca.
Logre el objetivo de escribir en el local.prop (lo cual es siempre un buen indicio), pero no me tomo el valor de la property (le seteaba 1 mas toda la mugre que ponia el log atras) y para colmo hacia que el celu se me colgase. Con lo cual por ahi no iba a tener suerte.
Postie lo que encontre en XDA y en grupoandroid, esperando que alguien le de bola y se fijase si lo podia seguir. No paso ninguna de las 2 cosas y lo deje medio olvidado en espera de que alguien lo tome y lo siga.


Un par de findes atras, me volvieron a agarrar ganas de mirarlo, y volvi al analisis del script y encontre esta condicion/cacho de codigo:

       newMD5=`cat $PRELOAD_HASH_DIR/$file.md5`
       oldMD5=`cat $DATA_HASH_DIR/$file.md5`
       if [ "$newMD5" != "$oldMD5" ]; then
           isInstalled=`pm path $file`
           # app not installed, but md5 exists = user uninstalled app, do nothing
           if [ -z "$isInstalled" -a -e "$DATA_HASH_DIR/$file.md5" ]; then
               echo "$file: user has uninstalled, dont reinstall. copying $file.md5 to $DATA_HASH_DIR"
               echo "$file: user has uninstalled, dont reinstall. copying $file.md5 to $DATA_HASH_DIR" >> $PRELOAD_LOG_FILE
               cp $PRELOAD_HASH_DIR/$file.md5 $DATA_HASH_DIR

Previamente en el codigo:
PRELOAD_HASH_DIR=/system/preinstall/md5
DATA_HASH_DIR=/data/preinstall_md5
y $file es el nombre del archivo que encontro en /preinstall/app/

Entonces, supongamos que el archivo en /preinstall/app/ se llama pepe:
El script compara los contenidos de /data/preinstall_md5/pepe.md5 y /preinstall/md5/pepe.md5. Si difieren pero /data/preinstall_md5/pepe.md5 existe (el cat devuelve "" si no existe) entonces copio el archivo desde /preinstall/md5/pepe.md5 a /data/preinstall_md5/pepe.md5.

Ahora, que pasa si existe un pepe.md5 en /data/preinstall_md5, pero es un symbolic link /data/local.prop, y el contenido de /preinstall/md5/pepe.md5 es "ro.sys.atvc_allow_all_adb=1"? Deberia pisar local.prop con "ro.sys.atvc_allow_all_adb=1" y ya esta, ganamos!

Bueno no, no se porque, si por alguna limitacion en como corre el script o que, pero no me lo dejo hacer, con lo cual hay que buscar otro metodo.
De todas formas ese metodo se puede usar para pisar cualquier archivo del sistema (siempre y cuando este en una particion montada como rw), lo cual nos puede venir copado.

Lo que estaria bueno en este punto es correr codigo nuestro en lugar de estar trasteando con algun bug en un script. Mirnado este post en vulnfactory.org vi que hacia referencia a que se puede logar eso modificando   proc/sys/kernel/modprobe o /proc/sys/kernel/hotplug y haciendolos apuntar a un script definido por el usuario. En el kernel que usa el MM2 esos archivos fueron reemplazados por /sys/kernel/uevent_helper.

Basicamente cuando se produce un uevent (que ni idea que es ni que lo produce XD), el kernel llama al script al cual apunta ese archivo (como root obviamente), con lo cual si creamos un script en /data/preinstall_md5 (porque a esta altura ya me familiarise con ese escritorio y tengo permisos para hacer lo que quiera ahi, pero tranquilamente podria ser en cualquier otro lado), ponele que lo llamemos test.sh, y pisamos /sys/kernel/uevent_helper, con "/data/preinstall_md5/test.sh", entonces cuando se produsca un uevent se va a ejecutar nuestro script.
Hasta ahi todo bien, pero ... como hacemos que se ejecute un uevent? 
Googleando un poco encontre este articulo que dice que se puede triggerear un uevent escribiendo "change" en /sys/class/mem/null/uevent.
Ya tenemos la idea, entonces:
Creamos un archivo /data/preinstall_md5/test.sh con el siguiente contenido (tuve que llamar al sh y usar los full paths porque sino no funcionaba):
#!/system/bin/sh
/system/bin/sh -c "/system/bin/id > /data/preinstall_md5/lala.txt"
(el comando id te dice como que usuario estas corriendo)

2 symbolics links
primero.md5 -> /sys/kernel/uevent_helper
segundo.md5 -> /sys/class/mem/null/uevent

y modificar la particion preinstall para que tenga
app/primero
app/segundo
md5/primero.md5, contenido: /data/preinstall_md5/test.sh
md5/segundo.md5, contenido: change

El nombre de los archivos influye en el orden, justo se da que primero viene antes alfabeticamente que segundo, con lo cual lo va a procesar antes (que es lo que queremos)
Flasheamos el CG66, reiniciamos y o magia, en /data/preinstall_md5/lala.txt tengo:
uid=0(root) gid=0(root)

Luego el paso siguiente fue cambiar test.sh para que escriba ro.sys.atvc_allow_all_adb=1 al local.prop, lo cual funciono sin problemas y al reboot siguiente el adb me recibio como root. adb remount, me remonto system com rw, y listo el pollo, ya soy dueño de mi celu de vuelta.

Conclusiones:

1) No fue ningun hack magico,  simplemente un problema de permisos, mas un script que no validaba data que podia llegar a estar puesta por el ususario (jamas valida si lo que tiene en /preinstall/app es realmente una app, ni tampoco computa el md5 de esos archivos, simplemente usa los que tiene en /preinstall/md5)
2) Para el rooteo es necesario flashear una particion, con lo cual ninguna aplicacion malintencionada podria acceder como root por este metodo. 
3)No creo que Motorola parchee el bug. Si estuvieron 1 año para hacer el release de gingerbread, olvidate que saquen una version para fixear un rooteo, mas siendo que 2)
3)Antes de arrancar no tenia idea de las particiones del celular, ni habia usado nunca un symbolic link (si laburo mucho sobre linux), ni oido hablar del /sys/kernel/uevent_helper, con lo cual, cualquiera que le hubiese dedicado un par de findes lo podria haber hecho (de hecho todavia tengo un poco de bronca de que nadie aprovecho lo que postee sobre escribir en el local.prop a traves del log.txt).
4)Si tenes un celu que no se puede rootear, dedicale unas horitas a tratar de ver por donde se puede llegar a entrar, la idea de este post es mostrar las que encontre yo, en http://vulnfactory.org/blog/, hay otras otras tantas. Si encontras como rootearlo buenisimo, y sino vas a aprender una banda, como hice yo :)


Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Argentina License.

7 comentarios:

  1. Muy Muy Bueno.. Me Encantaria Saber Todo Eso.. Así Que a Estudiar :) Gracias Por Todo Eso :) Me Gustaría Aprender Con/Como Vos

    ResponderEliminar
  2. WOW!! esto es muy bueno vamos con el defymini xt320 que si se puede, como lo tengo será más fácil, pero tengo windows xp voy a ver que porque al linux le entiendo sólo un poco

    ResponderEliminar
  3. Waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.... Odiooo mi Milestone2 Es una Mierda!... En conclucion noc que mierda hacer con el!... Me cagooo en Personal!... En conclucion mi milestone2 Me dice q es un milestone1 Y tengo el android 2.2.1 Y es una Mierda! Alguien me Puede ayudar se Lo Agradeceria Muchisimo!... mi mail. lcristian87 @ hotmail.com Gracias!...

    ResponderEliminar
  4. paaa mi loco quiero un poco de ese mate tengo un milestone 2 que personal me lo dejo bloqueado porquelosseñoritos me dieron el code subsidy de 16 numeros y no andubo me lo tuvieron un mes para liberarlo y me dijeron que no andaban y tambien quiero darle una rom masactualizada ya que son flojos los de personal tengo el gingnbreik 2.3.6

    ResponderEliminar
  5. Gracias Capo, dejo algo por aquí:

    http://books.google.com.ar/books/about/Android_Forensics.html?id=zDibrpXTfxMC&redir_esc=y

    Anda el pdf y el epub por ahí dando vueltas.

    ResponderEliminar