Jak mogę przerzucić pojedynczy bit w pliku?

35

Chcę celowo uszkodzić plik, aby przetestować twierdzenia, że ​​btrfs może się wyleczyć . Artykuł mówi o zdjęciu systemu plików, uszkodzeniu zdjęcia poprzez „odwrócenie” go i ponowne zamontowanie. W starszych systemach plików byłoby to po prostu uszkodzone, ale powinno naprawić się w btrfs. Teoretycznie ma to sens, ale naprawdę chcę to przetestować.

Problem polega na tym, że artykuł nie wyjaśnia, jak to zrobić.
Jak mógłbym zmienić pojedynczy bit w bardzo określonej części systemu plików?

Powinienem również zaznaczyć, że należy to zrobić w systemie plików offline, aby btrfs nie widział mojego zapisu jako celowego.

Edycja: Podczas gdy pytanie (i dyskusja) dużo mówi o btrfs, chciałbym wiedzieć, czy istnieją niezależne od systemu plików metody implementacji tego rodzaju uszkodzenia (aby można je było porównać z różnymi typami RAID / kontrolerów / itp.).

Oli
źródło
@Dan Mam na myśli, że jeśli dokonam bezpośredniej edycji pliku, btrfs (lub dowolny inny system plików w tym przypadku) uzna to za poprawny zapis. Nie dałoby to zepsucia, którego szukam.
Oli
Czy jest to testowy system plików (tzn. Nie przejmujesz się zawartością, czy przywracanie kopii zapasowej jest w porządku? Czy używasz pojedynczej partycji btrfs na jednym dysku, czy pojedynczej partycji na macierzy RAID? , czy jakaś inna konfiguracja?
Darth Android
1
Jeśli btrfs obsługuje właściwe ioctls (nie jestem pewien, czy tak jest), możesz użyć, filefrag -vaby dowiedzieć się, gdzie dokładnie znajduje się plik.
derobert
3
@Oli Podejrzewam, że znajdziesz więcej zainteresowanych odbiorców na U&L, zarówno pod względem głosów, jak i odpowiedzi. plus to .
strugee
1
Wystrzel promień kosmiczny we właściwe miejsce.
smcg

Odpowiedzi:

20

Nie jestem ekspertem, ale btrfs-progspakiet faktycznie zawiera narzędzie specjalnie do tego celu, chociaż być może będziesz musiał zbudować ze źródła. W każdym razie, po zainstalowaniu lub zbudowaniu btrfs-progs, powinieneś być w stanie użyć narzędzia btrfs-corrupt-block, które jest używane przez programistów btrfs do testowania systemu plików.

Teraz, jak powiedziałem, nie miałem dużo czasu na zabawę z btrfs, więc nie znam dokładnego użycia tego narzędzia. Ale dzięki niemu powinieneś być w stanie uszkodzić system plików offline, który zostanie naprawiony, gdy uszkodzony plik zostanie odczytany (zakładając, że skonfigurowałeś RAID lub coś takiego, aby była inna kopia do użycia).

strugee
źródło
2
Niesamowite znalezisko! Zakładając, że btrfs-corrupt-blocktak naprawdę został napisany jako prawdziwy test, a nie „sztuczka” deweloperów btrfs, powinno to dokładnie pasować do rachunku.
allquixotic
@allquixotic, jeśli chcesz dowiedzieć się więcej o btrfs, jest świetna rozmowa z linux.conf.au 2012 . tak jak powiedziałem, btrfs-corrupt-blockjest używany przez programistów, więc nie byłby bardzo użyteczny, gdyby to była sztuczka :)
strugee
3
@allquixotic To jest piękno open source: możesz spojrzeć na kod źródłowy btrfs i to sprawdzić! Jasne, nie będzie to łatwe zadanie, ale jeśli naprawdę chcesz, możesz to zrobić.
Bakuriu
@ Bakuriu Jestem tego w pełni świadomy. Nigdy poważnie nie wątpiłem, że btrfs-corrupt-blocknie jest to szczery test, ponieważ ktoś bardzo szybko odkryje to źródło i użyje go jako negatywnego PR przeciwko Oracle (przynajmniej; jak również innym programistom / współpracownikom btrfs). To był zwykły komentarz.
allquixotic
Zastanawiam się, czy OP (@Oli) chce uszkodzić blok (tj. Strukturę systemu plików) lub plik (tj. Zawartość pliku?) ... I wierzę, że roszczenie btrfs dotyczące samoleczenia dotyczy pierwsze, a nie drugie? [skąd system plików wiedziałby, który bit został przerzucony w pliku? jakiś CRC?]. Ta odpowiedź jest prawdopodobnie prawidłowa, więc +1. [ale może to zmienić więcej niż „pojedynczy bit”? czy zmienić coś, co można wyleczyć łatwiej niż przypadkowy kawałek, który dzieje się „gdziekolwiek”?]
Olivier Dulac
16
  1. Uzyskaj wartość pojedynczego sektora na urządzeniu blokowym (np. /dev/sda1) Z przesunięciem o 1 milion przesunięć sektorów (tylko przykład):

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

    To dowolnie wybrane przesunięcie 1M * 512 bajtów ma na celu upewnienie się, że nie znajdujesz się w części systemu plików metadanych, a faktycznie w sektorze, który zawiera dane.

  2. Edytuj surowe dane sektora, zmieniając treść za pomocą edytora szesnastkowego. Zobacz na przykład Potrzebujesz dobrego edytora szesnastkowego dla systemu Linux .

  3. Umieść sektor na dysku z odwróconymi argumentami ifi of:

    sudo dd if=/root/mysector of=/dev/sda1 bs=512 count=1 seek=1M
    
gertvdijk
źródło
2
To nie pomoże mu w testowaniu, chyba że 1 milionowy blok faktycznie jest częścią pliku. Jak może sprawdzić, od którego bloku zaczyna się dany plik?
Darth Android
3
To tak prawie. Jeśli możesz zablokować polecenie dd na dokładnej pozycji pliku, jest to prawdopodobnie najlepszy sposób na zbliżenie się do tego.
Oli
@Oli Tak, wiem jak to zrobić dla rodziny systemów plików z rodziny Ext, ale nie mam tak dużego doświadczenia z btrfs. Pokaż mi, czy mogę znaleźć sposób.
gertvdijk
2
@Oli: możesz po prostu mieć pętlę, dd wychodząc z bloku blok po bloku (tj. Jak wyżej, ale „pomiń = N”, N jest w 1..max), dopóki nie możesz grepować linii z pliku, który chcesz edytować [spróbuj wygenerować linię, która nie wydarzy się nigdzie indziej ... na przykład weź ją z generatora haseł i wystarczająco długo?]. Następnie edytujesz ten konkretny blok. podłącz ponownie, sprawdź, czy zmiana została cofnięta (co wątpię, zobacz mój komentarz w górnej odpowiedzi ... wydaje się, że istnieje pomieszanie między danymi pliku (= zawartość) a samą strukturą systemu plików (= sposób organizacji plików i ich zawartości )?)
Olivier Dulac
16

@Oli - cześć, jestem Jim Salter, facet, który napisał ten artykuł. Pracowałem z maszyną wirtualną, co upraszczało sprawę. Zacząłem od pliku JPEG i otworzyłem go w edytorze szesnastkowym. Tym, którego użyłem, był Bless, który możesz zainstalować w Ubuntu za pomocą zwykłego blessa instalacyjnego apt-get .

Po otwarciu pliku JPEG w programie Bless kilka razy przewróciłem stronę w dół, aby dobrze zagłębić się w „mięso” pliku JPEG, a następnie podświetliłem dane o wartości około pięćdziesięciu bajtów, skopiowałem je i wkleiłem w edytorze tekstu (w moim sprawa, gEdit). To dało mi coś do wyszukiwania.

Teraz zapisałem JPEG w każdej tablicy na maszynie wirtualnej. Za tablicami znajdowała się seria plików .qcow2. Kiedy już zapisałem JPEG w tablicach, mogłem załadować pliki .qcow2 związane z każdą tablicą do Bless i przeszukać je - nie były bardzo duże, nie były niczym innym jak JPEG i metadanymi - dla tego pięćdziesięciobajtowego wzorca Podkreśliłem i skopiowałem z JPEG. Voila, miałem blok do zepsucia! W tym momencie mogłem po prostu ręcznie edytować poszczególne bajty JPEG zapisane na dysku wirtualnym maszyny wirtualnej za pomocą Bless - i, co ważne, zrobić to w dokładnie taki sam sposób dla każdej tablicy.

Jedynym zmarszczeniem jest to, że w przypadku testowanej w artykule macierzy RAID5 musiałem upewnić się, że edytowałem rzeczywistą kopię danych w pasku, a nie parzystość dla samego paska - był to mały obraz na w przeciwnym razie pusta tablica, więc w bloku FOLLOWING w pasku nie było żadnych danych, dzięki czemu blok parzystości zawiera dane niezmienione z bloku danych. Gdybym przypadkowo edytował blok parzystości zamiast bloku danych, obraz byłby wyświetlany jako niezmieniony.

Ostatnia uwaga - nie potrzebujesz do tego maszyn wirtualnych - możesz robić te same rzeczy w ten sam sposób z gołym metalem; byłoby to bardziej kłopotliwe w tyłku, ponieważ musiałbyś pracować z całymi surowymi dyskami zamiast z ładnymi małymi plikami .qcow2, i musiałbyś albo wyciągnąć dyski i umieścić je na innej maszynie, lub uruchom się w środowisku na żywo (lub po prostu innym), aby z nimi zadzierać. (Testowałem uzdrawianie danych ZFS właśnie w ten sposób, ale na prawdziwych maszynach bez systemu metalowego, 7 lat temu, kiedy po raz pierwszy zainteresowałem się systemami plików nowej generacji.)

Mam nadzieję że to pomoże!

Jim Salter
źródło
4

Możesz wypróbować mały program, który będzie działał na otwartym pliku.FIBMAP ioctl(2)

Dzięki szybkiemu wyszukiwaniu w Internecie znalazłem ten post na blogu http://smackerelofopinion.blogspot.tw/2009/06/fibmap-ioctl-file-system-block-number.html szczegółowo opisujący, jak to zrobić - poda nawet link do przykładowego programu, który możesz samodzielnie skompilować i uruchomić.

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

Dokładnie tak hdparm --fibmapjest zaimplementowany (wspomniany przez @falconer).

Po znalezieniu numerów bloków możesz użyć ddgongfu do modyfikacji pliku, na przykład naszkicowany @gertvdijk. A może możesz po prostu zmodyfikować fibmap.cpowyższy program, aby wykonać bit flip dla siebie, bezpośrednio zapisując do pliku urządzenia z pominięciem warstwy systemu plików (trzy parametry dla programu: 1. ścieżka do pliku, 2. plik urządzenia zawierający plik system, 3. offset i bit, który chcesz zmodyfikować).

( Oświadczenie: Nie testowałem i nie mogę zagwarantować, że FIBMAP ioctl(2)będzie działał dla pliku w urządzeniu z pętlą zwrotną lub w systemie plików btrfs, ale zdecydowanie bym się tego spodziewał. Zgaduję, hdparm że sprawdzę typ urządzenia przed wykonaniem ioctl(2)pliku i dlatego jest w braku.)

FooF
źródło
3
sudo hdparm --fibmap /PATH/TO/FILE

poda LBA, w których znajduje się plik. Następnie możesz użyć odpowiedzi @gertvdijk.

sokolnik
źródło
Niestety to nie działa. Wyrzuca to 0,39: device not found in /devalbo dlatego, że jest to btrfs, albo (bardziej prawdopodobne), ponieważ używam go do plików przechowywanych w pętli zwrotnej. Spróbuję to zrobić z „właściwą” maszyną wirtualną.
Oli
@Oli Hmm. Myślałem, że hdparmdziała na każdym systemie plików, ale może tak nie jest.
sokolnik