Writeup: FlareOn 2021: 003 - antioch

Task description

1. TLDR

Antioch graph

2. Dane wejściowe

Plik z zadaniem znajduje się tutaj. Hasło: flare.

Przedmiotem zadania był plik antioch.tar

antioch.tar

Zawartość archiwum stanowiły pliki i katalogi:

09e6fff53d6496d170aaa9bc88bd39e17c8e5c13ee9066935b089ab0312635ef
1c5d28d6564aed0316526e8bb2d79a436b45530d2493967c8083fea2b2e518ce
25e171d6ac47c26159b26cd192a90d5d37e733eb16e68d3579df364908db30f2
2b363180ec5d5862b2a348db3069b51d79d4e7a277d5cf5e4afe2a54fc04730e
303dfd1f7447a80322cc8a8677941da7116fbf0cea56e7d36a4f563c6f22e867
49fb821d2bf6d6841ac7cf5005a6f18c4c76f417ac8a53d9e6b48154b5aa1e76
4c33f90f25ea2ab1352efb77794ecc424883181cf8e6644946255738ac9f5dbd
58da659c7d1c5a0c3447cb97cd6ffb12027c734bfba32de8b9b362475fe92fae
6b4e128697aa0459a6caba2088f6f77efaaf29d407ec6b58939c9bc7814688ad
7016b68f19aed3bb67ac4bf310defd3f7e0f7dd3ce544177c506d795f0b2acf3
754ee87063ee108c1f939cd3a28980a03b700f3c3967df8058831edad2743fd7
76531a907cdecf03c8ac404d91cbcabd438a226161e621fab103a920600372a8
7d643931f34d73776e9169551798e1c4ca3b4c37b730143e88171292dbe99264
81f28623cca429f9914e21790722d0351737f8ad3e823619a4f7019be72e2195
8e11477e79016a17e5cde00abc06523856a7db9104c0234803d30a81c50d2b71
9a31bad171ad7e8009fba41193d339271fc51f992b8d574c501cae1bfa6c3fe2
a13ffcf46cf41480e7f15c7f3c6b862b799bbe61e7d5909150d8a43bd3b6c039.json
a2de31788db95838a986271665b958ac888d78559aa07e55d2a98fc3baecf6e6
a435765bcd8745561460979b270878a3e7c729fae46d9e878f4c2d42e5096a44
b5f502d32c018d6b2ee6a61f30306f9b46dad823ba503eea5b403951209fd59b
b75ea3e81881c5d36261f64d467c7eb87cd694c85dd15df946601330f36763a4
bfefc1bdf8b980a525f58da1550b56daa67bae66b56e49b993fff139faa1472c
cd27ad9a438a7eef05f5b5d99e2454225693e63aba29ce8553800fed23575040
cfd7ddb31ce44bb24b373645876ac7ea372da1f3f31758f2321cc8f5b29884fb
e1a9333f9eccfeae42acec6ac459b9025fe6097c065ffeefe5210867e1e2317d
e5254dec4c7d10c15e16b41994ca3cf0c5e2b2a56c9d4dc2ef053eeff24333ff
e6c2557dc0ff4173baee856cbc5641d5b19706ddb4368556fcdb046f36efd2e2
ea12384be264c32ec1db0986247a8d4b2231bf017742313c01b05a7e431d9c26
f2ebdc667cbafc2725421d3c02babc957da2370fbd019a9e1993d8b0409f86dd
f9621328166de01de73b4044edb9030b3ad3d5dbc61c0b79e26f177e9123d184
fadf53f0ae11908b89dffc3123e662d31176b0bb047182bfec51845d1e81beb9
fd8bf3c084c5dd42159f9654475f5861add943905d0ad1d3672f39e014757470
manifest.json
repositories

Można było zauważyć, że zawartość katalogów była powtarzalna wg schematu:

json
layer.tar
VERSION

Analiza zawartości plików pozwoliła ustalić, że jest plik antioch.tar to dockerowy obraz.

3. Analiza obrazu

Załadowałem obraz:

$ docker load -i antioch.tar

A następnie uruchomiłem narzędzie (Dedockify)[https://github.com/mrhavens/Dedockify]:

$ docker run -v /var/run/docker.sock:/var/run/docker.sock mrhavens/dedockify a1
FROM antioch:latest
ADD file:fae1674275a5cc9b0c04ef177df65aebeaf796b0ba7c94ac2bd35120306411d4 in /
CMD ["/AntiochOS"]

W tym momencie zbyt wiele dla mnie z tego nie wynikało. Rozpocząłem poszukiwania pliku wykonywalnego:

$ unar antioch.tar
$ cd ./antioch/
find ./ -type f -name *.tar -exec tar -xf {} \;

Jednym z rozpakowanych plików był AntiochOS. Pobieżna analiza pozwoliła zidentyfikować 4 polecenia:

quit
help
approach
consult

Uruchomiłem program. Analiza komunikatów i poleceń pozwoliła odgadnąć, że program odwzorowuje scenę z filmu Monty Python i Święty Graal:

remnux@remnux:~/RE$ docker run -i antioch /AntiochOS
AntiochOS, version 1.32 (build 1975)
Type help for help
> approach
Approach the Gorge of Eternal Peril!
What is your name? Sir Lancelot
What is your quest? To seek the Holy Grail
What is your favorite color? Blue
Right. Off you go. #18

> approach
Approach the Gorge of Eternal Peril!
What is your name? Sir Gallahad
What is your quest? To seek the Holy Grail!
What is your favorite color? Yellow
Right. Off you go. #30

Czym były jednak liczby pojawiające się na końcu rozmowy? Numerami poszczególnych warstw obrazów. Imiona były zaszyte w pliku json w polu author. Numery były ukryte w kodzie programu jako sumy CRC32. Pozostało zatem napisać krótki skrypt, który ustaliłby prawidłową kolejność warstw:

#!/usr/bin/env python3

from pprint import pprint

known_crc32 = [0x0B59395A9,0x1BB5AB29,0x0E,0x5EFDD04B,0x3F8468C8,0x12,0x0ECED85D0,0x82D23D48,0x2,0x0D8549214,0x472EE5,0x1D,0x2C2F024D,0x0C9A060AA,0x0C,0x18A5232,0x24D235,0x0D,0x72B88A33,0x81576613,0x14,0x674404E2,0x5169E129,0x0B,0x307A73B5,0x0E560E13E,0x1C,0x13468704,0x2358E4A9,0x15,0x94F6471B,0x0D6341A53,0x5,0x0EDA1CF75,0x0BAFA91E5,0x18,0x0BBAC124D,0x0A697641D,0x19,0x0F707E4C3,0x0EF185643,0x7,0x0D702596F,0x79C28915,0x0A,0x86A10848,0x59108FDC,0x1,0x0D640531C,0x0EF3DE1E8,0x13,0x7B665DB3,0x0A3A903B0,0x3,0x0AB1321CC,0x0EEEDEAD7,0x4,0x4F6066D8,0x9C8A3D07,0x11,0x256047CA,0x4085BE9E,0x9,0x3FC91ED3,0x379549C9,0x8,0x0A424AFE4,0x0EF871347,0x1B,0x550901DA,0x1FCEC6B,0x10,0x10A29E2D,0x0E76056AA,0x16,0x56CBC85F,0x356F1A68,0x0F,0x80DFE3A6,0x9D0AB536,0x1E,0x0E657D4E1,0x0B4E9FD30,0x17,0x2BA1E1D4,0x0BE66D918,0x1A,0x7D33089B,0x67C1F585,0x6,]

import zlib

known_crc32_length = len(known_crc32)/3
print(f"{known_crc32_length}")

names = [ "Dragon of Angnor", "Roger the Shrubber", "Dinky", "Dennis the Peasant", "Sir Ector", "A Famous Historian", "Tim the Enchanter", "Sir Gawain", "Trojan Rabbit", "Sir Robin", "Green Knight", "Sir Bedevere", "Squire Concorde", "Sir Not-Appearing-in-this-Film", "Legendary Black Beast of Argh", "Sir Gallahad", "Lady of the Lake", "Zoot", "Miss Islington", "Chicken of Bristol", "Rabbit of Caerbannog", "Black Knight", "Prince Herbert", "Brother Maynard", "King Arthur", "Sir Bors", "Squire Patsy", "Bridge Keeper", "Inspector End Of Film", "Sir Lancelot"] 

tuples = []

for name in names:
    crc32_value = zlib.crc32((name+'\n').encode('ascii')) & 0xffffffff
    for i in range(0,int(known_crc32_length)):
        if crc32_value == known_crc32[i*3]:
            tuples.append((name, known_crc32[i*3+2]))
            break

sorted_by_second = sorted(tuples, key=lambda tup: tup[1])
pprint(sorted_by_second)

Na wyjściu pojawiła się kolejność:

[('Miss Islington', 1),
 ('Sir Bors', 2),
 ('Tim the Enchanter', 3),
 ('Dragon of Angnor', 4),
 ('Brother Maynard', 5),
 ('Sir Bedevere', 6),
 ('Sir Robin', 7),
 ('Zoot', 8),
 ('Squire Concorde', 9),
 ('Green Knight', 10),
 ('Trojan Rabbit', 11),
 ('Chicken of Bristol', 12),
 ('Roger the Shrubber', 13),
 ('Bridge Keeper', 14),
 ('Sir Gawain', 15),
 ('Legendary Black Beast of Argh', 16),
 ('A Famous Historian', 17),
 ('Sir Lancelot', 18),
 ('Lady of the Lake', 19),
 ('Rabbit of Caerbannog', 20),
 ('Sir Not-Appearing-in-this-Film', 21),
 ('Prince Herbert', 22),
 ('King Arthur', 23),
 ('Inspector End Of Film', 24),
 ('Sir Ector', 25),
 ('Squire Patsy', 26),
 ('Dennis the Peasant', 27),
 ('Dinky', 28),
 ('Black Knight', 29),
 ('Sir Gallahad', 30)]

4. Odczytanie flagi

Pozostało zatem złożyć prawidłowy obraz (tzn. ułożyć pliki nadpisując je we właściwej kolejności)

rm -rf ./repacked

names=(
    'Islington'
    'Bors'
    'Enchanter'
    'Dragon'
    'Brother'
    'Bedevere'
    'Robin'
    'Zoot'
    'Squire'
    'Green'
    'Trojan'
    'Chicken'
    'Shrubber'
    'Bridge'
    'Gawain'
    'Legendary'
    'Famous'
    'Lancelot'
    'Lady'
    'Rabbit'
    'Not-Appearing-in-this-Film'
    'Herbert'
    'Arthur'
    'Inspector'
    'Ector'
    'Squire'
    'Dennis'
    'Dinky'
    'Black'
    'Gallahad'
)

for name in ${names[*]}
do
    printf "NAME %s\n" $name
    layer=$(grep -r $name ./antioch)
    path=${layer:0:75}layer.tar
    printf "%s\n" $path
    unar -f -D -o ./repacked $path
    #sleep 2
    #exit
done

unar -f -D -o ./repacked ./antioch/7016b68f19aed3bb67ac4bf310defd3f7e0f7dd3ce544177c506d795f0b2acf3/layer.tar 

Po wpisaniu polecenia consult można było odczytać z ascii artu flagę:

Five-Is-Right-Out@flare-on.com