¿Cómo puedo voltear un solo bit en un archivo?

35

Quiero dañar intencionalmente un archivo para probar las afirmaciones de que btrfs puede curarse solo . El artículo habla sobre quitar el sistema de archivos, dañar una foto al "voltear" un solo bit y luego volver a montarla. En sistemas de archivos más antiguos, esto simplemente estaría dañado, pero se supone que se arreglará en btrfs. En teoría, esto tiene sentido, pero realmente quiero probarlo.

El problema es que el artículo no explica cómo hacer nada de eso.
¿Cómo haría para cambiar un solo bit en una parte muy específica de un sistema de archivos?

También debo señalar que esto debe hacerse en un sistema de archivos fuera de línea para que btrfs no vea mi escritura como intencional.

Editar: Si bien la pregunta (y discusión) habla mucho sobre btrfs, me gustaría saber si hay métodos independientes del sistema de archivos para implementar este tipo de corrupción (para que pueda compararse entre diferentes tipos de RAID / controladores / etc.).

Oli
fuente
@Dan Quiero decir que si edito el archivo directamente, btrfs (o cualquier otro sistema de archivos) contaría eso como una escritura válida. No daría la corrupción que estoy buscando.
Oli
¿Es este un sistema de archivos de prueba (es decir, no le importan los contenidos o está perfectamente bien con la restauración desde la copia de seguridad? Además, ¿está utilizando una única partición btrfs en una sola unidad o una sola partición en la parte superior de una matriz RAID? , o alguna otra configuración?
Darth Android
1
Si btrfs admite los ioctls correctos (no estoy seguro si lo hace), puede utilizar filefrag -vpara averiguar exactamente dónde se encuentra un archivo.
derobert
3
@Oli Sospecho que encontraría un público más interesado en U&L, tanto en términos de votos como en términos de respuestas. Además, esto .
Strugee
1
Dispara un rayo cósmico en el lugar correcto.
smcg

Respuestas:

20

No soy un experto, pero el btrfs-progspaquete en realidad incluye una herramienta específica para hacer esto, aunque es posible que tenga que compilar desde la fuente. En cualquier caso, una vez que haya instalado o construido btrfs-progs, debería poder usar la herramienta btrfs-corrupt-block, que utilizan los desarrolladores de btrfs para probar el sistema de archivos.

Ahora, como dije, no he tenido mucho tiempo para jugar con btrfs, así que no sé el uso exacto de esta herramienta. Pero con él, debería poder corromper un sistema de archivos fuera de línea, que se solucionará cuando se lea el archivo dañado (suponiendo que haya configurado RAID o algo así para que haya otra copia para usar).

Strugee
fuente
2
Impresionante encontrar! Asumiendo que en btrfs-corrupt-blockrealidad está escrito para ser una prueba genuina y no un "truco" de los desarrolladores de btrfs, esto debería encajar exactamente.
allquixotic
@allquixotic si desea obtener más información sobre btrfs, linux.conf.au 2012 ofrece una excelente charla . como dije, btrfs-corrupt-blockes utilizado por los desarrolladores, por lo que no sería muy útil si fuera un truco :)
strugee
3
@allquixotic Esa es la belleza del código abierto: ¡puedes mirar el código fuente de btrfs y comprobarlo! Por supuesto, éste no es una tarea fácil, pero si realmente desea, puede hacer eso.
Bakuriu
@Bakuriu Soy completamente consciente de eso. Nunca dudé seriamente de que btrfs-corrupt-blockno sea una prueba sincera, ya que sería descubierta rápidamente por alguien que hurgaba en la fuente y se usaría como PR negativa contra Oracle (al menos, así como cualquier otro desarrollador / contribuyente de btrfs). Fue solo un comentario extravagante.
allquixotic
Me pregunto si el OP (@Oli) quiere corromper un bloque (es decir, la estructura del sistema de archivos) o un archivo (es decir, el contenido de un archivo ??) ... Y creo que la afirmación btrfs de autocuración se trata el primero, no el segundo? [¿cómo sabría un sistema de archivos qué bit se volcó en un archivo? algún tipo de CRC?]. Sin embargo, esta respuesta probablemente sea la correcta, por lo que +1. [pero puede cambiar más que un "bit único"? o cambiar algo que puede curarse más fácilmente que un bit aleatorio que ocurre "en cualquier lugar"?]
Olivier Dulac
16
  1. Obtenga el valor de un solo sector en el dispositivo de bloque (por ejemplo /dev/sda1) con una compensación de 1 millón de sectores (solo un ejemplo):

    sudo dd if=/dev/sda1 of=/root/mysector bs=512 count=1 skip=1M
    

    Este desplazamiento arbitrario elegido de 1M * 512 bytes es solo para asegurarse de que está fuera de la parte de metadatos del sistema de archivos y de que realmente está en un sector que contiene datos.

  2. Edite los datos del sector sin procesar cambiando el contenido con un editor hexadecimal. Ver por ejemplo Necesita un buen editor hexadecimal para Linux .

  3. Vuelva a colocar el sector en el disco con los argumentos ify ofinvertidos:

    sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    
gertvdijk
fuente
2
Esto no lo ayudará a probar a menos que el bloque 1 millón sea en realidad parte de un archivo. ¿Cómo puede buscar en qué bloque comienza un archivo en particular?
Darth Android
3
Eso es casi así . Si puede bloquear el comando dd en la posición exacta del archivo, esta es probablemente la mejor manera de abordar esto.
Oli
@Oli Sí, sé cómo hacerlo para la familia de sistemas de archivos Ext, pero no tengo mucha experiencia con btrfs. Déjame ver si puedo encontrar un camino.
gertvdijk
2
@Oli: simplemente puede tener un bucle, dd emitiendo bloque por bloque (es decir, como el anterior, pero "omitir = N", N está en 1..max) hasta que pueda seleccionar una línea del archivo que desea editar [intente generar una línea que no sucederá en ningún otro lugar ... por ejemplo, tomarla de un generador de contraseñas, y el tiempo suficiente?]. Luego editas ese bloque en particular. vuelva a montar, pruebe si el cambio fue revertido (lo cual dudo, vea mi comentario en la respuesta superior ... parece haber una confusión entre los datos del archivo (= contenido) y la estructura del sistema de archivos en sí (= cómo se organizan los archivos y su contenido )?)
Olivier Dulac
16

@Oli: hola, soy Jim Salter, el tipo que realmente escribió ese artículo. Estaba trabajando con una máquina virtual, lo que simplificó las cosas. Lo que hice comenzó con un archivo JPEG y lo abrí en un editor hexadecimal. El particular que usé fue Bless, que puedes instalar en Ubuntu con un simple apt-get install bless .

Después de abrir el JPEG en Bless, presioné la página varias veces para adentrarme en la "carne" del JPEG, y luego resalté unos cincuenta bytes de datos, y los copié y pegué en un editor de texto (en mi caso, gEdit). Esto me dio algo que buscar.

Ahora guardé el JPEG en cada matriz en la VM. El almacenamiento detrás de las matrices era una serie de archivos .qcow2. Una vez que guardé el JPEG en las matrices, pude cargar los archivos .qcow2 asociados con cada matriz en Bless, y buscarlos, no eran muy grandes, no eran más que JPEG y algunos metadatos, para ese patrón de cincuenta bytes. Lo había resaltado y copiado del JPEG. ¡Voila, tenía el bloqueo para corromper! En este punto, podría editar manualmente bytes individuales del JPEG tal como están almacenados en el disco virtual de la VM usando Bless, y, lo que es más importante, hacerlo exactamente de la misma manera en cada matriz.

El único inconveniente es que, en el caso de la matriz RAID5 probada en el artículo, tuve que asegurarme de que edité la copia real de los datos en la banda, y no la paridad de la banda en sí, era una pequeña imagen en un de lo contrario, matriz vacía, por lo que no había ningún dato en el bloque SIGUIENTE en la franja, lo que hace que el bloque de paridad contenga los datos inalterados del bloque de datos. Si hubiera editado accidentalmente el bloque de paridad en lugar del bloque de datos, la imagen se habría mostrado sin cambios.

Una nota final: no NECESITA máquinas virtuales para hacer esto: podría hacer las mismas cosas de la misma manera con metal desnudo; Sería más doloroso porque necesitarías trabajar con unidades RAW enteras en lugar de con pequeños archivos .qcow2, y tendrías que extraer las unidades y colocarlas en una máquina diferente, o iniciar en un entorno en vivo (o simplemente alternativo) para meterse con ellos. (Probé la recuperación de datos de ZFS exactamente de esta manera, pero en máquinas reales de metal desnudo, hace 7 años, cuando me interesé por primera vez en los sistemas de archivos de próxima generación).

¡Espero que esto ayude!

Jim Salter
fuente
4

Puede probar un pequeño programa que funcionará en el archivo abierto.FIBMAP ioctl(2)

Mediante una búsqueda rápida en la web, encontré esta publicación de blog http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html que detalla cómo hacer esto, incluso le dará un enlace a un programa de muestra que puede compilar y ejecutar usted mismo.

$ git clone git://kernel.ubuntu.com/cking/debug-code
$ cd debug-code/block-mapper-fibmap
$ make
$ sudo ./fibmap /path/to/your/image-file.jpg

Esta es exactamente la forma hdparm --fibmapen que se implementa (mencionado por @falconer).

Después de encontrar los números de bloque, podría emplear ddgongfu para modificar el archivo, como @gertvdijk esbozado. O tal vez podrías simplemente modificar elfibmap.c programa anterior para hacer el cambio de bit por usted, escribiendo directamente en el archivo del dispositivo sin pasar por la capa del sistema de archivos (tres parámetros para el programa: 1. la ruta al archivo, 2. archivo del dispositivo que contiene el archivo sistema, 3. desplazamiento y bit que desea modificar).

( Negación: no he probado y no puede garantizar que la FIBMAP ioctl(2)va a trabajar para un archivo en el sistema de archivos del dispositivo de bucle de retorno o btrfs, pero yo esperaría fuerte que hace que estoy. Adivinando hdparm comprobará el tipo de dispositivo antes de realizar el ioctl(2)en el archivo y es, por tanto, defecto.)

FooF
fuente
3
sudo hdparm --fibmap /PATH/TO/FILE

le dará los LBA donde se encuentra el archivo. Después de esto, puede usar la respuesta de @gertvdijk.

halconero
fuente
Lamentablemente, esto no parece funcionar. Está escupiendo un 0,39: device not found in /devEs porque es btrfs o (más probablemente) porque lo estoy usando en archivos retenidos en bucle. Intentaré hacer esto con una máquina virtual "adecuada".
Oli
@Oli Hmm. Pensé que hdparmfunciona en todos los sistemas de archivos, pero tal vez no sea así.
cetrero