Como posso virar um único bit em um arquivo?

35

Quero danificar intencionalmente um arquivo para testar as alegações de que o btrfs pode se curar . O artigo fala sobre como remover o sistema de arquivos, danificar uma foto "invertendo" um pouco e remontando-a. Nos sistemas de arquivos mais antigos, isso seria corrompido, mas deveria se consertar no btrfs. Em teoria, isso faz sentido, mas eu realmente quero testá-lo.

O problema é que o artigo não explica como fazer nada disso.
Como eu mudaria um único bit em uma parte muito específica de um sistema de arquivos?

Devo também salientar que isso deve ser feito em um sistema de arquivos offline, para que o btrfs não veja minha gravação como intencional.

Edit: Enquanto a pergunta (e discussão) fala muito sobre btrfs, eu gostaria de saber se existem métodos independentes de sistema de arquivos para implementar esse tipo de corrupção (para que possa ser comparado entre diferentes tipos / controladores / etc) de RAID.

Oli
fonte
@ Dan Quero dizer que, se eu editar o arquivo diretamente, o btrfs (ou qualquer sistema de arquivos) contará isso como uma gravação válida. Não daria a corrupção que estou procurando.
Oli
Este é um sistema de arquivos de teste (ou seja, você não se importa com o conteúdo ou está perfeitamente bem com a restauração do backup? Além disso, você está usando uma única partição btrfs em uma única unidade ou uma única partição no topo de uma matriz RAID , ou alguma outra configuração?
Darth Android
1
Se o btrfs suportar os ioctls certos (não tenho certeza se sim), você poderá usar filefrag -vpara descobrir exatamente onde um arquivo está localizado.
derobert
3
@Oli Suspeito que você encontre um público mais interessado em U&L, tanto em termos de votos quanto de respostas. mais isso .
strugee
1
Atire um raio cósmico exatamente no ponto certo.
smcg

Respostas:

20

Não sou especialista, mas o btrfs-progspacote realmente inclui uma ferramenta específica para fazer isso, embora você precise construir a partir do código-fonte. De qualquer forma, depois de instalar ou construir btrfs-progs, você poderá usar a ferramenta btrfs-corrupt-block, usada pelos desenvolvedores do btrfs para testar o sistema de arquivos.

Agora, como eu disse, não tive muito tempo para brincar com o btrfs, então não sei o uso exato dessa ferramenta. Mas com ele, você poderá corromper um sistema de arquivos offline, que será corrigido quando o arquivo corrompido for lido (supondo que você configurou o RAID ou algo assim, para que haja outra cópia a ser usada).

strugee
fonte
2
Achado impressionante! Supondo que btrfs-corrupt-blockrealmente seja escrito como um teste genuíno e não como um "truque" dos desenvolvedores do btrfs, isso deve se encaixar perfeitamente.
allquixotic
@allquixotic Se você quiser aprender mais sobre o btrfs, há uma grande palestra no linux.conf.au 2012 . como eu disse, btrfs-corrupt-blocké usado pelos desenvolvedores, por isso não seria muito útil se fosse um truque :)
strugee
3
@ allquixotic Essa é a beleza do código aberto: você pode olhar o código-fonte do btrfs e verificá-lo! Claro, isso não será uma tarefa fácil, mas se você realmente quiser, poderá fazer isso.
Bakuriu 16/01
@Bakuriu Estou completamente ciente disso. Eu nunca duvidei seriamente que esse btrfs-corrupt-blocknão fosse um teste sincero, pois seria descoberto muito rapidamente por alguém cutucando a fonte e usado como PR negativo contra a Oracle (pelo menos; assim como qualquer outro desenvolvedor / colaborador do btrfs). Foi apenas um comentário inusitado.
allquixotic
Gostaria de saber se o OP (@Oli) quer corromper um bloco (ou seja, a estrutura do sistema de arquivos) ou um arquivo (ou seja, o conteúdo de um arquivo ??) ... E eu acredito que a reivindicação de auto-recuperação do btrfs é sobre o primeiro, não o último? [como um sistema de arquivos saberia qual bit foi invertido em um arquivo? algum tipo de CRC?]. Esta resposta provavelmente está à direita, no entanto, então +1. [mas pode mudar mais do que um "bit único"? ? ou alterar algo que pode ser curado mais facilmente do que um pouco aleatório acontecendo "em qualquer lugar"]
Olivier Dulac
16
  1. Obtenha o valor de um único setor no dispositivo de bloco (por exemplo /dev/sda1) com um deslocamento de 1 milhão de setores (apenas um exemplo):

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

    Esse deslocamento arbitrário de 1M * 512 bytes escolhido é apenas para garantir que você esteja fora da parte de metadados do sistema de arquivos e realmente de um setor que contém dados.

  2. Edite os dados brutos do setor, alterando o conteúdo com um editor hexadecimal. Veja, por exemplo, Precisa de um bom editor hexadecimal para Linux .

  3. Coloque de volta o setor na unidade com os argumentos ife ofinvertidos:

    sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    
gertvdijk
fonte
2
Isso não o ajudará a testar, a menos que o milionésimo bloco seja realmente parte de um arquivo. Como ele pode procurar em que bloco um arquivo específico inicia?
Darth Android
3
Isso é tão quase lá. Se você pode bloquear o comando dd na posição exata do arquivo, provavelmente esta é a melhor maneira de abordar isso.
Oli
@ Oli Sim, eu sei como fazer isso para a família Ext de sistemas de arquivos, mas não tenho muita experiência com btrfs. Deixe-me ver se consigo encontrar um caminho.
precisa saber é
2
@ Oli: você pode simplesmente ter um loop, dd outpouting bloco por bloco (ou seja, como acima, mas "skip = N", N estando em 1..max) até que você possa receber uma linha do arquivo que deseja editar [tente gerar uma linha que não acontecerá em nenhum outro lugar ... por exemplo, use-a em um gerador de senhas e por tempo suficiente?]. Então você edita esse bloco específico. remonte, teste se a alteração foi revertida (o que duvido, veja meu comentário na resposta principal ... parece haver uma confusão entre os dados do arquivo (= conteúdo) e a própria estrutura do sistema de arquivos (= como os arquivos e seu conteúdo são organizados )?)
Olivier Dulac
16

@Oli - oi, eu sou Jim Salter, o cara que realmente escreveu esse artigo. Eu estava trabalhando com uma máquina virtual, o que simplificou as coisas. O que fiz foi iniciado com um arquivo JPEG e aberto em um editor hexadecimal. O que eu usei em particular foi o Bless, que você pode instalar no Ubuntu com um simples apt-get install bless .

Depois de abrir o JPEG no Bless, acertei a página algumas vezes para entrar na "carne" do JPEG e, em seguida, realcei cerca de cinquenta bytes de dados, copiei e colei em um editor de texto (no meu case, gEdit). Isso me deu algo para procurar.

Agora salvei o JPEG em cada matriz na VM. O armazenamento atrás das matrizes era uma série de arquivos .qcow2. Depois de salvar o JPEG nas matrizes, eu poderia carregar os arquivos .qcow2 associados a cada matriz no Bless e pesquisá-los - eles não eram muito grandes, nada mais que o JPEG e alguns metadados - para esse padrão de cinquenta bytes Eu destaquei e copiei o JPEG. Voila, eu tinha o bloqueio para corromper! Nesse ponto, eu poderia editar manualmente bytes individuais do JPEG armazenados no disco virtual da VM usando o Bless - e, o mais importante, fazê-lo exatamente da mesma maneira em cada matriz.

A única desvantagem é que, no caso da matriz RAID5 testada no artigo, eu tive que me certificar de editar a cópia real dos dados na faixa e não a paridade da faixa em si - era uma pequena imagem em um caso contrário, uma matriz vazia, portanto, não havia dados no bloco FOLLOWING na faixa, fazendo com que o bloco de paridade contenha os dados inalterados do bloco de dados. Se eu tivesse editado acidentalmente o bloco de paridade em vez do bloco de dados, a imagem teria aparecido como inalterada.

Uma observação final - você NÃO PRECISA de máquinas virtuais para fazer isso - você pode fazer as mesmas coisas da mesma maneira com o bare metal; seria um pouco mais complicado porque você precisaria trabalhar com unidades brutas inteiras, em vez de com pequenos arquivos .qcow2, e você teria que puxar as unidades e colocá-las em uma máquina diferente ou inicialize em um ambiente ao vivo (ou apenas alternativo) para mexer com eles. (Testei a recuperação de dados do ZFS exatamente dessa maneira, mas em máquinas bare metal reais, há 7 anos atrás, quando me interessei em sistemas de arquivos de última geração.)

Espero que isto ajude!

Jim Salter
fonte
4

Você pode tentar um pequeno programa que será executado no arquivo aberto.FIBMAP ioctl(2)

Por uma rápida pesquisa na web, encontrei esta postagem no blog http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html detalhando como fazer isso - ele ainda fornece um link para um programa de amostra que você pode compilar e executar.

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

É exatamente dessa maneira hdparm --fibmap(mencionada por @falconer) que é implementada.

Depois de encontrar os números dos blocos, você poderá empregar ddgongfu para modificar o arquivo, como @gertvdijk esboçado. Ou talvez você possa apenas modificar o fibmap.cprograma acima para fazer a inversão de bits, gravando diretamente no arquivo do dispositivo ignorando a camada do sistema de arquivos (três parâmetros para o programa: 1. o caminho para o arquivo, 2. arquivo do dispositivo que contém o arquivo 3. offset e bit que você deseja modificar).

( Disclaimer: Eu não testei e não pode garantir que o FIBMAP ioctl(2)irá trabalhar para um arquivo no dispositivo de loopback ou btrfs sistema de arquivos, mas eu fortemente esperar isso acontecer eu estou. Adivinhando hdparm irá verificar o tipo de dispositivo antes de realizar o ioctl(2)sobre o arquivo e, portanto, é falhando.)

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

fornecerá os LBAs onde o arquivo está localizado. Depois disso, você pode usar a resposta de @gertvdijk.

falcoeiro
fonte
Infelizmente, isso não parece funcionar. Está cuspindo a 0,39: device not found in /devÉ porque é btrfs ou (mais provável) porque estou usando em arquivos mantidos em loopback. Vou tentar fazer isso com uma VM "adequada".
Oli
@Oli Hmm. Eu pensei que hdparmfunciona em todos os sistemas de arquivos, mas talvez não seja assim.
Falconer