Pocztówka od KrzaQ
0x0. Nieoczekiwana przesyłka czyli jak trafiłem do dzienniczka⌗
Czasami śledząc losy takich agentów
jak popularny Thomas, zastanawiam się jak (nie)wiele potrzeba, aby trafić na watchlistę trzyliterowej firmy sponsorowanej z budżetu państwa. Jak bardzo musiałbym się postarać? W podobnym zamyśleniu trwałem w momencie wyciągania poczty, ze skrzynki, pewnego środowego poranka. I w tym momencie w moje ręce wpadła pocztówka. Ot taka zaadresowana do @foxtrot_charlie
.
Świetnie pomyślałem spoglądając na tę część, która z reguły zawiera kilka miłych dla adresata słów, teraz to już na pewno taka firma
doda sobie mnie do znajomych.
0x1. Biuro Szyfrów i Spraw Beznadziejnych⌗
No dobra, skoro orzeł wylądował
to wypadałoby coś z tym fantem zrobić. Trochę z obawą zająłem się rozwiązywaniem tej łamigłówki, no bo jakby mi nie wyszło… to jak to tak… cough niehackersko cough! Wiem! Powiem, że mi się zgubiła… Nie, słabe to, muszę rozwiązać. No nic, ** failure is not an option ** jak to mówią.
1. Przepisujemy!⌗
Powiedzmy sobie szczerze, operowanie bitami znacznie szybciej przychodzi naszym kwarcowym kumplom niż białkowcom. Po zdigitalizowaniu otrzymujemy coś takiego:
51 63 70 62 63 61 78 6c 63 20 6e 6d
78 62 70 6d 75 67 63 6c 67 79 20 78
20 4c 6d 75 63 65 6d 20 48 6d 70 69
73 21 0a 0a 69 6f 0a
2. Łamiemy!⌗
Na pierwszy rzut oka wszystkie wartości są zawierają się w przedziale ASCII, więc może szyfrowanie nie jest aż takie trudne? Sprawdźmy.
Krótki helper w Pythonie
i otrzymujemy:
Qcpbcaxlc nmxbpmugclgy x Lmucem Hmpis!
io
Chyba jest dobrze… Mamy coś co przypomina wyrażenie zgodne z jakimś językiem, wszystkie znaki należą do ASCII
, nie mamy żadnych krzaczków (KrzaQ ;D). Czyli pewnie zastosowano jakiś szyfr podstawieniowy. To jest moment w którym powiedziałem sobie to “io” to będzie podpis kq. Stąd droga do rozwiązania łamigłówki już krótka. Za każdy znak podstawiamy jego odpowiednik “oddalony” w alfabecie o określony offset. Dla każdego przesunięcia printujemy rozwiązanie. Jedno z nich wygląda następująco:
Serdeczne pozdrowienia z Nowego Jorku!
kq
BINGO! Chciałem tylko nadmienić, że mój zmysł łowcy od razu podpowiedział mi, że io -> kq
, #aniemowilem?
Dziękuję serdecznie za śliczną pocztówkę KrzaQ
! Publicznie zobowiązuję się do zajęcia Ci chwili podobną wiadomością!
To jeszcze panorama Nowego Jorku:
Epilog⌗
Zgodnie z założeniami tego typu postów, mają one nieść ze sobą pewną wartość merytoryczną. Dlatego przedstawiam krótki kod, którym rozwiązałem to zadanie. Oczywiście da się to zrobić ładniej, krócej, szybciej, ale tak jak w przypadku CTFów: what works works
.
#!/usr/bin/env python3
import string
import codecs
def rot(i, text):
# prosta i przyjemna w użyciu funkcja maketrans zamieni nam odpowiadające
# literki (operuje na bajtach stąd .encode())
rotI = bytes.maketrans(
string.ascii_letters.encode(),
string.ascii_letters[i:].encode() + string.ascii_letters[:i].encode()
)
# zwracamy "przetłumaczoną" wiadomość zdekodowaną do ascii
return codecs.decode(text.encode().translate(rotI))
def main():
'''
zawartość postcard.txt:
51 63 70 62 63 61 78 6c 63 20 6E 6D
78 62 70 6D 75 67 63 6c 67 79 20 78
20 4c 6d 75 63 65 6d 20 48 6d 70 69
73 21 0a 0a 69 6f 0a
'''
# wczytujemy kartkę z pliku postcard.txt i zamieniamy na ascii
ptcard = ''.join([chr(int(x, 16)) for x in open(
'./postcard.txt').read().replace('\n', ' ')
.replace(' ', ' ').strip().split(" ")])
'''
Wynikiem działania jest:
Qcpbcaxlc nmxbpmugclgy x Lmucem Hmpis!
io
'''
# teraz najważniejsza część, czyli dla każdego przesunięcia (rotX)
# tworzymy odpowiadający mu string
for i in range(len(string.ascii_letters)):
print(rot(i, ptcard))
if __name__ == '__main__':
main()
Przy okazji postanowiłem pobawić się i stworzyć niezbyt czytelnego onelinera, który również rozwiąże łamigłówkę:
import string; print(list(map(lambda i: '{} ---> '.format(i) + ''.join( [x.upper() if w.isupper() else (x) for x, w in zip([chr(ord('a')+(ord(g) + i)%len(string.ascii_lowercase)) if g in string.ascii_lowercase else g for g in 'Qcpbcaxlc nmxbpmugclgy x Lmucem Hmpis!\n\nio'.lower()], list('Qcpbcaxlc nmxbpmugclgy x Lmucem Hmpis!\n\nio'))]), range(len(string.ascii_lowercase))))[9])
foxtrot_charlie