Format BMP okiem hakera


Format BMP okiem hakera
Atak
Michał Gynvael Coldwind Składnikiewicz
stopień trudności
Pliki graficzne są dziś szeroko rozpowszechnionym nośnikiem
informacji, spotyka się je praktycznie na każdym komputerze.
Dobry programista powinien wiedzieć jak wyglądają nagłówki
poszczególnych formatów plików graficznych, i jak są
przechowywany jest sam obraz. A jak to zwykle bywa, diabeł tkwi
w szczegółach.
iniejszy artykuł ma na celu zapoznać niezależnie od wersji) która zawiera m.in. iden-
czytelnika z formatem przechowywa- tyfikator pliku  tzw. liczbę magiczną (ang. ma-
Nnia obrazu BMP, wskazać w nich miej- gic number), oraz offset na którym znajdują się
sca które można wykorzystać do przemycenia dane bitmapy. Bezpośrednio po BITMAPFILE-
ukrytych danych, miejsca w których programi- HEADER, na offsecie 0Eh, znajduje się struktu-
sta może popełnić błąd podczas implementacji ra BITMAPINFOHEADER (dodam że deklara-
oraz zapoznać ze samym formatem. Przykła- cje omawianych struktur można znalezć w pliku
dy będą w miarę możliwości zilustrowane pew- wingdi.h w Platform SDK), która zawiera infor-
nymi bugami w istniejącym oprogramowaniu, macje o obrazie, jego rozdzielczości, głębi kolo-
znalezionymi przez autora oraz inne osoby. rów czy użytej metody kodowania/kompresji. W
przypadku bitmap o głębi 4 lub 8 bitów, zaraz za
Wstęp do BMP strukturą BITMAPINFOHEADER znajduje się
Niesławny format BMP znany jest przede
wszystkim z plików o ogromnych wielkościach
(w porównaniu do JPEG czy PNG). Format ten
Z artykułu dowiesz się
stworzony został przez firmy IBM oraz Microsoft
" jak zbudowany jest plik BMP,
na potrzeby systemów OS/2 oraz Windows, obie
" na co uważać podczas implementowania ob-
firmy rozwijały go jednak oddzielnie, co spowo-
sługi formatu BMP,
dowało powstanie kilku wariantów tego formatu.
" gdzie szukać błędów w aplikacjach korzystają-
Niniejszy tekst skupia się na BMP w wersji Win-
cych z BMP.
dows V3, pozostałe wersje (OS/2 V1 i V2 oraz
Windows V4 i V5) pozostawiam czytelnikowi do
własnej analizy jako zadanie domowe :).
Co powinieneś wiedzieć
Niezależnie od wersji, ogólna budowa pli-
ku, przedstawiona na Rysunku 1, pozostaje ta- " mieć ogólne pojęcie na temat plików binarnych,
" mieć ogólne pojęcie na temat bitmap.
ka sama. Na samym początku pliku znajduje się
struktura BITMAPFILEHEADER (jest ona stała,
hakin9 Nr 3/2008
2 www.hakin9.org
Format BMP okiem hakera
paleta barw, którą jest odpowiedniej ile wg. bfSize jest potrzebne, po czym
wielkości tablica struktur RGBQUAD. wczytał cały plik (aż do końca) do za-
W przypadku bitmap o głębi kolorów alokowanego bufora. Funkcja działa
16 bitów zamiast palety barw w tym wyśmienicie, pod warunkiem że war-
miejscu znajduję się prosta struktura tość bfSize jest równa lub większa od
składająca się z trzech DWORD'ów faktycznej wielkości pliku. Jeśli war-
które są maskami bitowymi określa- tość bfSize będzie mniejsza, dojdzie
jącymi które bity w danych obrazu od- do klasycznego błędu przepełnienia
powiadają za barwę, kolejno, czerwo- bufora  który wprawny włamywacz
ną, zieloną oraz niebieską, natomiast mógł by wykorzystać do wykonania
w bitmapach, o głębi 24 bity lub więk- własnego kodu. Dobrym pomysłem
szejm paleta barw nie występuje. Da- jest zignorowanie wartości tego pola,
ne obrazu zaczynają się na offsecie i korzystanie jedynie z wielkości pliku
podanym w BITMAPFILEHEADER, otrzymanej od systemu plików. Sta-
zazwyczaj od razu po ostatnim na- nowcza większość aplikacji faktycz-
główku. Budowa danych zależy za nie ignoruje to pole, co z kolei pozwa-
równo od użytego kodowania jak i la wykorzystać je w celu ukrycia 32
głębi kolorów. bitów danych.
Tak przedstawia się ogólna budo- Dwa kolejne pola  bfReserved1
wa formatu BMP. Szczegółowa budo- oraz bfReserved2  według specyfi-
wa formatu BMP przedstawiona jest kacji powinny być wyzerowane, po-
Rysunek 1. Budowa pliku BMP
w dalszej części artykułu. nieważ są zarezerwowane na przy-
szłość. Póki co są jednak niewyko- Na początek najbardziej trywialny
Nagłówek rzystywane, więc mogą posłużyć do  programista z góry zakłada że da-
BITMAPFILEHEADER ukrycia kolejnych 32 bitów danych ne obrazu znajdują się za nagłówka-
Nagłówek BITMAPFILEHEADER (oba pola są WORDami, czyli mają mi i ignoruje pole bfOffBits  tak dzia-
(patrz Tabela 1) rozpoczyna się na po 16 bitów każde). Warto zaznaczyć ło się w przypadku starszych wersji
początku pliku (offset 0) i ma wielkość iż żadna z testowanych przez auto- Total Commander (na przykład 6.51,
14 bajtów (0Eh). Najmniej interesują- ra aplikacji nie sprawdzała czy w w/w wersje nowsze, na przykład 7.01 nie
cym polem struktury jest pierwsze po- polach faktycznie znajdują się zera. ignorują już tego pola). Pomijając pro-
le  bfType, które zawsze ma wartość Ostatnie pole stanowi kolejną pu- blemy z wyświetlaniem prawidłowych
odpowiadającą ciągowi ASCII BM. łapkę. Pole bfOffBits, bo o nim mowa, bitmap które mają dane obrazu odsu-
Kolejnym polem jest DWORD bfSi- jest 32 bitową wartością bez znaku nięte od nagłówków, pozwala to na
ze w którym wg. specyfikacji powinna (DWORD, czyli w terminologii C jest przykład stworzyć plik BMP który wy-
znalezć się całkowita wielkość pliku w to unsigned int) która mówi o tym w świetlany w Total Commanderze bę-
bajtach. Wielkość pliku prawidłowego którym miejscu pliku (a dokładniej, dzie prezentował inną grafikę niż gdy-
pliku łatwo obliczyć dodając wielko- od którego bajtu pliku) zaczynają się by ten tam plik BMP podać innej, pra-
ści poszczególnych nagłówków, pale- faktyczne dane obrazu. Zdarzają się widłowo obsługującej pole bfOffBits,
ty barw oraz danych obrazu. To pole przypadki w których to pole jest wy- aplikacji. Taki właśnie efekt zapre-
stanowi pierwszą pułapkę, ale w nią zerowane  część aplikacji w tym wy- zentowany jest na Rysunku 2 (użyte
wpadają jedynie nieuważni programi- padku uznaje że dane obrazu znajdu- grafiki pochodzą z http://icanhasche-
ści. Rozważmy kod z Listingu 1  pro- ją się bezpośrednio za nagłówkami. ezburger.com), dla ukazania efektu
gramista wczytał nagłówek, zaufał Programista implementujący obsłu- ten sam plik BMP podano Listerowi
polu bfSize i zaalokował tyle pamięci gę BMP może popełnić kilka błędów. (część Total Commandera odpowie-
dzialna za podgląd plików) oraz Irfa-
Tabela 1. Struktura BITMAPFILEHEADER
nView 4.10. Należy zaznaczyć iż plik
Typ i nazwa pola Opis jest oczywiście dwa razy większy niż
byłby normalnie (ponieważ zawiera
WORD bfType Identyfikator BMP, zazwyczaj lite-
dwa obrazki).
ry  BM
Drugim błędem który programi-
DWORD bfSize Całkowita wielkość pliku
sta może popełnić jest założenie że
WORD bfReserved1 Zarezerwowane, zaleca się nadanie
polu bfOffBits można zaufać i będzie
wartości 0
ono na pewno mniejsze od wielkości
WORD bfReserved2 Zarezerwowane, zaleca się nadanie
pliku, a tym bardziej dodatnie (jak pi-
wartości 0
sałem wcześniej jest to DWORD, czy-
li liczbą bez znaku, ale należy pamię-
DWORD bfOffBits Pozycja (offset) danych w pliku
tać że suma dwóch liczb 32 bitowych
www.hakin9.org hakin9 Nr 2/2008 3
Atak
jest nadal liczbą 32 bitową, czyli nie Warto zauważyć iż odsunięcie rokości bitmapy (biWidth), jej wyso-
ma tak na prawdę różnicy czy jest to danych od nagłówków stwarza do- kości (biHeight) oraz głębi kolorów,
DWORD czy SDWORD jeśli nastą- wolną ilość miejsca na ukrycie ewen- czyli ilości bitów które opisują każ-
pi integer overflow). Tego typu błąd, tualnych dodatkowych danych. dy kolejny piksel (biBitCount). War-
niegrozny  ale jednak, występuje w Podsumowując strukturę BIT- tości z tych pól bardzo często służą
Microsoft Paint do wersji 5.1 włącznie MAPFILEHEADER, są tu dwa miej- do wyliczenia całkowitej ilości bajtów
(czyli tej dołączonej do Microsoft Win- sca w których programista może po- potrzebnej do przechowania bitmapy
dows XP SP2, wersja 6.0, dołączo- pełnić błąd, a także 64 bity (8 bajtów) w pamięci. W tym celu implementuje
na do Microsoft Windows Vista, zo- w samym nagłówku, w których moż- się następujące równanie:
stała poprawiona). Przykładowe wy- na zapisać (ukryć) dodatkowe dane.
korzystanie widać na Rysunku 3, ze- PotrzebnaIlośćBajtów =
stawiono na nim aplikację Microsoft Nagłówek Szerokość * Wysokość * (Głębia / 8)
Paint oraz IrfanView, które wyświetla- BITMAPINFOHEADER
ją ten sam plik BMP. Jak można do- Drugim z kolei nagłówkiem plików W przypadku BMP szerokość, czyli
myślić się z rysunku IrfanView posta- BMP w wersji Windows V3 jest BIT- biWidth, w tym równaniu zaokrągla-
nowił zignorować błędnie wypełnione MAPINFOHEADER, struktura skła- na jest w górę do najbliższego iloczy-
pole bfOffBits i uznał że dane obrazu dająca się z 11 pól o łącznej długości nu liczby 4 (więcej o tym będzie w pa-
znajdują się bezpośrednio za nagłów- 40 bajtów (28h), rozpoczynająca się ragrafie Dane obrazu  BI _ RGB), czy-
kami, natomiast mspaint.exe wykonał od offsetu 0Eh. li jeśli bitmapa na przykład ma szero-
operacje WyświetlBitmapę(Początek- Pierwsze pole  biSize  określa kość 109 pikseli, to w tym równaniu
Danych + bfOffBits), co poskutkowa- wielkość niniejszego nagłówka, po zostanie użyta wartość 112. Tak więc
ło wyświetleniem fragmentu pamięci tej wielkości aplikacje rozpoznają czy to równanie w przypadku BMP ma
należącej do aplikacji. Należy dodać nagłówkiem jest faktycznie BITMA- następującą postać:
że w wypadku gdy PoczątekDanych PINFOHEADER, i czy plik BMP jest
+ bfOffBits wskazuje na nieistnieją- na pewno wersją Windows V3 forma- PotrzebnaIlośćBajtów =
cy fragment pamięci, zostaje rzuco- tu BMP. Prawidłową wartością jest ZaokrąglonaSzerokość *
ny wyjątek (Naruszenie Ochrony Pod- oczywiście 40 (28h). Niektóre apli- Wysokość * (Głębia / 8)
czas Odczytu, ang. Read Access Vio- kacje, takie jak IrfanView czy Mozilla,
lation), w wypadku mspaint.exe jest przyjmują że plik BMP jest plikiem w Tak wyliczona wartość używana jest
on jednak obsługiwany. Należy za- wersji Windows V3 nawet w wypad- zazwyczaj do alokacji pamięci na po-
uważyć iż jeżeli tego typu błąd wystą- ku gdy biSize posiada jakąś inną, nie- trzeby docelowej bitmapy. Jest to jed-
pił by w aplikacji posiadającej w pa- znaną, wartość  daje to możliwość nocześnie miejsce, w którym istnie-
mięci wrażliwe dane, to sprawny so- ukrycia kolejnych 32 bitów danych, z je prawdopodobieństwo błędnej im-
cjotechnik mógł by z powodzeniem tym że nie wszystkie programy będą plementacji. Załóżmy na chwilę że
wydobyć od nieświadomego użyt- potrafiły poradzić sobtie z wyświetle- programista założył że PotrzebnaIlo-
kownika zrzut ekranu na którym wi- niem bitmapy w takim wypadku. śćBajtów jest wartością typu LONG
dać zle wyświetlaną bitmapę która tak Drugim, trzecim oraz piątym z lub DWORD (32 bity), a tak się czę-
na prawdę przedstawiała by fragment kolei polem są kolejno biWidth, bi- sto zdarza. Jeżeli wynik równania bę-
pamięci na przykład z hasłem i logi- Height oraz biBitCount. Są to, jak dzie większy od FFFFFFFFh, czy-
nem danego użytkownika. nazwa wskazuje, informacje o sze- li maksymalnej liczby którą można
zapisać w 32 bitowej zmiennej typu
Tabela 2. Struktura BITMAPINFOHEADER całkowitego/naturalnego, to nastą-
pi przepełnienie zmiennej całkowi-
Typ i nazwa pola Opis
tej (ang. Integer Overflow), co z ko-
DWORD biSize Wielkość nagłówka, w tym wypadku 28h
lei może doprowadzić do błędu ty-
LONG biWidth Szerokość bitmapy
pu przepełnienia bufora. Wezmy pod
LONG biHeight Wysokość bitmapy
uwagę kod z Listingu 2. Programista
zaokrągla szerokość po czym wyli-
WORD biPlanes Ilość płaszczyzn, przyjęto wartość 1
cza potrzebną ilość bajtów, a następ-
WORD biBitCount Ilość bitów na piksel
nie alokuje pamięć i wczytuje wiersz
DWORD biCompression Rodzaj zastosowanego kodowania/kompresji
po wierszu całą bitmapę do zaaloko-
DWORD biSizeImage Wielkość nieskompresowanej bitmapy w pamięci
wanej pamięci. Wszystko wydaje się
LONG biXPelsPerMeter DPI poziome być w porządku, ale załóżmy na chwi-
lę że otrzymaliśmy bitmapę o wielko-
LONG biYPelsPerMeter DPI pionowe
ści 65536x65536x8, czyli szerokość
DWORD biClrUsed Użyta ilość kolorów
i wysokość mają wartość 10000h.
DWORD biClrImportant Ilość ważnych kolorów
Po podstawieniu wartości w równa-
www.hakin9.org
4 hakin9 Nr 2/2008
Format BMP okiem hakera
niu na potrzebną ilość bajtów otrzy-
Listing 1. Niebezpieczny kod wczytujący bitmapę
mamy 10000h * 10000h * (8/8), czy-
li 100000000h. DWORD pomieścić
void *ReadBMPtoMemory(const char *name, unsigned int *size)
może jedynie najmłodsze 32 bity tej
{
liczby, w związku z czym w zmiennej char *data = NULL;
BITMAPFILEHEADER bmfh;
size zapisane zostanie 00000000h,
FILE *f = NULL;
czyli 0. Następnie dojdzie do aloka-
size_t ret = 0;
cji pamięci, która zakończy się suk-
/* Otwórz plik */
cesem (przykładowo system Win-
f = fopen(name,  rb );
dows zaalokuje 16 bajtów, mimo ze if(!f) return NULL;
/* Wczytaj naglowek i zaalokuj pamięć */
malloc dostał 0 w parametrze), a po-
fread(&bmfh, 1, sizeof(bmfh));
tem zostanie w to miejsce wczytane
*size = bmfh.bfSize;
65536 wierszy po 65536 pikseli każ-
data = malloc(bmfh.bfSize);
dy, czyli 4 GB danych, co spowodu-
if(!data) goto err;
je przepełnienie bufora oraz wyrzuce- memset(data, 0, bmfh.bfSize);
/* Wczytaj plik */
nie wyjątku (ang. Write Access Viola-
fseek(f, 0, SEEK_SET);
tion). W przypadku gdy wyjątek zosta-
do {
nie obsłużony prawdopodobnie bę-
ret += fread(data + ret, 1, 0x1000, f);
dzie również możliwość wykonania
} while(!feof(f));
kodu, a w wypadku gdy nie zostanie /* Powrót */
fclose(f);
obsłużony, aplikacja po prostu zakoń-
return data;
czy działanie z odpowiednim komuni-
/* Obsluga bledow */
kacje o błędzie.
err:
Czwartym z kolei polem, pomi-
if(f) fclose(f);
niętym wcześniej, jest biPlanes, które if(data) free(data);
return NULL;
mówi o ilości płaszczyzn. Przyjęte jest
}
że w tym polu powinna być wartość 1.
Niektóre programy ignorują wartość
tego pola, przez co możliwe jest ukry-
cie kolejnych 16 bitów danych. W przypadku tego pola pułapka wy- jąć bardzo małą wartość (na przykład
Kolejnym, szóstym polem jest gląda bardzo podobnie jak w przy- 1), i wtedy nawet mała bitmapa może
biCompression field. To pole przyj- padku pola bfSize z BITMAPFILEHE- zająć kilkanaście kartek A4, lub bar-
muje pewne z góry ustalone war- ADER, zaleca się więc zignorowanie dzo dużą wartość, przez co cała bit-
tości które mówią o sposobie ko- wartości tego pola. Nieostrożne uży- mapa będzie wielkości milimetr na mi-
dowania i kompresji użytej w przy- cie wartości biSizeImage przy aloka- limetr. To pole może zostać wykorzy-
padku danego pliku BMP. Dostęp- cji pamięci, a następnie brak kontro- stane również do przechowania pew-
ne wartości w BMP Windows V3 to li pozycji wskaznika zapisu przy de- nej informacji (64 bity łącznie), szcze-
BI _ RGB (0), BI _ RLE8 (1), BI _ RLE4 kompresji może prowadzić do prze- gólnie jeśli nie zależy nam na popraw-
(2) oraz BI _ BITFIELDS (3). Kolejne pełnienia bufora. ności rozdzielczości drukowanej.
wersje formatu BMP zakładają rów- Dwa kolejne pola  biXPelsPerMe- Przedostatnim polem jest biClrU-
nież dwie inne wartości: BI _ JPEG (4) ter oraz biYPelsPerMeter  mówią o sed które mówi o ilości kolorów w pa-
oraz BI _ PNG (5). Różne rodzaje ko- poziomej i pionowej ilości pikseli przy- lecie barw. Jeżeli to pole jest wyzero-
dowanie BMP są omówione w kolej- padających na metr (informacja ana- wane, przyjmuje się że ilość kolorów
nych podpunktach. logiczna do DPI, ang. Dots Per Inch). w palecie jest równa liczbie 2 podnie-
Następnym polem jest biSizeIma- Informacje te są potrzebne głównie w sionej do potęgi biBitCount (do 8 bi-
ge określające całkowitą wielkość bit- przypadku drukowania danej bitma- tów włącznie), czyli na przykład w
mapy po ewentualnej dekompresji py. Pojawia się tutaj pewna grozba w przypadku 8-bitowej bitmapy przyj-
(jeżeli bitmapa nie jest kompresowa- przypadku implementacji drukowania muje się że paleta ma 256 kolorów.
na, to pole może być ustawione na 0). bitmap  rozdzielczość ta może przy- Co ciekawe, programiści mają ten-
dencje ufać temu polu i zakładać że
Tabela 3. Struktura RGBQUAD
jeżeli biClrUser wynosi na przykład 1,
Typ i nazwa pola Opis
to w bitmapie pojawi się jedynie pierw-
BYTE rgbBlue Wartość barwy niebieskiej szy z kolei kolor, czyli 00. Jeżeli w bit-
mapie pojawi się więcej kolorów pra-
BYTE rgbGreen Wartość barwy zielonej
widłowym działaniem powinno być al-
BYTE rgbRed Wartość barwy czerwonej
bo wyświetlanie pozostałych kolorów
BYTE rgbReserved Zarezerwowane
jako czarny (czyli wyzerowanie pozo-
www.hakin9.org hakin9 Nr 2/2008 5
Atak
stałej części palety), albo wykonanie
operacji modulo (wyświetlony _ kolor
= kolor % biClrUsed). Tak zachowu-
ją się MSPaint, Internet Explorer, czy
Paint Shop Pro. Bardzo dużo progra-
mów jednak rysuje bitmapę na swój
własny sposób, czego przykład jest
przedstawiony na Rysunku 4. W tym
miejscu należało by się zaintereso-
wać czemu tak się dzieje, oraz skąd
się biorą pozostałe kolory  ponie-
waż w palecie w pliku BMP zadekla- Rysunek 2. Wykorzystanie ignorowania pola bfOffBits
rowany został tylko jeden. Odpowiedz
na to drugie pytanie jest dość prosta te przeglądarki obsługują wprowadzo- nika na wyciek informacji a nawet wy-
 najwyrazniej programy alokują pa- ny w HTML 5 tag , który umoż- konanie kodu. Dodatkowo w tym na-
mięć na pełną paletę kolorów (256 ko- liwia rysowanie po płótnie, kopiowa- główku można ukryć kolejne bajty
lorów), po czym wczytują z pliku ca- nie bitmap z tagów na płótno, informacji dodatkowych, niezwiąza-
łą tam zawartą paletę (1 kolor). Resz- oraz odczyt wartości kolorów z płótna. nych z bitmapą.
ta palety, jako że nie była wyzerowa- Możliwe jest więc stworzenie skryptu
na, zawiera w takim przypadku dane który wyświetli odpowiednio sprepa- Paleta barw
które znajdowały się wcześniej w pa- rowany plik BMP a następnie skopiuje Paleta barw jest tablicą struktur
mięci, a konkretniej na stogu (ang. he- go na canvas, odczyta wartości kolo- RGBQUAD (patrz Tabela 3) które
ap). Drugą możliwa odpowiedz jest ta- rów i prześle je na zdalny serwer. Wg. opisują wartość barw, kolejno niebie-
ka że program alokuje paletę o wielko- badań przeprowadzonych przez au- skiej, zielonej i czerwonej, danego ko-
ści biClrUsed, a kolory powyżej biCl- tora dane przesyłane na zdalny ser- loru. Dodatkowo każda struktura do-
rUsed po prostu korzystają z pamię- wer mogą zawierać fragmenty innych pełniona jest jedno bajtowym po-
ci po za paletą tak jak by to był dalszy stron, fragmenty ulubionych, fragmen- lem rgbReserved, dzięki czemu cała
ciąg palety (tzw. boundary condition ty historii oraz inne informacje. W mo- struktura ma wielkość 32 bitów (4 baj-
error). W obu przypadkach kolory któ- mencie pisania tego artykułu powyż- tów). Standard nakazuje aby to ostat-
re według pola biClrUsed nie powinny sza, znaleziona przez autora, luka, nie pole było wyzerowane, jednak w
być używane, są opisane przez dane klasyfikowana jako Remote Informa- rzeczywistości aplikacje nie spraw-
znajdujące się w pamięci. Idąc o krok tion Disclosure, nie została jeszcze dzają tego. To pole może zostać uży-
dalej, można stworzyć BMP o wielko- poprawiona. te do ukrycia dodatkowych informacji,
ści 256x1 w której dane obrazu bę- Ostatnim polem tego nagłówka lub do zapisania kanału alfa (w przy-
dą kolejnymi kolorami, od 00 do FFh, jest biClrImportant  mówiące o ilości padku bitmap 32 bitowych). Paleta
dzięki temu wyświetlona bitmapa bę- istotnych kolorów w bitmapie. Stanow- barw występuje w przypadku bitmap
dzie praktycznie rzecz biorąc skopio- cza większość aplikacji ignoruje jed- 1 (1 bitowa bitmapa wcale nie musi
waną paletą kolorów, czyli na ekranie nak to pole, dzięki czemu może ono być czarno-biała!), 4 oraz 8 bitowych
pojawią się, w postaci kolorowych pik- zostać użyte do przechowania 32 bi- (patrz pole biBitCount z BITMAPIN-
seli, dane z pamięci. Czy jednak moż- tów danych niezwiązanych z bitmapą. FOHEADER). W przypadku tych bit-
na w jakiś sposób przesłać automa- Podsumowując, w nagłówku BIT- map, jeśli pole biClrUsed nie mówi in-
tycznie przesłać tą bitmapę do jakie- MAPINFOHEADER znajduje się wie- aczej, paleta zawiera kolejno 2, 16 lub
goś zdalnego serwera? Okazuje się le pól które nieuważny programista 256 struktur RGBQUAD.
że w przypadku Firefox 2.0.0.11 oraz może potraktować ze zbytnim zaufa-
Opera 9.50 beta jest to możliwe. Obie niem narażając tym samym użytkow- Dane obrazu  BI_RGB
Dane obrazu w przypadku BI_RGB
należy rozważać w dwóch katego-
Listing 2. Niebezpieczny kod alokujący pamięć i wczytujący dane
riach  faktycznych kolorów RGB (bit-
/* Wylicz szerokosc i wielkosc */
mapa 24 bitowa), oraz numerów kolo-
DWORD padded_width = (bmih.biWidth + 3) & (~3);
rów w palecie barw (1 bitowe, 4 bitowe
DWORD size = padded_width * bmih.biHeight * (bmih.biBitCount / 8);
lub 8 bitowe bitmapy). Niemniej jed-
/* Alokacja pamieci */
nak kilka rzeczy jest wspólne. Pierw-
char *data = malloc(size), *p;
if(!data) goto err;
szą z nich jest zapis bitmapy do gó-
/* Wczytaj dane */
ry nogami, czyli pierwsze w pliku znaj-
fseek(f, bmfh.biOffBits, SEEK_SET);
dują się wiersze które trafią na dół bit-
for(p = data, y = 0; y < bmih.biHeight; y++, p += padded_width)
mapy, a kolejne zawierają informa-
fread(p, 1, padded_width, f);
cje o wierszach znajdujących się co-
www.hakin9.org
6 hakin9 Nr 2/2008
Format BMP okiem hakera
raz wyżej w faktycznym obrazie. Dru- rów. W przypadku 8-bitowej bitmapy Większość aplikacji oczekuje że każ-
gą rzeczą jest wspomniane wcześniej w wypadku gdy nie wszystkie kolory dy wiersz będzie zakończony 00 00,
dopełnianie ilości danych (bajtów) w są używane (lub w wypadku bitmap ale istnieją również takie (IrfanView)
wierszy do iloczynu liczby 4. W przy- 1-bitowych i 4-bitowych skonwerto- u których jest to niekonieczne.
padku kiedy iloczyn szerokości i ilości wanych do 8-bitowej bitmapy) moż- 00 01  Zakończenie bitmapy. Je-
bajtów przypadających na piksel nie na ukryć dodatkowe informacje bez żeli pozostały jakieś niezapisane pik-
jest podzielny przez 4, na koniec da- zmiany wyglądu bitmapy poprzez po- sele, nadaje się im kolor 0. 00 02 XX
nych wiersza dopisywana jest odpo- wielenie części palety kolorów i sto- YY  Ten znacznik składa się z czte-
wiednia ilość (od 1 do 3) bajtów zero- sowanie zamiennie kolorów z części rech bajtów. Dwa dodatkowe bajty
wych, tak aby całkowita ilość danych oryginalnej (0) lub powielonej (1). W zawierają liczbę kolumn oraz wier-
opisujących wiersz była iloczynem przypadku 4-bitowych bitmap (czy- szy o jaką wskaznik zapisu należy
liczby 4. Jak się łatwo domyślić żadna li 16-kolorowych) skonwertowanych przesunąć (czyli mówi o tym ile pik-
aplikacja nie sprawdza czy w dopeł- do 8-bitowych paletę kolorów można seli i wierszy dalej znajdują się na-
nieniu zostały użyte zera, można więc powielić 16 razy (256/16 = 16), dzię- stępne dane). Wszystkie pominię-
wykorzystać dopełnienie do ukrycia ki czemu na dobrą sprawę najbardziej te piksele przyjmuje się że mają ko-
własnych danych. Korzystając z tego znaczące 4 bity każdego bajtu mogą lor 0. 00 NN ... (gdzie NN >= 3)  Jest
sposobu można ukryć, w zależności zawierać dowolne ukryte dane. to znacznik przełączający dekompre-
od szerokości wiersza, od 1 do 3 bajty sje w tzw. tryb bezwzględny. Zaraz po
na wiersz razy wysokość bitmapy. Dane obrazu  BI_RLE8 nim następują bajty które nie są zako-
W przypadku 24-bitowej bitmapy Ostatnią poruszaną w tym artykule dowane RLE, a po prostu przepisane
i BI _ RGB kolejne bajty zawierają, po- kwestią dotyczącą BMP jest kodo- z kompresowanej bitmapy  o ilości
dobnie jak w palecie barw, wartość wanie RLE 8-bitowych bitmap. RLE tych bajtów mówi drugi bajt znaczni-
barwy niebieskiej, zielonej oraz czer- (ang. Run Length Encoding) jest bar- ka (oznaczony jako NN). Bajty nastę-
wonej każdego piksela (po 3 bajty na dzo prostą metodą kompresji polega- pujące po znaczniku powinny zostać
piksel). Przykładowo, 00 00 00 zosta- jącą na zapisie danych w postaci pary po prostu przepisane na rozpakowa-
nie wyświetlone na ekranie na kolor ilość wystąpień oraz znak. Przykłado- ną bitmapę. W przypadku gdy liczba
czarny, a 00 FF 00 na kolor zielony. wo ciąg AAAABBB za pomocą RLE NN jest nieparzysta, należy następu-
Popularną metodą steganograficzną został by skompresowany do 4A3B. jące bajty dopełnić jednym bajtem ze-
jest użycie najmniej znaczącego bi- W przypadku BMP za równo ilość rowym, w celu uzyskania parzystej
tu każdej barwy w każdym pikselu do wystąpień oraz znak mają wielkości liczby bajtów. Oczywiście żadna apli-
przechowania ukrytych informacji. jednego bajtu (czyli razem 16 bitów). kacja nie sprawdza czy jest to bajt ze-
W przypadku 8-bitowej bitmapy Oprócz tego BMP RLE posiada rów- rowy, można więc zapełnić do ukryty-
kolejne bajty zawierają numery kolo- nież specjalne znaczniki zaczynające mi informacjami.
rów z palety kolorów, a podczas prze- się od bajtu zerowego (czyli ilość wy- Tak skonstruowana kompre-
noszenia bitmapy na 24-bitowy ekran stąpień wynosi zero), są to: sja RLE stawia wiele pułapek przed
każdy piksel jest zamieniany z nu- 00 00  Przejście na początek programistą, i jednocześnie stwa-
meru koloru na wartości poszcze- następnego wiersza bitmapy (czy- rza wiele miejsc na ukrycie danych.
gólnych barw pobrane z palety kolo- li kolejne dane opisują nowy wiersz, Przykładowo osoba chcąca ukryć da-
przyjmuje się że do końca obec- ne może posłużyć się różnymi sposo-
nego wiersza dane mają kolor 0). bami skompresowania tej samej bit-
Rysunek 4. Ta sama bitmapa różnie
rysowana w różnych programach Rysunek 3. Brak kontroli wartości pola bfOffBits w mspaint.exe
www.hakin9.org hakin9 Nr 2/2008 7
Atak
mapy używając różnych znaczników.
Przykładowo bitmapa składająca się
O autorze
z kolorów AABBBCC może zostać
Michał Składnikiewicz, inżynier informatyki, ma wieloletnie doświadczenie jako pro-
zapisana jako 02 A 03 B 02 C, lub ja- gramista oraz reverse engineer. Obecnie jest koordynatorem działu analiz w między-
ko 01 A 01 A 02 B 01 B 01 C 01 C, lub narodowej firmie specjalizującej się w bezpieczeństwie komputerowym.
Kontakt z autorem: gynvael@coldwind.pl
nawet  korzystając ze specjalnych
znaczników  jako 00 03 A A B 00 00
02 00 00 01 B 02 C. Pomijając spra-
wy skuteczności kompresji, liczba stępnie nadpisanie go dowolnymi da- dynie w części ze standardem mogą
możliwości w jaki sposób można za- nymi. W przypadku IrfanView, który przysporzyć sporo problemów. Wda-
pisać taką bitmapę jest nieskończo- w tej wersji spakowany był ASPac- jąc się w szczegóły techniczne, pro-
na (choćby dlatego że znacznik 00 02 kiem, sytuację dodatkowo pogarszał gramista powinien zwracać uwagę
00 00 można wstawiać bezkarnie do- fakt iż sekcja .text (w której znajdu- szczególnie na sprawdzenia granic
wolną ilość razy)  można więc stwo- je się kod programu, patrz pliki PE) używanych buforów i tablic  bufo-
rzyć pewnego rodzaju kod dzięki któ- miała prawa do zapisu, czyli atakują- ru obrazu, buforu skompresowanych
remu można by przechowywać infor- cy mógł przesunąć wskaznik zapisu danych, czy palety kolorów. Granice,
macje w bitmapie, bez zmiany jej fak- za pomocą serii 00 02 FF FF na sek- co nie dla wszystkich jest oczywi-
tycznego wyglądu. cje .text, a następnie nadpisać znaj- ste, powinny być sprawdzane z obu
Jeżeli zaś chodzi o pułapki, to dujący się tam kod własnym kodem stron, aby zapobiec zarówno błędom
pierwszą rzucającą się w oczy jest  na przykład uruchamiającym back- typu buffer overflow, jak i błędom ty-
przepełnienie bufora w przypad- doora. Nowsze wersje IrfanView (od pu buffer underflow. Programista po-
ku gdy programista nie sprawdzi czy 4.00 włącznie) nie są jednak już po- winien również używać odpowied-
dekompresja pojedynczej pary RLE datne na ten błąd. niego rozmiaru zmiennych, lub sto-
nie przepełni bufora. Aatwo wyobra- Pewien mniej grozny błąd, ale sownego ograniczania wartości, aby
zić sobie przypadek w którym bitma- mogący utrudnić życie użytkowniko- zapobiec sytuacjom z przepełnie-
pa o wielkości 1x1 zawiera w danych wi, znalazł autor (współpracując z ha- niem zmiennej całkowitej (ang. inte-
obrazu znacznik FF 00 (czyli 255 ra- kerem o pseudonimie Simey) w prze- ger overflow)  warto w tym wypad-
zy bajt 0). W przypadku braku kontro- glądarce Opera (9.24 oraz 9.50 be- ku zwrócić uwagę szczególnie na
li czy wskaznik dekompresji nie wyj- ta). Programiści Opery popełnili błąd równanie obliczające wielkość bit-
dzie po za bufor, takie coś może spo- podczas implementowania tagu 00 mapy. Czytając standard należy my-
wodować w najlepszym wypadku wy- 02 XX YY który powodował iż obsłu- śleć nie tylko o tym, jak go zaimple-
jątek, a w najgorszym wykonanie ko- ga tego znacznika była niewiarygod- mentować, ale również jak zabezpie-
du. Analogiczna pułapka występu- nie wolna. Dzięki temu stało się moż- czyć przed nieprawidłowym użyciem
je w przypadku znacznika włączają- liwe stworzenie bitmapy której prze- każdej pojedynczej cechy formatu,
cego tryb bezwzględny. Zapis 00 FF twarzanie w Operze trwa 4 minuty na co może się stać, gdyby któreś po-
00 w danych bitmapy mo- bardzo szybkim komputerze, a 20 mi- le nagłówka przyjęło nieprawidłową
że doprowadzić do faktycznego wy- nut na średnim  w tym czasie Ope- (z logicznego punktu widzenia) war-
konania kodu (prawdopodobnie bę- ra nie reaguje na żadne bodzce ze- tość, oraz jakie mogą być tego kon-
dzie to trudne, ale jednak możliwe). wnętrzne. Atakujący mógłby stwo- sekwencje. Należy pamiętać, iż pro-
Powyższe pułapki są jednak bar- rzyć stronę WWW zawierającą setki gramista musi zabezpieczyć wszyst-
dzo oczywiste, i mało który programi- takich bitmap, przez co przeglądarka ko, ponieważ atakujący musi znalezć
sta w nie wpada. Troszeczkę mniej nieświadomego użytkownika mogła tylko jeden błąd.
oczywistą pułapką jest znacznik 00 by odmówić posłuszeństwa na dłu-
02 XX YY służący do przesuwania gie godziny. Podsumowanie
do przodu znacznika zapisu dekom- Podsumowując, kodowanie RLE Format BMP, mimo swojej pozor-
presowanych danych. Ivan Fratric 6 stwarza wiele możliwości ataku oraz nej prostoty (w porównaniu do np.
kwietnia roku 2007 opublikował in- ukrycia informacji. Należy zachować PNG czy JPEG) jest najeżony pu-
formacje na temat wykorzystania ta- szczególną ostrożność implementu- łapkami, miejscami gdzie można po-
gu 00 02 XX YY do wykonania ko- jąc obsługę RLE w formacie BMP. pełnić choćby drobny błąd, oraz za-
du w ACDSee oraz IrfanView. Pro- wiera wiele miejsc w których można
blem polegał na tym iż programiści Bezpieczna ukryć dodatkowe dane, bez wpływa-
w obu przypadkach nie sprawdza- implementacja nia na wyświetlaną bitmapę.
li czy wskaznik zapisu po wykonaniu Programista powinien pamiętać, iż Jako zadanie domowe pozosta-
znacznika 00 02 XX YY nie opuścił zgodność ze standardem zapewnia wiam czytelnikowi analizę zapisu da-
bufora bitmapy. Możliwe zatem sta- bezpieczną obsługę jedynie popraw- nych obrazu metodą BI_BITFIELD,
ło się nakierowanie wskaznika zapi- nych bitmap faktycznie zgodnych ze oraz analizę pozostałych wersji for-
su na dowolny fragment pamięci, i na- standardem  pliki BMP zgodne je- matu BMP. l
www.hakin9.org
8 hakin9 Nr 2/2008


Wyszukiwarka