Misja Gynvaela 013

Steganografia według wikipedii to nauka o komunikacji w taki sposób, by obecność komunikatu nie mogła zostać wykryta. Klasycznym jej przykładem jest ukrycie wiadomości w najmniej znaczącym bicie. Można w ten sposób ukryć dane w obrazie, a zmodyfikowane wartości kolorów są praktycznie niezauważalne. W tym przypadku jednak nie było tak “kolorowo”…

 

Misja z serii CTF opublikowana po live stream’ie Gynvael’s Livestream #51.

Treść misji:

Po ściągnięciu pliku ukazuje nam się plik png.

 

Zmyłka programu graficznego

Próba rozwiązania tej misji zaczęła się trochę niefortunnie. Nie ma ona za bardzo związku z rozwiązaniem, ale postanowiłem że to opiszę. Faktyczne rozwiązanie misji znajduje się niżej.

Gdy misja została opublikowana, z ciekawości zerknąłem na załącznik. Oooo… “VERY PNG MUCH STEGANO!!”  napis sugeruje, że to zadanie ma jakiś związek ze steganografią. Super! 🙂 Pobawimy się bitami. Nie miałem jednak czasu tego dnia na nic więcej. Następnego dnia w pracy (oczywiście w trakcie przerwy), zerknąłem na ten obrazek bo ciekawość nie dawała mi spokoju.

Zadania z obrazkami zawsze zaczynam od sprawdzenia, czy nie ma przypadkiem jakiś kolorów, które są do siebie bardzo zbliżone i są niewidoczne dla oczu. W tym wypadku włączam funkcję Levels albo Curves (po polsku funkcja Poziomy, Krzywe) i kręcę pokrętłami próbując zobaczyć jakieś zmiany w kolorach. Gdy już coś wypatrzę to włączam mój programik Lupochondryk (który służy mi od dobrych 15 lat) i przeglądam te miejsca próbując znaleźć to coś.

W pracy mam do dyspozycji moją ulubioną przeglądarkę obrazków ACDSee. Wersja trochę stara, ale działa całkiem dobrze. Załadowałem obrazek z misji no i podglądam. Wydaje się, że są tylko 2 kolory – czarny i biały. Wybieram funkcję Levels i mieszam… Zadowolenie. Coś się pojawia. Na rysunku 1 widać, że na krawędziach liter są jakieś pixele w innych kolorach. Lupochondryk ładnie pokazuje wartości… koniec przerwy, w domu dalej będziemy się bawić.

Rysunek 1

Dzieci poszły spać, jest chwila, aby usiąść do kompa. No więc zacząłem robić to co w pracy, czyli włączyłem GIMPa i przesuwam te suwaczki w funkcjach Levels i Curves. Potem włączam moj programik. Włączam inny pogram… Masakra! Nic nie ma. W całym obrazku są tylko 2 kolory (rysunek 2).

Rysunek 2

W końcu piszę krótką funkcję.

Niefajnie, faktycznie tylko 2 kolory.

No i co teraz? Nie ma żadnych pixeli, na które liczyłem, z poustawianymi najniższymi bitami. Pomyślałem, że chyba musiało mi się coś przywidzieć w pracy. Może zmęczony byłem i mi się coś w głowie uroiło. No ale jednak nie, bo na drugi dzień zrobiłem to samo i nawet coś więcej wyszło. Wyszła mi taka sama obwódka jak na rysunku 3a.
Co jest grane? Pierwsza wskazówka to skala. Jak można zauważyć na samym dole na rysunku 1 widać skalę 70%. Okazało się, że ACDSee 10 wykonuje funkcję Levels na pomniejszonej wersji widoku, a nie na oryginalnym rysunku. Pomniejszenie powoduje rozmazanie i na krawędziach pojawiają się pixele o kolorze pośrednim w tym przypadku szarym.

Rysunek 3. GIMP zmiana rozmiaru + Curves (uwidocznienie wartości bliskich 0 i 255)

Skąd jednak bierze się obwódka na rysunku 3a? Przecież kolor pośredni powinien pojawić się na krawędzi, tak jak jest to na rysunku 3c. W pewnym momencie pomyślałem sobie nawet, że Gynvael skorzystał z jakiegoś błędu w algorytmie png, co powoduje ukrycie pixeli w obwódkach liter i uwidacznia się to dopiero przy manipulacjach obrazu.

Rysunek 4

Odpowiedź jest jednak prostsza niż można się spodziewać. Mianowicie problem tkwi w algorytmie zmiany rozmiaru bitmapy. ACDSee używa domyślnie algorytmu Lanczos. To właśnie on powoduje, że wokół liter na obrazku pojawia się dodatkowa obwódka.
Na rysunku 3 przedstawiłem testy w GIMPie. Obrazek pomniejszałem do 79%, najpierw używając funkcji Sinc (Lanczos3) – rysunek 3a, potem używając funkcji Cubic – rysunek 3c. Dodatkowo, aby obalić pomysł o błędzie w png, zapisałem plik jako BMP, a następnie zrobiłem to samo co na początku – rysunek 3b.
Wszystkie obrazki zostały potraktowane filtrem Curves, którego parametry przedstawiam na rysunku 4.

 

Powrót do punkcu wyjścia. Tzn. próbowałem jeszcze liczyć czarne pixele w rzędach i kolumnach i konwertować do ASCII ale nic z tego.

 

Rozwiązanie misji 013

Patrząc na obrazek nic więcej już nie zdziałam. Jedyne co przychodzi mi do głowy to – binwalk.

Bingo!

Zaskoczenie było ogromne. Wyeksportował dwa pliki do podfolderu. Pierwszy z nich był dosyć duży 1920800 bajtów. Ciekawe co jest w środku. Zmieniam rozszerzenie na .data i idziemy do GIMP’a.

Rysunek 5

No teraz jest już trochę ciekawiej. Po dostosowaniu szerokości widzimy czarne poziome linie. Nie da się jednak wyprostować obrazka (rysunek 5) widocznie szerokość danych w pliku nie jest podzielna przez 3. W tym momencie przypomniało mi się jak na jakiejś prelekcji Gynvael mówił o plikach bmp. Jak wiadomo każdy wiersz dopełniany jest tak, aby był podzielny przez 4. Jeśli autor algorytmu nie zadba o wyzerowanie to do pliku mogą zostać zapisane dane, które wcześniej znajdowały się w pamięci. Może w dopełnieniu jest coś ukryte? Z prostych wyliczeń wychodzi jednak, że  – 800*3 = 2400 / 3 = 600 – wiersz jest podzielny przez 4, nie trzeba dopełniać. Analizujemy… rysunek 6.

Rysunek 6

Nareszcie są pixele o innych kolorach.

Jednak jeszcze jeden pomysł wpadł mi do głowy. Jeśli dane w pliku nie są podzielne przez trzy to powinno udać się je wyprostować wybierając w GIMPie tryb jedno-bajtowy, czyli Indexed.

Rysunek 7 (otwórz w nowym oknie)

OK. Mamy już wyprostowane. No to kolejne co przychodzi do głowy, mając na względzie poprzednie misje. Czy te czarne i białe linie to nie są bity?

Piszemy funkcję wyczytującą rysunek i bierzemy 5 kolumnę na warsztat. Kilka razy musiałem modyfikować kod. Kluczem okazało się zinterpretowanie czarnych pixeli jako 1, a białych jako 0.

 

Udało się.

 

Flaga: “Hmmm, czy to zadanie czasem juz nie bylo gdzies?

 

Kontynuacja >>

Post Author: marbel82

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.