Misja Gynvaela 011

MISJA 011            goo.gl/keE94T                  DIFFICULTY: █████░░░░░ [5/10]
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅

Jednemu z naszych agentów polowych poszczęściło się - zakradł się do biura
podejrzanego i zrobił zdjęcie bardzo ważnego dokumentu. Zdjęcie udało się wywołać
i otrzymaliśmy dzisiaj archiwum z jego skanem.

Ponieważ jestem obecnie bardzo zajęty i mam bardzo ważne spotkanie, poniżej jest
link do pliku - zajmij się tym.

  goo.gl/A6sMwA

Powodzenia!

--

Odzyskaną wiadomość umieść w komentarzu pod tym video :)
Linki do kodu/wpisów na blogu/etc z opisem rozwiązania są również mile widziane!

P.S. Rozwiązanie zadania przedstawię na jednym z vlogów w okolicy dwóch tygodni.

Ściągnięty plik 43842e832bfe28328309053ce1b1a49afc1047e5.bin wykrywany jest jako archiwum 7z przez narzędzie file:

> file 43842e832bfe28328309053ce1b1a49afc1047e5.bin
43842e832bfe28328309053ce1b1a49afc1047e5.bin: 7-zip archive data, version 0.4

Po sprawdzeniu okazało się, że w archiwum znajduje się ponad 75 000 plików o właściwie identycznych rozmairach. Będąc przekonanym, że podobnie do Misji 008, wypakowywanie ich jest bezcelowe, zacząłem szukać sugestii w ich metadanych. Lista wyglądała następująco:

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-4770K CPU @ 3.50GHz (306C3),ASM,AES-NI)
 
Scanning the drive for archives:
1 file, 2260394 bytes (2208 KiB)
 
Listing archive: 43842e832bfe28328309053ce1b1a49afc1047e5.bin.7z
 
--
Path = 43842e832bfe28328309053ce1b1a49afc1047e5.bin.7z
Type = 7z
Physical Size = 2260394
Headers Size = 990068
Method = LZMA:27
Solid = +
Blocks = 1
 
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2017-09-28 19:28:39 D....            0            0  zdjecie_dokumentu
2017-09-28 19:15:54 ....A         8771      1270326  zdjecie_dokumentu/1000099b5802
2017-09-28 19:15:54 ....A         8771               zdjecie_dokumentu/10001494c006
2017-09-28 19:15:54 ....A         8774               zdjecie_dokumentu/1000ee4ba590
2017-09-28 19:15:54 ....A         8776               zdjecie_dokumentu/1000f352b441
2017-09-28 19:15:54 ....A         8771               zdjecie_dokumentu/10023645483f
2017-09-28 19:15:54 ....A         8771               zdjecie_dokumentu/10040f06c95d
[...]
2017-09-28 19:25:20 ....A         8772               zdjecie_dokumentu/fff6940e20c0
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/fff86fecc806
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/fffa379476c6
2017-09-28 19:25:20 ....A         8774               zdjecie_dokumentu/fffbb82314bb
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/fffda28a026f
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/fffdc98e6122
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/fffe366b11ec
2017-09-28 19:25:20 ....A         8771               zdjecie_dokumentu/ffff609e5415
2017-09-28 19:25:20 ....A         8772               zdjecie_dokumentu/ffffdca9b891
------------------- ----- ------------ ------------  ------------------------
2017-09-28 19:28:39          673653115      1270326  76800 files, 1 folders

Jak widać, wielkości plików są prawie identyczne – ale jednak identyczne nie są. Wobec tego należy sprawdzić, jaki mają rozrzut:

arr = File.read('list.txt')
    .scan(/ (87[678]\d)/)
    .map(&:first)
    .map(&:to_i)
 
p [arr.min, arr.max]
 
[8768, 8780]

Interesujące. Może są to piksele obrazka o poszczególnej jasności?

arr = File.read('list.txt')
    .scan(/ (87[678]\d)/)
    .map(&:first)
    .map(&:to_i)
    .map{ |n| n - 8768 }
    .map{ |n| [(n*15).chr]*3 }
    .flatten
    .join
 
File.write('img.raw', arr)

Po otworzeniu w programie GIMP okazało się jednak, że to ślepa uliczka.

GIMPGIMP

Wobec tego rozpakowałem archiwum i sprawdziłem jakiego typu są zawarte w nim pliki. file raportował dla każego z nich, że jest to PCX ver. 3.0 image data bounding box [0, 0] – [319, 239], 3 planes each of 8-bit colour, RLE compressed.

Po przejrzeniu kilku z tych plików okazało się, że każdy z nich miał dokładnie jeden ustawiony piksel na czarnym tle. Oczywistym stało się przypuszczenie, że 76 800 plików-obrazków to tak naprawdę 76 800 pikseli obrazka z flagą. Zdecydowałem, że je wszystkie złożę. Aby tego dokonać, musiałem pierw przekonwertować wszystkie do formatu png, ponieważ pcx nie wspiera kanału alfa.

FILES = Dir['zdjecie_dokumentu/*']
    .map{ |s| s.sub(/zdjecie_dokumentu\/(.+)/, '\1') }
 
 
CMD_CONVERT = 'convert zdjecie_dokumentu/%s -transparent black out/%s.png'
CMD_COMPOSE = 'convert tmp.png out/%s.png -gravity center  -composite tmp.png'
 
system('rm tmp.png')
system('cp base.png tmp.png')
 
 
done = 0
FILES.each do |f|
    system(CMD_CONVERT % [f, f])
    system(CMD_COMPOSE % f)
    done += 1
    puts 'Done: % 5d/%d' % [done, FILES.size]
    if done % 100 == 0 then
        cmd = 'cp tmp.png partials/%05d.png' % done
        system cmd
    end
end

Nie było to rozwiązanie najszybsze (przerabiało ok 15 pikseli na sekundę), ale mimo wszystko było zadowalające. Już po przerobieniu połowy pikseli widać było część hasła, chociaż wtedy wydawało mi się, że jego treść to “Pocztówka z Sarkcz“:

Pocztówka z SarkczPocztówka z Sarkcz

Wystarczyło jednak chwilkę jeszcze poczekać, aby odczytać faktyczne hasło – “Pocztówka z wakacji“. Osobiście preferuję jednak wersję z Sarkcz.

Pocztówka z wakacjiPocztówka z wakacji

A tak wygląda wizualizacja uzupełniania obrazka:

Polska misja Gynvaela 011

Bardzo ciekawa misja, oby takich więcej!

Leave a Reply

Your email address will not be published.