How can I flip a single bit in a file?

Solution 1:

I'm not an expert, but the btrfs-progs package actually includes a tool specifically to do this, although you may have to build from source. In any case, once you have installed or built btrfs-progs, you should be able to use the tool btrfs-corrupt-block, which is used by the btrfs developers to test the filesystem.

Now, like I said, I haven't had a lot of time to play around with btrfs, so I don't know the exact usage of this tool. But with it, you should be able to corrupt an offline filesystem, which will be fixed when the corrupted file is read (assuming that you have set up RAID or something so that there's another copy to use).

Solution 2:

@Oli - hi, I'm Jim Salter, the guy who actually wrote that article. I was working with a virtual machine, which made things simpler. What I did is started out with a JPEG file, and opened it up in a hex editor. The particular one that I used was Bless, which you can install in Ubuntu with a simple apt-get install bless.

After opening up the JPEG in Bless, I hit page down a few times to get well into the "meat" of the JPEG, and then just highlighted about fifty bytes worth of data, and copied and pasted it into a text editor (in my case, gEdit). This gave me something to search for.

Now I saved the JPEG into each array on the VM. The storage behind the arrays were a series of .qcow2 files. Once I'd saved the JPEG into the arrays, I could load the .qcow2 files associated with each array into Bless, and search them - they weren't very large, being nothing but the JPEG and some metadata - for that fifty byte pattern I'd highlighted and copied out of the JPEG. Voila, I had the block to corrupt! At this point, I could just manually edit individual bytes of the JPEG as stored on the VM's virtual disk using Bless - and, importantly, do so in exactly the same way on each array.

The only wrinkle is that in the case of the RAID5 array tested in the article, I had to make sure I edited the actual copy of the data in the stripe, and not the parity for the stripe itself - it was a small image on an otherwise empty array, so there wasn't any data in the FOLLOWING block in the stripe, making the parity block contain the data unaltered from the data block. If I'd accidentally edited the parity block instead of the data block, the image would have shown up as unchanged.

One final note - you don't NEED virtual machines to do this - you could do the same things in the same ways with bare metal; it would just be more of a pain in the butt because you'd need to work with entire raw drives instead of with nice small .qcow2 files, and you'd either have to pull the drives and put them in a different machine, or boot into a live (or just alternate) environment to mess with them. (I tested ZFS's data healing in exactly this way, but on real bare metal machines, 7-ish years ago when I first got interested in next-gen filesystems.)

Hope this helps!

Solution 3:

  1. Get the value of a single sector on the block device (e.g. /dev/sda1) with an offset of 1 million sectors offset (just an example):

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

    This arbitrary chosen 1M * 512 bytes offset is just to make sure you're out of the metadata part of the filesystem and actually on a sector which contains data.

  2. Edit the raw sector data by changing the content with a hex editor. See for example Need a good hex editor for Linux.

  3. Put back the sector on the drive with the if and of arguments reversed:

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