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

Quiero dañar intencionalmente un archivo para probar las afirmaciones de que btrfs puede curarse a sí mismo . 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 anteriores, esto solo se corrompería, pero se supone que se corrige solo 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 podría 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.

Edit: Si bien la pregunta (y la discusión) habla mucho sobre btrfs, me gustaría saber si existen 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).

No soy un experto, pero el paquete btrfs-progs realidad incluye una herramienta específicamente para hacer esto, aunque es posible que tenga que comstackr desde la fuente. En cualquier caso, una vez que haya instalado o creado btrfs-progs , debería poder usar la herramienta btrfs-corrupt-block , que es utilizada por 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).

  1. Obtenga el valor de un solo sector en el dispositivo de bloque (por ejemplo, /dev/sda1 ) con un desplazamiento de 1 millón de sectores de compensación (solo un ejemplo):

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

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

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

  3. Vuelva a colocar el sector en la unidad con el if y los argumentos invertidos:

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

@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 fue comenzar con un archivo JPEG y abrirlo en un editor hexadecimal. El particular que utilicé fue Bless, que puedes instalar en Ubuntu con un simple apt-get install bendición .

Después de abrir el archivo JPEG en Bless, presioné la página varias veces para meterme en la “carne” del archivo JPEG, y luego realicé unos cincuenta bytes de datos, lo copié y pegué en un editor de texto (en mi caso, gEdit). Esto me dio algo para buscar.

Ahora guardo el JPEG en cada matriz en la máquina virtual. El almacenamiento detrás de los arreglos eran una serie de archivos .qcow2. Una vez que había guardado el JPEG en los arreglos, podía cargar los archivos .qcow2 asociados con cada arreglo en Bless, y buscarlos, no eran muy grandes, no eran más que el JPEG y algunos metadatos, para ese patrón de cincuenta bytes. He resaltado y copiado fuera del JPEG. Voila, tuve el locking para corromper! En este punto, podría editar manualmente los bytes individuales del JPEG como se almacenan en el disco virtual de la máquina virtual utilizando Bless y, lo que es más importante, hacerlo exactamente de la misma manera en cada matriz.

El único problema es que, en el caso de la matriz RAID5 probada en el artículo, tuve que asegurarme de editar la copia real de los datos en la franja, y no la paridad de la franja en sí, era una imagen pequeña en una de lo contrario, vacía la matriz, por lo que no había ningún dato en el bloque SIGUIENTE de la franja, haciendo 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 NECESITAS máquinas virtuales para hacer esto, podrías hacer las mismas cosas de la misma manera con el metal desnudo; simplemente sería más molesto porque necesitaría trabajar con unidades completas en bruto en lugar de con pequeños archivos .qcow2, y tendría que tirar de las unidades y colocarlas en una máquina diferente, o arrancar 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!

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

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 progtwig de muestra que puede comstackr 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 en que se hdparm --fibmap (mencionado por @falconer).

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

( Descargo de responsabilidad: no he probado y no puedo garantizar que el FIBMAP ioctl(2) funcione para un archivo en un dispositivo de bucle invertido o en un sistema de archivos btrfs, pero espero que sí. Supongo que hdparm verificará el tipo de dispositivo antes de realizar el ioctl(2) en el archivo y por lo tanto está fallando.)

 sudo hdparm --fibmap /PATH/TO/FILE 

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