Mój writeup - nie udało się zrobić wszystkiego, ale na usprawiedliwienie powiem, że dowiedziałem się o konkursie o 17:50 w sobotę (wg historii przeglądarki):
Cebula
Flaga 1:
Widzimy, że tekst z zadania to liczby do 128 - zatem pewnie ASCII. W Pythonie potwierdziło się.
Kopiuj
s="82 49 107 122 81 48 70 79 85 108 90 70 81 84 78 69 83 48 108 67 86 48 100 90 85 85 82 78 84 107 112 66
82 49 107 121 85 48 70 79 85 108 90 70 81 84 78 69 84 85 108 67 86 48 100 90 85 85 82 78 84 108 74 66 82
49 107 121 85 48 70 79 85 108 90 70 81 84 78 69 84 85 108 67 86 48 100 86 85 85 82 78 84 107 112 66 82 49
107 121 85 48 70 79 85 108 90 70 81 84 78 69 84 85 108 67 86 48 100 86 85 85 82 78 84 107 112 66 82 49
107 121 85 48 70 79 85 108 100 70 81 84 78 69 84 85 108 67 86 48 100 86 85 85 82 78 84 107 112 66 82 49
107 121 85 48 70 79 85 108 90 70 81 84 78 69 83 48 108 67 86 48 100 90 85 85 82 78 84 108 74 66 82 122 81
48 85 48 70 79 87 108 108 70 81 84 78 85 84 85 108 67 87 85 104 70 85 85 82 80 84 48 112 66 82 122 81 48
81 48 70 79 85 108 112 70 81 84 78 85 84 48 108 67 87 69 104 70 85 85 82 82 84 86 74 66 82 49 107 48 85
48 70 85 85 48 112 74 84 86 112 86 86 86 81 121 81 48 115 49 82 86 90 74 85 48 78 86 83 107 74 66 86 107
107 57 80 84 49 81 85 106 77 122 86 70 108 102 82 122 65 119 82 65 61 61 71 48 48 68 83 84 52 82 84"
r="".join([chr(int(x)) for x in s.split(" ")])
print r
R1kzQ0FOUlZFQTNES0lCV0dZUURNTkpBR1kyU0FOUlZFQTNETUlCV0dZUURNTlJBR1kyU0FOUlZFQTNETUlCV0dVUURNT
kpBR1kyU0FOUlZFQTNETUlCV0dVUURNTkpBR1kyU0FOUldFQTNETUlCV0dVUURNTkpBR1kyU0FOUlZFQTNES0lCV0dZUU
RNTlJBRzQ0U0FOWllFQTNUTUlCWUhFUURPT0pBRzQ0Q0FOUlpFQTNUT0lCWEhFUURRTVJBR1k0U0FUU0pJTVpVVVQyQ0s
1RVZJU0NVSkJBVkk9PT1QUjMzVFlfRzAwRA==G00DST4RT
Zatem flaga to G00DST4RT.
Flaga 2:
Poprzednia warstwa kończyła się dwoma znakami równości, a sama składała się z liter i cyfr. Prawdopodobnie to Base64:
Kopiuj
s="R1kzQ0FOUlZFQTNES0lCV0dZUURNTkpBR1kyU0FOUlZFQTNETUlCV0dZUURNTlJBR1kyU0FOUlZFQTNETUlCV0dVUURNTkpBR1kyU0FOUlZFQT
NETUlCV0dVUURNTkpBR1kyU0FOUldFQTNETUlCV0dVUURNTkpBR1kyU0FOUlZFQTNES0lCV0dZUURNTlJBRzQ0U0FOWllFQTNUTUlCWUhFUURPT0p
BRzQ0Q0FOUlpFQTNUT0lCWEhFUURRTVJBR1k0U0FUU0pJTVpVVVQyQ0s1RVZJU0NVSkJBVkk9PT1QUjMzVFlfRzAwRA=="
import base64
base64.b64decode(s)
'GY3CANRVEA3DKIBWGYQDMNJAGY2SANRVEA3DMIBWGYQDMNRAGY2SANRVEA3DMIBWGU
QDMNJAGY2SANRVEA3DMIBWGUQDMNJAGY2SANRWEA3DMIBWGUQDMNJA
GY2SANRVEA3DKIBWGYQDMNRAG44SANZYEA3TMIBYHEQDOOJAG44CANRZEA3TOIBXHEQ
DQMRAGY4SATSJIMZUUT2CK5EVISCUJBAVI===PR33TY_G00D'
Flaga to PR33TY_G00D.
Flaga 3:
Podobnie jak poprzednio. Tym razem tekst to wielkie litery i cyfry, oraz === na końcu. Po chwili googlania, wychodzi base32:
Kopiuj
s='GY3CANRVEA3DKIBWGYQDMNJAGY2SANRVEA3DMIBWGYQDMNRAGY2SANRVEA3DMIBWGUQ
DMNJAGY2SANRVEA3DMIBWGUQDMNJAGY2SANRWEA3DMIBWGUQDMNJAGY2SANR
VEA3DKIBWGYQDMNRAG44SANZYEA3TMIBYHEQDOOJAG44CANRZEA3TOIBXHEQDQMRAGY4S
ATSJIMZUUT2CK5EVISCUJBAVI==='
base64.b32decode(s)
'66 65 65 66 65 65 65 66 66 66 65 65 66 65 65 65 65 66 65 65 65 66 66 65 65 65 65 65 66 66 79 78 76 89 79 78 69 77 79 82 69 NIC3JOBWITHTHAT'
Flaga to: NIC3JOBWITHTHAT.
Flaga 4:
Powtórka z flagi 1:
Kopiuj
s='66 65 65 66 65 65 65 66 66 66 65 65 66 65 65 65 65 66 65 65 65 66 66 65 65 65 65 65 66 66 79 78 76 89 79 78 69 77 79 82 69'
"".join([chr(int(x)) for x in s.split(" ")])
'BAABAAABBBAABAAAABAAABBAAAAABBONLYONEMORE'
Flaga: ONLYONEMORE.
Flaga 5:
Tekst to ciąg liter A i B. Sugeruje to użycie kodu Bacona (http://rumkin.com/tools/cipher/baconian.php). Po wklejeniu tam
naszego ciągu (i wybraniu opcji i=J and U=V), dostajemy flagę THEEND.
Where is my password?! #1
Flaga wg treści pochodzi z klucza. Klucz to:
klucz='7034xx6265747465725f6b6565705f69745f72616e646f6d5f647564653b29xx'
gdzie x to niewiadoma. Zauważamy, że klucz jest heksadecymalny, a poszczególne bajty nie przekraczają 0x7f, co sugeruje ascii.
Po zdekodowaniu dostajemy:
p4?better_keep_it_random_dude;)?
Zatem flaga to:
p4{better_keep_it_random_dude;)}
Hasło Shaloma
Otwieramy plik w Wiresharku, patrz screenshot http://imgur.com/ryZfAXx. Nie licząc czasu, tylko dwa bajty się
zmieniały pomiędzy pakietami, z czego pierwszy tylko pomiędzy dwoma wartościami: 0x00 i 0x20. Przypuściłem, że to zapewne
Shift albo coś w tym stylu, natomiast drugi bajt koduje klawisz. Problem w tym, że nie było to ani ascii, ani nic podobnego.
Po poszperaniu w internecie, znalazłem jednak stronę z kodami klawiaturowymi:
https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html
Po przeliterowaniu (ręcznie) po wszystkich naciśnięciach, dostajemy flagę:
p4{i--74k--u2yvv4m--m45ki}
Capture The Data #1
Kopiuj
strings -n 10 forensics2.pcapng | grep p4{
6PASS p4{FTP_Free_To_Pwn}
Capture The Data #2
Otwierając w Wiresharku plik, okazuje się że poprzednia flaga była w przekazie FTP. Przekazany był jeden plik - po wyciągnięciu
go, okazuje się, że był to zip zawierający 1000 plików o nazwach 1, 2, ..., 1000. Na szczęście były one niewielkie, zatem je
po prostu wypisałem:
Po szybkim przejrzeniu okazuje się, że tylko jeden zawierał coś dłuższego niż kilka znaków:
70347b616c6c5f6f665f796f75725f7a6970735f6172655f62656c6f6e675f746f5f75737d
Flaga to więc, po zmianie hex->ascii:
p4{all_of_your_zips_are_belong_to_us}
English, do you speak it? / Do they speak English in "what"?
Zadanie polegało na napisaniu bota, który po otrzymaniu akapitu w jednym z kilku języków odpowie, jaki to był język.
Najprościej znaleźć w internecie listę 1000 najpopularniejszych słów w danym języku i dla każdego z nich zliczać, ile jest
trafień, by wypisać najlepszy strzał. To działało dla pierwszej części - w drugiej niestety nie byłem w stanie znaleźć
dobrego słownika dla np. języka arapaho, plemienia indiańskiego. Na szczęście mogłem wykorzystać sam serwer jako dawcę próbek
- po prostu odpowiadałem zawsze arp (skrót od arapaho) i jeśli nie było błędu, oznaczało to, iż mam próbkę tego języka.
piet
Szybko można znaleźć stronę http://www.bertnase.de/npiet/ zawierającą npiet - interpreter języka, oraz npiet-foogol, który jest
kompilatorem z języka foogol do języka piet. foogola również nie znałem (obviously...), ale po HelloWorld w nim to:
Kopiuj
begin
prints ("Hello World!\n")
end
Ten można natomiast łatwo zmodyfikować, aby wypisał potrzebny tekst.
Kapitan Rozdil
Po znalezieniu oryginału obrazka w internecie i porównaniu z naszym za pomocą narzędzia compare, dostajemy taki widok:
http://imgur.com/oa97kVF
SS-93 #1
Kopiuj
strings -n 10 stegano2.wav | grep p4{
p4{zawsze_ostatni_:(}
SS-93 #2
Po otworzeniu pliku w Audacity i wybraniu analizy spektralnej, dostajemy:
http://imgur.com/d094rMw
C3ntrum N$A
Wystarczy zmienić flagę w ciasteczku.
D0 Y0u 3v3n PHP? #1
Patrząc w źródło strony, widzimy komentarz dotyczący parametru debug=1. Flaga jest na linku:
http://web.ctf.4programmers.net/web1/?debug=1
D0 Y0u 3v3n PHP? #2
Na tej samej stronie dostajemy kod php. Flaga jest porównywana z polem "password" za pomocą funkcji strcmp.
W dokumentacji PHP czytamy w komentarzach, że strcmp zwraca zero (oprócz gdy stringi są równe) także przy błędzie,
np. gdy jeden z argumentów jest tablicą. Zmieniamy więc w requeście pole password na password[] i otrzymujemy flagę.
Koty MSMa
Znamy miejsce ukrycia flagi i wiemy że zdjęcia kotów są wywoływane jako |url|?cat=Amber.jpg
Flagę otrzymujemy poprzez:
curl http://web2.ctf.4programmers.net/web2/show.php?cat=/home/flag.txt
p4{path_traversal_cats}
42
Po wpisaniu admin, dostajemy hasło admina: ICANSQL. Próbujemy więc sql injection:
' or '1'='1' or '1'='
Po czym dostajemy flagę.
Obfuscated
Jak sama nazwa wskazuje, należy znaleźć sens w udziwnionym kodzie JavaScriptu. Nie będę dokładnie się rozpisywał - wystarczy
dokładnie przejść instrukcja po instrukcji i w końcu odgadnie się hasła.
Księżniczka Lea
Musimy znaleźć takie $data i $signature, dla którego nie wykona się $signature !== hash('sha256', $key . $data), a
ponadto $signature zawiera w sobie stringa: "&user=admin". W treści jest wspomniane o HMAC, które po chwili googlania prowadzi do:
https://en.wikipedia.org/wiki/Length_extension_attack
Okazuje się, że istnieje już gotowy tool do podobnych rzeczy:
https://github.com/iagox86/hash_extender
Wpisujemy weń:
Kopiuj
./hash_extender --data blah=qwerty --secret 20 --append \&user=admin --signature
c700e9638661184e03a2c372b0639f4efd05f3814b08c83ba8461ef25addcdbd --format sha256
Otrzymujemy rozwiązanie ($signature i $data).
easymode
Kopiuj
strings -n 10 re0.exe | grep p4{
p4{najprostsze_re_na_swiecie}
xorme
Korzystając z IDA'y, deasemblujemy plik. Po analizie, dostajemy coś, co można sprowadzić do kodu w C (pomijam wypisywanie błędów):
Kopiuj
char xorred[]="\x7f;tw`}Pf{PnccPnakP{gjaPb`}jr";
int main(int argc, char** argv){
int len=strlen(argv[1]);
for(int i=0;i<len;i++){
if(xorred[i]^0x0f^argv[1][i]){
puts("Wrong");
exit(0);
}
}
puts("Ok");
}
Ponieważ xorred jest dostępny, a operacja ^ (xor) jest odwracalna, uzyskamy rozwiązanie poprzez xorred[] xor 0x0F:
Kopiuj
s="\x7f;tw`}Pf{PnccPnakP{gjaPb`}jr"
print "".join([chr(ord(c)^0x0F) for c in s])
p4{xor_it_all_and_then_more}
Zadania z Captchami:
Użycie Tesseracta i naklepanie skryptu w Pythonie do automatycznego odpowiadania na zapytania pozwoliło na rozwiązanie dwóch pierwszych tasków.
Niezrobione zadania:
Remy Suarez Ascander
Analiza kodu w bodajże F#, a później coś z RSA. Jakoś nie bardzo mi się chciało zagłębiać w tę dziwna składnię (ale może to dlatego, że byłem wówczas już na szczycie rankingu ;) )
Where is my password #2
Myślałem, że to trudniejsze - ale nigdy nie byłem dobry w kryptografii. Jak mnie koledzy z IRCa później uświadomili, dało się to rozwiązać w dwóch linijkach, bo znamy plaintext, ciphertext i key, a potrzebujemy tylko IV: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29
Bodajże: IV=P1 xor Decrypt(key, C1), gdzie P1 i C1 to odpowiednio pierwsze bloki plain- i cipher-textu.
Impossibru captcha
Captcha z kreskami - co prawda je jakoś usuwałem, ale jednak tesseract nie dawał rady ze zniekształconymi nieco literami.
Jeśli ktoś czyta ten tekst i się czuje głupio, że sam na to nie wpadł, to niech pamięta, że opisuję tutaj jedynie udane próby. Spędziłem sporo czasu brnąc w ślepe uliczki i próbując rozwiązywać zadania w zły sposób - nie zniechęcajcie się więc zbyt szybko, bo tylko ten, który nie próbuje, nigdy się nie myli.
Podsumowując, CTF zaliczam zdecydowanie do udanych :)
karolinaaShalom