<div class="post-info"><h2 class="post-title"><a href="http://belinux.wordpress.com/2007/07/16/porque-es-dificil-recuperar-un-fichero-borrado-de-ext3/" rel="bookmark" title="Permanent Link: Porqué es difícil recuperar un fichero borrado de&nbsp;EXT3">
Porqué es difícil recuperar un fichero borrado de&nbsp;EXT3</a></h2>
Posted by makj under <a href="http://es.wordpress.com/tag/howto/" title="Ver todas las entradas en HowTO" rel="category tag">HowTO</a> ,  <a href="http://es.wordpress.com/tag/seguridad/" title="Ver todas las entradas en Seguridad" rel="category tag">
Seguridad</a> ,  <a href="http://es.wordpress.com/tag/tutorial/" title="Ver todas las entradas en Tutorial" rel="category tag">Tutorial</a> <br>&nbsp;</div>

        <div class="snap_preview"><p>[traducción del artículo original que se encuentra en <a href="http://linux.sys-con.com/read/117909.htm" target="_blank">ésta página</a>]</p>
<p align="justify">Todos lo hemos hecho antes: accidentalmente tecleas el argumento incorrecto al hacer <em>rm</em>
o seleccionas el fichero incorrecto para su borrado, al pulsar enter te
das cuenta de tu error y tu estómago da un vuelco. Y cuando vas a
buscar la copia de seguridad del sistema no hay ninguna.</p>
<p align="justify">Hay muchas herramientas de desborrado para sistemas
FAT y NTFS, pero hay muy pocas para EXT3, que es actualmente el sistema
de fichero por defecto de muchas distribuciones Linux. Esto es debido
al modo en que los ficheros EXT3 son eliminados: información crucial
que almacena donde está localizado el contenido del fichero es
eliminada durante el proceso de borrado.</p>
<p align="justify">En este artículo, echaremos un vistazo a bajo nivel
de porqué la recuperación es dificil y a algunas aproximaciones que son
efectivas algunas veces. Usaremos herramientas de código abierto para
la recuperación, pero las técnicas no son completamente automáticas.</p>
<p><span id="more-19"></span></p>
<p align="center"><strong>¿Qué es un fichero?</strong></p>
<p align="justify">Antes de poder ver como recuperar ficheros,
necesitamos ver como se almacenan. Típicamente, los sistemas de
ficheros están localizados dentro de particiones de disco, que a su vez
está organizada en sectores (usualmente de 512 bytes). Cuando la
partición está formateada usando EXT3, los sectores consecutivos son
agrupados en bloques, cuyo rango puede variar entre 1024 y 4096 bytes.
Los bloques son agrupados juntos en grupos de bloques, cuyo tamaño será
de decenas de miles de bloques. Cada ficheros tiene sus datos
almacenados en tres ubicaciones principales: bloques, inodos y entradas
de directorio. El contenido del fichero se almacena en bloques, que son
dispuestos para el uso exclusivo de ese fichero, expandiéndose por
tantos bloques como sea necesario. Idealmente, el fichero debería
utilizar bloques consecutivos, pero esto no es siempre posible.</p>
<p align="justify">Los metadatos del fichero son almacenados en una
estructura de inodo, que se encuentra en una tabla de inodos colocada
en el inicio de un grupo de bloques. Hay un número finito de inodos y
cada uno es asignado a un grupo de bloques. Los metadatos de un fichero
incluyen los datos temporales tales como la última modificación, el
último acceso, el último cambio y la fecha de borrado. También incluye
el tamaño del fichero, el identificador de usuario y de grupo, los
permisos, y las direcciones de los bloques donde se puede encontrar el
contenido del fichero.</p>
<p align="justify">Las direcciones de los primeros 12 bloques son
guardadas en el inodo y las direcciones adicionales son almacenadas
externamente en bloques, llamados bloques indirectos. Si el fichero
requiere muchos bloques y no todas las direcciones caben en un bloque
indirecto, un doble bloque indirecto es usado cuya dirección se incluye
en el inodo. El doble bloque indirecto contiene direcciones de bloques
indirectos simples, que contienen direcciones de bloques con datos de
fichero. Hay incluso direcciones indirectas triples en el inodo que
añaden una capa más de punteros.</p>
<p align="justify">Por último, el nombre del fichero está almacenado en
una estructura de entrada de directorio ubicada en un bloque asignado
al directorio padre del fichero. Un directorio EXT3 es parecido a un
fichero y sus bloques contienen una lista de estructuras de entradas de
directorio, cada una conteniendo el nombre de un fichero y las
dirección del inodo en el que se almacenan los metadatos del fichero.
Con el comando <em>ls -i</em> puedes ver la dirección del inodo que
corresponde a cada nombre de fichero. Se puede ver la relación entre
una entrada de directorio, el inodo y los bloques en la <a href="http://res.sys-con.com/story/aug05/117909/linux-carrier-fig1.gif">Figura 1</a>.</p>
<p align="justify">Cuando un nuevo fichero es creado, el sistema
operativo (SO) debe elegir que bloques e inodo asignará al fichero.
Linux intentará asignar los bloques y el inodo en el mismo grupo de
bloques que su directorio padre. Esto provoca que los ficheros en un
mismo directorio estén mucho más cercanos. Posteriormente usaremos este
hecho para restringir donde buscar datos eliminados.</p>
<p align="justify">El sistema de ficheros EXT3 tiene un  <em>journal</em> (<font color="#c0c0c0"><strong>nota del traductor:</strong>
me permito aquí mantener el término en inglés por comodidad en lugar de
usar bitácora o diario de registro, ya que cualquiera de los dos queda
algo raro</font>) que registra las actualizaciones de los metadatos del
sistea ANTES de que la actualización ocurra. En caso de una caída del
sistema, el SO lee el journal y podrá reprocesar o deshacer las
transacciones registradas para que la recuperación sea mucho más rápida
que examinar cada estructura de metadatos, que era el antiguo y
lentísimo mecanismo. Las estructuras de metadatos de ejemplo incluyen
las entradas de directorio que almacenan nombres de fichero e inodos
que almacenan los metadatos del fichero. El journal contiene el bloque
entero que está siendo actualizado, no solo el valor que está
cambiando. Cuando un nuevo fichero es creato, el journa debería
contener la versión actualizada de los bloques que contienen la entrada
del directorio y el inodo.</p>
<p align="center"><strong>El proceso de borrado</strong></p>
<p align="justify">Varias cosas ocurren cuando un fichero es borrado de
un sistema EXT3 en Linux. Hay que tener en cuenta que el SO debe
decidir exactamente que ocurre cuando un fichero es eliminado y éste
artículo asume un sistema Linux general.</p>
<p align="justify">Como mínimo, el SO debe marcar cada uno de los
bloques, el inodo y la entrada de directorio como no-asignados para que
ficheros posteriores puedan usarlos. Esta mínima aproximación es lo que
ocurría hace años con los sistemas EXT2. En ese caso, el proceso de
recuperación era relativamente simple ya que el inodo aún contenía las
direcciones de los bloques del contenido del fichero y herramientas
tales como <font color="#808000">debugfs</font> y <font color="#808000">e2undel</font>
podían re-crear el fichero fácilmente. Esto funcionaba mientras que los
bloques no habían sido asignados a un nuevo fichero y el contenido
original no había sido sobreescrito.</p>
<p align="justify">Con EXT3, hay un paso adicional que hace la
recuperación mucho más difícil: cuando los bloques son desasignados, el
tamaño del fichero y las direcciones de los bloques en el inodo son
limpiados; por tanto ya no podemos determinar donde estaba el contenido
del fichero. Podemos ver la relación entre la entrada de directorio, el
inodo y los bloques de un fichero desasignado en la <a href="http://res.sys-con.com/story/aug05/117909/linux-carrier-fig2.gif">Figura 2</a>.</p>
<p align="center"><strong>Aproximaciones de recuperación</strong></p>
<p align="justify">Ahora que conocemos los componente involucrados con
los ficheros y cuales son limpiados durante el borrado, podemos
examinar dos aproximaciones a la recuperación de ficheros (aparte de
usar un backup). La primera aproximación usa el tipo de aplicación del
fichero eliminado y la segunda aproximación usa los datos en el
journal. Independientemente de la aproximación, debería dejar de usar
el sistema de ficheros porque podría crear un fichero que sobreescriba
los datos que está tratando de recuperar, puede detener su sistema y
poner el disco en otro ordenador con un sistema Linux como un disco
esclavo (<em>slave</em>) o arrancar desde un Linux LiveCD (<font color="#808000">knoppix</font> o <font color="#808000">necromantux</font> son buenas distribuciones para este tipo de tareas).</p>
<p align="justify">El primer paso para ambas técnicas es determinar la
dirección del inodo del fichero eliminado. Esto puede ser determinado
usando <font color="#808000">debugfs</font> o <font color="#808000">The Sleuth Kit (TSK)</font>.
Mostraré aquí el método usando debugfs ya que esta herramiento se
incluye en muchas distribuciones Linux y es un depurador del sistema de
ficheros. Para empezar con debugfs, debe saber el nombre del
dispositivo de la partición que contiene el fichero eliminado. En mi
ejemplo, he iniciado desde un LiveCD y el fichero está ubicado en
/dev/hda5:</p>
<pre><font color="#800000" face="Verdana" size="2"> # debugfs /dev/hda5</font><font color="#800000" face="Verdana" size="2"><br><br></font><font color="#800000" face="Verdana" size="2"> debugfs 1.37 (21-Mar-2005)</font><font color="#800000" face="Verdana" size="2">
<br></font><font color="#800000" face="Verdana" size="2"> debugfs: </font></pre>
<p align="justify">Podemos usar el comando <em>cd</em> para cambiar al directorio del fichero eliminado:</p>
<pre><font color="#800000" face="Verdana" size="2"> debugfs:  cd /home/carrier/ </font></pre>
<p align="justify">El comando <em>ls -d</em> listará los ficheros
asignados y eliminados del directorio. Recuerde que la estructura de
entrada de directorio almacena el nombre e inodo de los ficheros y este
listado nos dará ambos valores ya que ninguno es eliminado durante el
proceso de borrado. Los ficheros eliminados tendrán su dirección de
inodo delimitado por "&lt;" y "&gt;":</p>
<pre><font color="#800000" face="Verdana" size="2"> debugfs: ls -d</font><font color="#800000" face="Verdana" size="2"><br><br></font><font color="#800000" face="Verdana" size="2"> 415848  (12) .    376097  (12) ..    415864  (16) .bashrc
</font><font color="#800000" face="Verdana" size="2"> </font></pre>
<pre><font color="#800000" face="Verdana" size="2">[…]</font><br><br><font color="#800000" face="Verdana" size="2"> &lt;415926&gt; (28) oops.dat </font></pre>
<p align="justify">El fichero que estamos intentando recuperar es <em>/home/carrier/oops.dat</em>
y podemos verlo previamente asociado al inodo 415,926. El "(28)" nos
indica la longitud de la estructura de entrada de directorio, pero eso
no nos interesa.</p>
<p align="center"><strong>Recuperación por "esculpido" de ficheros (<em>file carving</em>) </strong></p>
<p align="justify">La primera técnica de recuperación, llamada <em>file carving</em> (<font color="#c0c0c0"><strong>nota del traductor:</strong> mantendré el nombre en inglés</font>),
utiliza las firmas del fichero eliminado. Muchos tipos de ficheros
tienen valores estándar en los primeros bytes de la cabecera del
fichero, y ésta técnica de recuperación busca los valores de cabecera
del fichero eliminado para determinar donde puede que empezara el
fichero. Por ejemplo, los ficheros JPEG empiezan con 0xFFD8 y terminan
con 0xFFD9. Para recuperar un fichero JPEG eliminado, deberíamos buscar
en los dos primeros bytes de cada bloque hasta encontrarnos con la
marca OxFFD8. Cuando encontrásemos ese bloque, deberíamos buscar un
bloque con los bytes 0xFFD9 en él. Los datos intermedios se asume que
era el fichero. Desafortunadamente, no todos los tipos de ficheros
tienen una firma final, por tanto determinar el final es dificil. Un
ejemplo de una herramiento de código abierto que hace <em>file carving </em>es <font color="#808000">foremost</font>, también existen varias herramientas comerciales.</p>
<p align="justify">Podemos ejecutar una herramienta como <em>foremost</em>
en un sistema de ficheros completo, pero acabaríamos probablemente con
demasiados ficheros, incluyendo algunos ya asignados. Será preferible
lanzarlo sobre cuantos menos datos sea posible. La primera manera en
que podemos restringir el tamaño de los datos es examinar sólo los
grupos de bloques donde el fichero estaba ubicado. Recuerde que los
inodos y los bloques de un fichero están asociados a un mismo grupo de
bloques, si hay espacio. En nuestro caso, sabemos que inodo usaba el
fichero y por tanto podemos examinar sólo los bloques del mismo grupo.
El comando<em> imap</em> en <em>debugfs</em> nos indicará a que grupo de bloques pertenece un inodo:</p>
<pre><font color="#800000" face="Verdana" size="2"> debugfs:  imap &lt;415926&gt;</font><font color="#800000" face="Verdana" size="2"> Inode 415926 is part of block group 25</font><br><br><font color="#800000" face="Verdana" size="2">
 located at block 819426, offset 0×0a80 </font></pre>
<p align="justify">La salida del comando <em>fsstat</em> en <em>TSK</em> nos dirá también lo siguiente:</p>
<p><font color="#800000" face="Verdana" size="2"> # fsstat /dev/hda5<br>
[…]<br>
Group: 25:<br>
Inode Range: 408801 - 425152<br>
Block Range: 819200 - 851967 </font></p>
<p align="justify">A continuación, necesitamos determinar los bloques
que están en el grupo de bloques del fichero eliminado. Podemos verlos
en la salida del comando <em>fsstat</em> mostrado anteriormente, pero si estuvieramos usando <em>debugfs</em>, necesitamos calcular el rango. El comando stats nos da el número de bloques en cada grupo:</p>
<p><font color="#800000" face="Verdana" size="2"> debugfs: stats<br>
[…]<br>
Blocks per group: 32768<br>
[…] </font></p>
<p align="justify">Puesto que estamos buscando en el grupo de bloques
25, el rango de bloques va desde 819,200 (25 * 32,768) hasta el 851,967
(26 * 32,768 - 1). Si nos centramos sólo en estos bloques, estaremos
mirando en 128Mb en lugar de en el sistema de ficheros completo. Aún
así, si no podemos encontrar el fichero en estos bloques, necesitaremos
mirar en todo el sistema de ficheros.</p>
<p align="justify">El siguiente paso para reducir los datos a analizar
es extraer los bloques no asignados del sistema de ficheros ya que ahí
es donde nuestro fichero eliminado estará. <em>debugfs</em> no nos
permite actualmente extraer el espacio no asignado de sólo un grupo de
bloques específico, por tanto deberemos usar la herramienta <em>dls</em> de <em>TSK</em>.</p>
<pre><font color="#800000" face="Verdana" size="2"> # dls /dev/hda5 819200-851867 &gt; /mnt/unalloc.dat </font></pre>
<p align="justify">El comando anterior nos guardará los bloques no
asignados en el grupo de bloqes 25 en un fichero llamado
/mnt/unalloc.dat . Asegurese que este fichero esté en un sistema de
ficheros diferente ya que de otro modo podría acabar sobreescribiendo
su fichero eliminado.</p>
<p align="justify">Ahora podemos ejecutar la herramienta foremost sobre
los datos no asignados. foremost puede recuperar sólo tipos de ficheros
para los que se haya configurado. Si foremost no tiene la firma de
cabecera para el tipo del fichero eliminado, deberá examinar algunos
ficheros similar y personalizar el fichero de configuración. Podemos
ejecutarlo del siguiente modo:</p>
<pre><font color="#800000" face="Verdana" size="2"> # foremost -d -i /mnt/unalloc.dat -o /mnt/output/ </font></pre>
<p align="justify">La opción -d intentará detectar que bloques son
indirectos y no los incluirá en el fichero final. El directorio
/mnt/output contendrá los ficheros que hayan podido ser recuperados. Si
su fichero no está ahí, puede expandir su búsqueda a todos los bloques
no asignados en el sistema de ficheros en lugar de sólo a los bloques
del grupo.</p>
<p align="center"><strong>Recuperación basada en journal</strong></p>
<p align="justify">El segundo método para tratar de recuperar ficheros
es usar el journal. Ya hemos visto que las actualizaciones de inodos se
guardan primero en el journal, pero el concepto importante es que el
bloque entero en el que el inodo está ubicado es guardado en el
journal. Por tanto, cuando un inodo es actualizado, el journal
contendrá copias de otros inodos almacenados en el mismo bloque.
Versiones anteriores del inodo de nuestro fichero elimiando pueden
existir en el journal porque otro fichero fuera actualizado antes del
borrado.</p>
<p align="justify">La maner más fácil de buscar versiones anteriores del inodo es usando el comando<em> logdump -i </em>en <em>debugfs</em>:</p>
<pre><font color="#800000" face="Verdana" size="2"> debugfs:  logdump -i &lt;415926&gt;<br> Inode 415926 is at group 25, block 819426, offset 2688<br> Journal starts at block 1, transaction 104588<br> FS block 819426 logged at sequence 104940, journal block 2687
<br> (inode block for inode 415926):<br> Inode: 415926   Type: regular        Mode:  0664   Flags: 0×0<br> User:   500   Group:   500   Size: 2048000<br> […]<br> Blocks:  (0+12): 843274 (IND): 843286<br> […] </font></pre>

<p align="justify">En este caso, podemos encontrar una copia previa del
inodo y los bloques del contenido del fichero están listados en la
última línea. La última línea muestra que el primer bloque del fichero
es 843,274 y los siguientes 12 bloques en el sistema de ficheros son
los siguientes 12 bloques del fichero. El fichero es grande y necesita
un bloque indirecto, que está localizado en el bloque 843,286. Hasta
aquí, todos los bloques son consecutivos y no había fragmentación. El
bloque 843,286 contiene el resto de direcciones de bloques, así que
podríamos buscar en una versión anterior para descubrir donde está
ubicado el resto del fichero. Podemos ver si hay una copia en el
journal usando<em> logdump -b</em>:</p>
<pre><font color="#800000" face="Verdana" size="2"> debugfs:  logdump -b 843286 -c </font></pre>
<p align="justify">Desafortunadamente, no encontramos una copia del
bloque que contiene la lista original de punteros de bloque así que, si
queremos recuperar el fichero deberemos asumir que el resto del
contenido del fichero está guardado en el bloque 843,287 y siguientes.
Una aproximación más avanzada podría también considerar qué bloques
están actualmente asignados y saltarnoslos. Los datos pueden ser
extraidos con herramientas tales como <em>dd</em> o <em>Linux Disk Editor</em>. El journal puede ser consultado también usando las herramientas <em>jls</em> y <em>jcat</em> de <em>TSK</em>.</p>
<p align="center"><strong>Conclusión</strong></p>
<p align="justify">La recuperación de ficheros con EXT3 no es una tema
trivial, lo que refuerza el concepto de la importancia de hacer copias
de seguridad de los ficheros. Si el fichero no estaba fragmentado, la
búsqueda de su firma de cabecera puede ser útil, pero la herramienta
necesita saber ignorar los bloques indirectos y donde parar de copiar
(no todos los ficheros tienen una marca de final de fichero).
Restringiendo la búsqueda al grupo de bloques local puede ahorrar mucho
tiempo. El journal puede ser útil si los ficheros cerca del fichero
eliminado han sido reciéntemente actualizados y por tanto existe una
versión previa del inodo, pero esto no está siempre garantizado y el
bloque indirecto del fichero puede no existir.</p>
</div><br clear="all"><br>-- <br>Carlos Ortiz Gutierrez<br><a href="mailto:cortizg@ubuntu.org.ni">cortizg@ubuntu.org.ni</a><br><a href="mailto:cortizg@gmail.com">cortizg@gmail.com</a><br>mobil:5058338893<br>ubuntu user #: 14177