Hüseyin Altunkaynak Kişisel Blog

STMCTF - FirstOrder & backINtime

Bu sene MCLee takımı olarak katıldığımız yarışmada çok eğlendik. Eğlenirken öğrendik :) Coding kategorisindeki 2 adet sorunun çözümünü paylaşmak istedim. Çözerken çok yordu ama en sonunda gelen flag çok mutlu etti. Tabi geçen senelerdeki soruların çözümüne bakmamız gerektiğini de flagle bize hatırlattılar. Tekerleği yeniden icad ederek flagi bulmuş olduk. Son olarak yarışmayı hazırlayan ekibe de buradan teşekkürümü edip çözümlerden bahsetmek istiyorum.

Twitter Linki: https://twitter.com/StmCTF

FirstOrder

FirstOrder adlı soru için verilen linke gittiğimizde bize aşağıdaki gibi responselar dönüyordu.

['this', 'be', '67', '81', 'with', 'are', 'the', 'you', 'was', 'have', 'for', 'is', 'to', 'in', '50', 'a', '59', 'as', 'on', '59', 'that', '2', '17', '72', '35', '55', 'and', '58', 'of', 'it']-->Words first order
['your', 'this', 'are', 'from', 'or', 'to', 'of', 'at', '29', '17', '63', 'was', 'for', 'be', 'we', 'not', 'is', 'on', 'as', 'with', 'and', 'that', 'have', 'a', 'the', '52', 'in', 'you', '47', 'it']-->Numbers first order

Soruda yapılan açıklamaya göre bize verilen listeyi sonundaki Numbers ve Words etiketlerini dikkate alarak önceliği belirleyip ardından sıralayarak tekrar göndermekti. Post isteğini göndermek için çok kısa bir süre tanımlandığından dolayı küçük bir script yazmamız isteniyordu. Başta Javascript ile yazmak istesemde Python galip geldi ve daldım programlamaya.

import requests
import json

url = "https://zvlhch4ygd.execute-api.eu-west-1.amazonaws.com/production/challenge"
r = requests.get(url)

# Response'un parse edilmesi
text = r.text
text1 = text.split("-->")[0][1:-1].split("'")
text1 = [x for x in text1 if x != ", "]
text1.remove("")
text1.remove("")

numbers = []
texts = []
for den in text1:
    if (den.isnumeric()):
        den = int(den)
        numbers.append(den)
    else:
        texts.append(den)

numbers.sort()
texts.sort()

if (text.split("-->")[1].split(" ")[0] == "Words"):
    liste = texts + numbers
else:
    liste = numbers + texts

# Bizden istenen json veri
flag = {
    "answer": liste
}
print(json.dumps(flag))

r = requests.post(url, data=json.dumps(flag))
print(r.text)

firstorder

STMCTF{41g0riThm5_iN_YoUr_l1f3}

backINtime

Coding kategorisindeki asıl güzel olan soru buydu. Önceki senelerde sorulan decode döngü sorularının benzeriydi ama bakmak hiç aklıma gelmedi. Flagi aldıktan sonra farkettik ama biraz geç oldu :)

Flage gitmek için iç içe geçmiş 200 den fazla encoding ve sıkıştırma işlemini tersine çevirmemiz gerekiyordu. Bunu başlarda manuel yapmaya çalışsamda bu şekilde olmayacağını farketmem uzun sürdü. Çünkü zamanın nasıl geçtiğini anlamadım bile :) Gece 4 civarı hala bu soruya uğraşıyordum. En son dedim bu böyle olmayacak buna bi kod yazalım. Dedim ama baktım ki yeni kütüphaneler öğrenmem gerekecek. El mecbur bir kütüphane ile günü kurtardık. Linux kullanıyor olmanın rahatlığı ile os.system() yapıştırdım geçtim.

Sorunun benim için zor olan kısımlarında birisi de başlardaki bz2_codec(flag)= ifadesini binary olan dosyadan otomatik ayırmaktı. Pythonda, dosyayı binary okumanın önemini burada anladım.

Bize verilen flag.txt: flag.txt

import base64
import os
import codecs

def decode_base64(in_file):
    print("base64", in_file)
    file1 = open(str(in_file), "r")
    b64 = file1.read()
    bb64 = b64.encode()
    decoded = base64.b64decode(bb64)
    barray64 = bytearray(decoded)
    metod = find_metod(barray64)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+1), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+1)

def decode_base16(in_file):
    print("base16", in_file)
    file1 = open(str(in_file), "r")
    b16 = file1.read()
    decoded = base64.b16decode(b16)
    barray16 = bytearray(decoded)
    metod = find_metod(barray16)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+1), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+1)

def decode_base32(in_file):
    print("base32", in_file)
    file1 = open(str(in_file), "r")
    b32 = file1.read()
    bb32 = b32.encode()
    decoded = base64.b32decode(bb32)
    barray32 = bytearray(decoded)
    metod = find_metod(barray32)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+1), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+1)

def decompress_zlib(in_file):
    print("zlib", in_file)
    os.system("zlib-flate -uncompress < {} > {}".format(in_file, in_file+1))
    file1 = open(str(in_file+1), "rb")
    bencode = file1.read()
    berrey = bytearray(bencode)
    metod = find_metod(berrey)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+2), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+2)

def decompress_bzip2(in_file):
    print("bz", in_file)
    os.system("bzcat {} > {}".format(in_file, in_file+1))
    file1 = open(str(in_file+1), "rb")
    bencode = file1.read()
    berrey = bytearray(bencode)
    metod = find_metod(berrey)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+2), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+2)

def decode_rot13(in_file):
    print("rot", in_file)
    file1 = open(str(in_file), "r")
    rot13 = file1.read()
    decoded = codecs.decode(rot13, "rot_13")
    barrayrot = bytearray(decoded.encode())
    metod = find_metod(barrayrot)
    decoded2 = bytes(metod[1])
    file2 = open(str(in_file+1), "wb")
    file2.write(decoded2)
    file1.close()
    file2.close()
    return (metod[0], in_file+1)

def find_metod(babase):
    if(chr(babase[0]) == "z"):
        # zlib_codec(flag)= tarzı ifadeleri kaldırma
        babase = babase[17:]
        return ["zlib", babase]
    if(chr(babase[0]) == "r"):
        babase = babase[13:]
        return ["rot13", babase]
    if(chr(babase[1]) == "z"):
        babase = babase[16:]
        return ["bz2", babase]
    if(chr(babase[4]) == "1"):
        babase = babase[13:]
        return ["base16", babase]
    if(chr(babase[4]) == "3"):
        babase = babase[13:]
        return ["base32", babase]
    if(chr(babase[4]) == "6"):
        babase = babase[13:]
        return ["base64", babase]

if __name__ == "__main__":
    file1 = open("flag.txt", "rb")
    metod = find_metod(file1.read())
    file2 = open("1", "wb")
    file2.write(metod[1])
    file1.close()
    file2.close()

    out_file = 1
    metod = "base64"

    for den in range(1, 300):
        if(metod == "base64"):
            metod, out_file = decode_base64(out_file)
        if(metod == "base32"):
            metod, out_file = decode_base32(out_file)
        if(metod == "base16"):
            metod, out_file = decode_base16(out_file)
        if(metod == "zlib"):
            metod, out_file = decompress_zlib(out_file)
        if(metod == "bz2"):
            metod, out_file = decompress_bzip2(out_file)
        if(metod == "rot13"):
            metod, out_file = decode_rot13(out_file)

backintime01

Program çok güzel şekilde çalışmasına rağmen son adımda hata verdi. Son adımı da manuel yapmaya karar verdim. Fonksiyon hexadecimale uygun olmadığı için online bir decoder buldum. İşlemlerin hepsini adım adım dosyalar üzerinde yaptığım için hata vermeden önceki dosyayı açtım ve son adım için gerekli olan decode işlemini bu sayfadan yaptım.

backintime02

base16(flag)=53544D4354467B57655375676765737452656164696E6757726974657570734F664F6C6453544D4354464368616C6C656E6765737D
STMCTF{WeSuggestReadingWriteupsOfOldSTMCTFChallenges}

all tags