Na ogół zespół programistów nie musi zagłębiać się w strukturę binarną plików. Zdarzają się jednak przypadki, kiedy należy pochylić się nad omawianym tematem. Powodem ku temu może być chociażby realizacja powiązanego dziedzinowo projektu. Nie zawsze tak jest. Bywa, że stworzone oprogramowanie nie jest w pełni zoptymalizowane lub klient oczekuje szybszego działania. Stosując wzorce projektowe i dobre praktyki nie zawsze da się osiągnąć pożądany rezultat przy zachowaniu ustalonego budżetu. Dlatego też w celu uzyskania lepszej optymalizacji często zachodzi potrzeba wejścia w strukturę plików, które często wykorzystywane są jako magazyn danych.

Zagadnienie to nie należy do najłatwiejszych, ale jest elementarne jeżeli chodzi o działanie systemów operacyjnych. Żeby zrozumieć z czym ma się do czynienia, należy najpierw pojąć jak rozumieć plik w ogólnej abstrakcji. Ikona wraz z rozszerzeniem oraz wyświetlana zawartość na pewno nie stanowi jego definicji. Pomimo wielu lat doświadczenia, zauważyliśmy, że sporo osób z branży (znających wzorce projektowe, zasady SOLID oraz wszystkie zagadnienia powiązane z technikami takimi, jak TDD czy BDD) nie do końca rozumie czym jest plik. Najprościej rzecz ujmując, plik to abstrakcja systemu operacyjnego pozwalająca przechowywać dane na nośniku informacji. Każdy plik zdefiniowany według określonego standardu zwanego typem posiada określony nagłówek oraz sekcje przeznaczone na informacje.

Systemy operacyjne, w zależności od implementacji, rozpoznają typy plików na podstawie nagłówków lub rozszerzeń. To drugie podejście popularne jest w systemach operacyjnych Windows. Jest to oczywiście uproszczenie, ponieważ rozszerzenie to tylko ciąg znaków dodanych po kropce do nazwy pliku. Nie ma żadnego wpływu na rzeczywisty typ pliku oraz jego zawartość. Umożliwia jedynie skojarzenie go z domyślnym oprogramowaniem. Systemy z rodziny Linux respektują natomiast (w większości) nagłówki plików. Takie podejście jest znacznie lepsze z wielu względów, lecz to temat na osobny wpis.

Aby przybliżyć nieco strukturę plików posłużymy się przykładem pliku typu Portable Network Graphics (PNG) o wymiarach 1024×683. Do podglądu surowych danych binarnych wykorzystamy oprogramowanie stworzone przez Maëla Hörz – HxD. Można pobrać go z oficjalnej strony programisty. Zgodnie z oficjalną dokumentacją, plik PNG posiada ośmiobajtowy podpis w nagłówku, metadane zawarte w strukturze zwanej IHDR oraz segmenty danych IDAT zakończone segmentem IEND. Na przedstawionym poniżej obrazie można dostrzec zaznaczony segment z podpisem zawartym w nagłówku.

Na tym etapie można przyznać, że bez eskperckiej wiedzy lub dokumentacji ciężko znaleźć interesujące informacje. Pierwszy bajt o wartości 0x89 określa specjalny bit na pozycji najbardziej znaczącej (w kodowaniu binarnym) i jest integralną częścią nagłówka pliku PNG. Kolejne 3 bajty o wartościach 0x50, 0x4E oraz 0x47 to ciąg znaków ASCII o wartości "PNG". Jest to tzw. bezpośredni podpis pliku. Następne dwa bajty wskazują na znaki kończące linie w systemie typu msdos w reprezentacji ASCII. 0xD oraz 0xA to kolejno znak powrotu karetki (na początek linii) i znak nowej linii, reprezentowane często jako \r i \n. Pozostałe dwa bajty oznaczają reprezentację specjalnego znaku End Of File (EOF) oraz zakończenia linii w systemach Unix. Oczywiście taka analiza jest bardzo powolna. Dlatego też powstało bardziej zaawansowane oprogramowanie, które umożliwia wykorzystanie wzorców struktury plików w oparciu o oficjalne dokumentacje. Rozwiązania te są wciąż niszowe, ale do jednego z bardziej popularnych można zaliczyć ImHex.

ImHex od razu dopasowuje strukturę pliku z dokumentacji (a konkretniej, na podstawie specjalnego języka służącego do tworzenia wzorców plików). Oprócz widocznego w HxD podpisu w nagłówku, mamy tutaj wgląd bezpośrednio w strukturę IHDR oraz poszczególne segmenty IDAT. Oprócz podświetlenia konkretnych elementów ImHex umożliwia również odczyt typu pliku oraz jego wartość rzutowaną do postaci dziesiętnej. W ten sposób można w łatwy sposób sprawdzić, czy rzeczywiste wymiary obrazu zgadzają się z tymi wewnątrz nagłówka pliku. Oprogramowanie tego typu pozwala jeszcze lepiej zrozumieć strukturę przetwarzanych informacji oraz dokonać często niemożliwej z poziomu gotowych frameworków optymalizacji.


