Jak wyodrębnić segment pliku binarnego na podstawie początkowych i końcowych ciągów szesnastkowych

1

Mam duży plik binarny (kilkaset GB) i chcę z niego wyodrębnić segment. Znam szesnastkowe ciągi początkowych i końcowych punktów.

Hyatt
źródło

Odpowiedzi:

2

Możliwe rozwiązanie (zakładając, że możesz zrobić kopię pliku) może skorzystać z następującego przykładu

  1. Załóżmy, że wzorzec początkowy to hex 4f 0f 87 82
  2. zakładamy, że wzór końcowy to hex fb 8c e2 a0
  3. Załóżmy, że plik wejściowy jest wywoływany tfi ma długość 5000 bajtów

następnie

wykonaj kopię tfnowego pliku blahze zmienionym wzorcem początkowym

$ LC_ALL=C sed 's/'`printf "\x4f\x0f\x87\x82"`'/'`printf "AAAA"`'/'  <tf > blah

teraz znajdź lokalizację gdzie tfi się blahróżnią ( uwaga - sed zapisuje dodatkowy bajt zawierający nowy wiersz na końcu zmodyfikowanego pliku, więc porównujemy do długości oryginalnego pliku tf. Wygenerowany plik blahpowinien być o jeden bajt dłuższy ).

$ cmp -n 5000 -b tf blah

da to offset bajtowy, bs, gdzie pliki się różnią, np.

tf blah differ: byte 4337, line 10 is 117 O 101 A

teraz zrób to samo dla zakończenia wzoru

 $ LC_ALL=C sed  's/'`printf "\xfb\x8c\xe2\xa0"`'/'`printf "AAAA"`'/'  < tf > blah2
 $ cmp -n 5000 -b tf blah2
 tf blah2 differ: byte 4433, line 10 is 373 ? 101 A

teraz użyj, ddaby wyodrębnić część zainteresowania

dd if=tf skip=4336 bs=1 count=100 > fbit

Kilka dodatkowych notatek:

  1. niektóre wersje sed obsługują -bopcję, która traktuje plik wejściowy jako binarny. Inne wersje mają -zopcję oddzielającą wiersze znakami NUL. W obu przypadkach pasujące wzorce zawierające nową linię lub podział na nową linię nie zostały przetestowane.

  2. count=100zależy od długości wzoru dopasowane i czy dopasowanym wzorcem być zawarte w wyciągu (nie był jasny w tej kwestii). Ogólna formuła to liczba = (przesunięcie końcowe) - (przesunięcie początkowe) + (rozmiar wzoru końcowego) . Fragmenty dla konkretnego przykładu to 4433-4337 + 1, co daje 97 bajtów. To jest od początku wzorca początkowego do pierwszego bajtu wzorca końcowego włącznie. Dodatkowe 3 bajty są następnie dodawane, aby dać 100 w tym przykładzie, ponieważ końcowy wzorzec miał cztery bajty, a przykład zawiera końcowy wzorzec. Jeśli końcowy wzorzec nie był pożądany, count=96byłaby to wartość.

  3. możliwe jest podejście bardziej odporne na nowe linie i użycie polecenia hexdump. Nie w pełni przetestowałem to podejście. Zasadniczo użyłby hexdump z odrobiną sed, grep i tr, aby przekonwertować oryginalny plik binarny na hex w formie ascii. Wtedy można zastosować ten sam proces, ale z bardziej skomplikowaną arytmetyką itp. Potrzebne byłoby polecenie hexdump

    hexdump -v -x tf | sed s/'^[0-9]*\(.*\)/\1/' | sed s'/ *//g' | grep '[0-9]' | tr -d '\n' > tf.txt

  4. Po hexdumpetapie można zastosować ten sam proces sedi cmp. Dopasowany wzorzec musiałby zostać zaktualizowany, aby używać znaków ascii w postaci zrzutu heksowego, a nie surowego wydruku szesnastkowego.

  5. To podejście powinno także obsługiwać znaki nowego wiersza.

  6. LC_ALL=Cwydaje się być domyślnie potrzebny w OSX. Bez tego sedpolecenie powoduje błąd RE error: illegal byte sequence. Może nie być to prawdą na wszystkich platformach i / lub dystrybucjach systemów operacyjnych.

Chris Hill
źródło
(1) Jak się masz 96? (Wskazówka: Pomyśl o tym. Wierzę, że to źle.) (2) To nie zadziała, jeśli jednym ze znanych bajtów jest hex 0A. Czy potrafisz rozszerzyć swoją odpowiedź na tę sprawę? (3) Czy jest LC_ALL=Cpotrzebny? Czy możesz mi wytłumaczyć dlaczego? (4) Podobnie, czy możesz wyjaśnić, dlaczego -n 5000jest potrzebny? (5) Proszę zbadać „UUOC”. …………………………………………………………………………………………… Proszę nie odpowiadać w komentarzach; edytuj swoją odpowiedź, aby była jaśniejsza i bardziej kompletna.
G-Man,
edytowane - dziękuję za informację.
Chris Hill,
Chciałem powiedzieć, że myślałem, że się 98myliłem (to 96była literówka). Jest tak, ponieważ twoja odpowiedź pokazuje przykładowy wzorzec końcowy, który ma cztery bajty. W przeciwnym razie dobra robota.
G-Man,
Oczywiście wszystko, co musisz zrobić, to rozmiar = (przesunięcie końcowe) - (przesunięcie początkowe) + (rozmiar wzoru końcowego) . Podział 4 na 1 + 3 to tylko komplikacja.
G-Man