Usando Linux para arreglar un USB roto

Un amigo mío me preguntó si podía recuperar alguna información que tenía muy importante en un USB que no funcionaba bajo Windows (por supuesto, ¿dónde lo iba a usar si no?). El caso es que lo llevó a varias tiendas de informática donde incluso lo probaron con un sistema operativo de gurús llamado Linux y nada, no consiguieron sacar nada de él.

Sin embargo, el USB se podía leer entero, por lo que pensé que algo podría sacarle punta. Primero saqué toda la información que pude del USB:


dd if=/dev/sda of=fichero


Utilizando hexdump u od me di cuenta de que los primeros 0x20000 bytes estaban puestos a 0xFF, por lo que parecía que el USB había fallado justo por donde no deberían fallar: la tabla de partición, sector boot y FAT. Un disco así es casi imposible de recuperar, salvo quizá si puedes recuperar una de las dos FAT que lleva el disco. Me puse a buscar a mano y vi que la primera FAT estaba incompleta pero que la segunda podría estar intacta:


00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00020000 01 df 02 df 03 df 04 df 05 df 06 df 07 df 08 df |................|
00020010 09 df 0a df 0b df 0c df 0d df 0e df 0f df 10 df |................|
00020020 11 df 12 df 13 df 14 df 15 df 16 df 17 df 18 df |................|


Buscando la cadena 01 df 02 df hacia adelante descubrí que se repetía: la segunda copia de la FAT. Además, la diferencia entre las dos apariciones era de 0x1F400 bytes. Para localizar dónde empieza, se puede buscar la signatura f8 ff ff ff. Y la encontré en 0x23600. Haciendo las restas, supuse entonces que la primera FAT empezaba en 0x23600 - 0x1F400 = 0x4200.

Así que en principio, copiando los sectores de la FAT segunda a la primera (250 sectores de 512 bytes en total) puedo reconstruir la FAT. Hago una copia del fichero en el fichero.bak y utilizo dd:


dd if=fichero.bak of=fichero bs=512 seek=33 skip=283 count=250 conv=nocreat,notrunc


Esto es, copiar desde el sector 283 (la posición 0x23600) hacia el sector 33 (posición 0x4200) 250 sectores, que es el tamaño de la FAT. Esto nos da información de cuántos sectores reservados va a tener inicialmente el sistema de ficheros FAT16.

Ahora bien, ¿cuántos elementos tiene el directorio raíz? Si recordáis el formato FAT, existen una serie de sectores reservados al principio, las dos FATs (de todo ello sabemos el tamaño) y el directorio raíz, cuyo tamaño también está especificado en el sector de arranque... ¿Cuánto es ese tamaño? No se sabía. Había que averiguarlo. Al irme al directorio raíz encuentro esto al principio:


00042a00 42 4c 4f 51 55 45 53 20 20 20 20 11 00 a5 2e 56 |BLOQUES ....V|
00042a10 f1 34 54 35 00 00 2f 56 f1 34 02 00 00 00 00 00 |.4T5../V.4......|
00042a20 e5 4f 4f 54 45 58 20 20 4c 4f 47 20 00 17 87 81 |.OOTEX LOG ....|
00042a30 54 35 58 35 00 00 88 81 54 35 d7 00 50 06 00 00 |T5X5....T5..P...|
00042a40 e5 4f 4d 45 44 4f 52 20 44 57 4c 02 10 2b f0 a3 |.OMEDOR DWL..+..|
00042a50 57 35 57 35 00 00 24 a6 57 35 1d 8b 41 00 00 00 |W5W5..$.W5..A...|
00042a60 44 45 54 41 4c 4c 45 53 20 20 20 10 00 4f 30 56 |DETALLES ..O0V|
00042a70 f1 34 1f 35 00 00 31 56 f1 34 25 02 00 00 00 00 |.4.5..1V.4%.....|


Perfecto, entradas de directorio. Encuentro cuál es la última y cuento. Hice esto y no funcionó. El problema es que justo después del directorio raíz había otro directorio, y no sabía exactamente dónde terminaba.

Así que se me ocurrió la idea de buscar los ficheros especiales "." y "..". Sólo un subdirectorio los tendría, lo que me daría la última entrada del directorio raíz. ¡Bingo!:


00048000 2e 20 20 20 20 20 20 20 20 20 20 10 00 a5 2e 56 |. ....V|
00048010 f1 34 f1 34 00 00 2f 56 f1 34 02 00 00 00 00 00 |.4.4../V.4......|
00048020 2e 2e 20 20 20 20 20 20 20 20 20 10 00 a5 2e 56 |.. ....V|
00048030 f1 34 f1 34 00 00 2f 56 f1 34 00 00 00 00 00 00 |.4.4../V.4......|


Así que el directorio raíz tiene de tamaño 0x42a00 - 0x48000 en entradas de 32 bytes, esto es, 688 entradas. Ya tenemos todos los datos.

Como necesitaba un sector de arranque para la partición, creé un fichero del mismo tamaño que el lápiz usb:


dd if=/dev/zero of=valido bs=512 count=1024000


Y después lo formateé con los datos que hemos obtenido:


mkfs.msdos -s 16 -R 33 -r 688 valido


16 sectores por pista, 33 sectores reservados y 688 entradas en el directorio raíz. Finalmente tengo que copiar el sector de arranque, que está en los primeros 512 bytes.


dd if=valido of=fichero bs=512 count=1 conv=nocreat,notrunc


Ya puedo montar el fichero:


mount fichero /mnt -o loop


Después de hacer algunas pruebas para ajustar exactamente los parámetros, he consegido recuperar mucha de la información del lápiz USB. Por supuesto alguna se ha perdido, porque estos fallos normalmente se producen por fallos en los bancos de memoria del USB, pero algo es algo.

Como información, decir que he probado varias utilidades para recuperar sistemas de ficheros y ninguna ha funcionado. No eran capaces de ver todas estas sutilezas. Esto me trae a la mente dos cosas, básicamente:

* Sería interesante ofrecer estos servicios a las empresas o personas que lo solicitaran.
* Linux es una maravilla :) y ha permitido recuperar información de un USB que, según Windows y otras tiendas especializadas en Informática, para lo único que valía era para tirarlo a la basura.

Todo esto está basado en un artículo de Linux Journal.

blog comments powered by Disqus