Writeup, script, coordination, and research repo for Patriot CTF 2023
import os
import glob
import json
import httpx

TOP_LEVEL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
AUTOMATION_DIR = os.path.dirname(os.path.abspath(__file__))

DIRECTORY_LIST = [ y for y in glob.glob(os.path.join(TOP_LEVEL_DIR, '*')) if os.path.isdir(y) ]
DIRECTORY_LIST.sort()

SUB_DIRECTORY_LIST = [ y for x in DIRECTORY_LIST for y in glob.glob(os.path.join(x, '*')) if os.path.isdir(y) ]
SUB_DIRECTORY_LIST.sort()
# call the CTF Time API from the url in event.txt

with open(os.path.join(AUTOMATION_DIR, 'Change-Me/event.txt'), 'r') as f:
    event_url = f.read()
    # generate the api url from the event url
    api_url = event_url.replace('ctftime.org/event/', 'ctftime.org/api/v1/events/')

# get the event description from the api url
r = httpx.get(api_url + '/')
event_description = r.json()['description']
event_name = r.json()['title']

# Open the descriptions file and read the descriptions into a list
with open(os.path.join(AUTOMATION_DIR, 'Read-Only/descriptions.json'), 'r') as f:
    descriptions = json.load(f)

# generate the README.md file. 
# generate an unordered list of the directories and subdirectories in the repository. 
# should be in the format of:
# * [directory name](directory link)
#   * [subdirectory name](subdirectory link)
#   * [subdirectory name](subdirectory link)
# and so on...

with open(os.path.join(TOP_LEVEL_DIR, 'README.md'), 'w') as f:
    f.write('# ' + event_name + '\n\n')
    f.write(event_url + '\n\n')
    f.write('## Event Description\n\n')
    f.write(event_description + '\n\n')
    for directory in DIRECTORY_LIST:
        f.write('## [{}](<{}>)\n'.format(os.path.basename(directory), os.path.basename(directory)))
        for subdirectory in SUB_DIRECTORY_LIST:
            if os.path.dirname(subdirectory) == directory:
                f.write(' * #### [{}](<{}/{}/>)\n'.format(os.path.basename(subdirectory), os.path.basename(directory), os.path.basename(subdirectory) ))

# do the same thing for the README in each directory
for directory in DIRECTORY_LIST:
    with open(os.path.join(directory, 'README.md'), 'w') as f:
        f.write('# ' + os.path.basename(directory) + '\n\n')
        # From the descriptions var, check if the directory name is contained in the category and if so, write the description to the README
        f.write('### Category Description\n\n')
        for category in descriptions['categories']:
            if os.path.basename(directory) in category['name']:
                f.write(category['details']['description'] + '\n\n')
        f.write('## Challenges\n\n')
        for subdirectory in SUB_DIRECTORY_LIST:
            if os.path.dirname(subdirectory) == directory:
                f.write('- ### [{}](<{}>)\n'.format(os.path.basename(subdirectory), os.path.basename(subdirectory)))
.automation/index.py
ResetSec/PatriotCTF-2023
from Crypto.Hash import SHA, SHA1, MD2, MD4, MD5, SHA224, SHA256, SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, TupleHash128, TupleHash256, BLAKE2s, BLAKE2b
algos = [SHA, SHA1, MD2, MD4, MD5, SHA224, SHA256, SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, TupleHash128, TupleHash256, BLAKE2s, BLAKE2b]
import string
with open("BreakfastPasswords.txt", "r") as f:
    hashes = f.readlines()

flag = ""
for i in range(len(hashes)):
    algo, hash = hashes[i].split(" ")
    algo = algos[i]
    for char in string.printable:
        test_hash = algo.new()
        test_hash.update(char.encode())
        if test_hash.hexdigest() in hash:
            flag += char

print(flag)
Crypto/Breakfast Club/solve_Breakfast.py
ResetSec/PatriotCTF-2023
from Crypto.Util.number import inverse, long_to_bytes
ct = 54759004599647026122514406856463259157378742086576765421244403681057296667830958496097262677746909468103297432816490414974960025967213693421040371093540798741957150802518404127189506742415632446902481096660685226143139168835776151244118812818745848450316412121438483636074283621696771442062588211105702224797096594284830392179478934633773789319724361281826846525046587704425880624392223072702388140497093800595319096777828899843167601670276914798992771993918276031148033426480942116222001562109013541640188092750398752212726596965440829166079035212641935716410853385684323732317195302607653110572864832832492308614332695688026288520379691225852762946806737257238301231217698751952484355171918946864695694585061331718299798994297433154149373824622985169040067985382226600836882257453757742535197828643434202698460569184108581507634281208686802314678004371660462919488865692183302431661256061955513742244618890434230273318857591946851400449861980175942498279589784406195234672687906617881785093459544645790910945383784867571124154943079571223415398926441026293968354045886500561571326810144583303737574480859608505324180488889170197186871175999271657954999333530291298833058735090465076060239548834720762411779404098209293580868238466921597526031645695700528053632374874845185932714808431370633811502523716823233253451786716629551331404364972256882272398057080620635036019083703322493946834189252061534859326525293003316374735791004880070727032995927925012517689373392639682427582718014579410960338409525830939648282656446532813746549464546747380511872293584924550440836335584666857767951458610836477980076516864059214230403983895530230891408789302306325203234906970983917665145158863889393533463367162504710902317594257056239723173936694745323601923224395095916354161650048792002668682709118545891847039556531344563788200718268073364636546696496449249304700845489683618878058637196637029487619802085884870782067462172988768589896393636504395939721367767239915021596943439462134035647695619496772122726337729191387011155654027977443603283338951893855590636103517011604511158111104893275895159828829025697557539673460337393857004875529156640158439781534266181143797969599285806376638562160457655232891670383782099559129401371578394437360288146260479509996113420815925580470892601019143611638145200265373771650504910779904325868578063492818604204326923531004660704531023499416374365214282656114536666455627295115405857300937775736555543797882713184445755824314743287083 
e = 65537

p = 752756528841875537911878995753042707647403949554360208367234877025624409540203682761921093915508418655852799100141664622335039455920022213609629067262019404612608900257336038659394515010131767517305770031660647162848609109822750643234640501869740955176655922145570708435217100522986867976006579678556886154064634200401859738311135275046545253349948244695029660140086807289271141101862789519751792359117649145998563961368942821022739792392716620716795592972055314693267400368927621775645833555066476806996288903284102193917193424100068717536343788993196099054983601286805432602788326469869468644448618558376266945936822260704639989072737441301312016573245856870596451013862168846041144962976913828840204703903519058925554216678932337578982416183815574423593903203140061821312979288304894805529113548445359754020916457961543405670043499378618149742163277100368075376976838192481235095913624354114215289486427358337371249645934091262158698478769080944913191018283682299227448548572620178211758775226399248736351823883253425428859608839822967748417750750768678997191631591453855893210333524224040810300416007274952248435723849035137713609019261006737832050925751968653488941495762445378969236893490220931960617082372175080757226428538037
q = 880398969251452887308660917504486182562846904076287121291763168719274136746566491678268037510905591990771798869782714420383346558397372393848950944120645649208321456758294667377506618947318155191556866564510660193561519685221217401809653517643739084470712009338319620153911750948178187377988580670621276663435429513039194166524665848331078509242778461325908028625612645176647057551931509423846025480365963513278356214803825583621656344773968156935822116713294271209716208332966958714033498575400100929432657699444697408341784580190674105709745459315906374144815643729066799108493717417753626735266610965158888422349537481792575479701428877195230383568296602594553805793662138189357884360599766137250987445388558207947305949875916134750004434379767332412127692481777269654899411040863041093873128187130822708039864773659377990453077182559620579273207601721543020232868137483373438109337018806333516965007507716183075768926336370269493707028653198744031420944067462865900096247705191920717575149703524335706216759290920064723973507925674189242744371890566278426602689696896442712046610306732798031648865549772061987449249681612534599958604135136995325790860158962960039727556175624948552406762985831640742320290062631120287472335619521
n = p*q

phi = (p-1)*(q-1)
d = inverse(e,phi)
m = pow(ct,d,n)
print(m)

print(long_to_bytes(m))
Crypto/ReReCaptcha/solve.py
ResetSec/PatriotCTF-2023
import pwn

chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def start():
    return pwn.remote("chal.pctf.competitivecyber.club", 4757)

def pad(s):
    return s + ("0" * (18 - len(s))) + "}"

def try_string(s):
    import time
    io = start()
    io.recv()
    io.send((s + "\n").encode())
    time.sleep(0.1)
    x = io.recv().decode()
    return x

base = "pctf{"
to_try = []

while len(base) < 18:
    for c in chars:
        # print(pad(base + c))
        out = try_string(pad(base + c))
        # print(out)
        if out.count("User") > len(base):
            print(out)
            base += c
            break
    print(base)
Misc/Flag Finder/script.py
ResetSec/PatriotCTF-2023
import string
from random import *

def finalstage(w):
    h = 0
    w = list(w)
    w.reverse()
    w = "".join(g for g in w)
    flag = ''

    while h < len(w):
        try:
            flag += w[h+1] + w[h]
        except:
            flag += w[h]
        h += 2
    return flag

def stage2(b):
    t = ""
    seed(10)
    
    for q in range(len(b)):
        t += chr(ord(b[q])-randint(0,5))
    
    flag = finalstage(t)
    return flag

def stage1(a):
    a = list(a)
    b = list(string.ascii_lowercase)
    
    for o in range(len(a)):
        a[o] = chr(ord(a[o])^o)
    
    z = "".join(x for x in a)
    
    for y in range(len(z)):
        b[y%len(b)] = chr((ord(z[y])^ord(a[y]))+len(b))
    
    flag = stage2(z)
    return flag


def entry(f):
    seed(10)
    f = list(f)
    f.reverse()
    f = "".join(i for i in f)
    
    flag = stage1(f)
    return flag

def decrypt_finalstage(flag):
    h = 0
    flag = list(flag)
    decrypted = ''

    while h < len(flag):
        try:
            decrypted += flag[h+1] + flag[h]
        except:
            decrypted += flag[h]
        h += 2

    decrypted = list(decrypted)
    decrypted.reverse()
    decrypted = "".join(g for g in decrypted)
    
    return decrypted

def decrypt_stage2(b):
    seed(10)
    t = ""
    
    for q in range(len(b)):
        t += chr(ord(b[q])+randint(0,5))
    return t

def decrypt_stage1(z):
    a = list(z)
    b = list(string.ascii_lowercase)
    
    for y in range(len(z)):
        b[y%len(b)] = chr(((ord(z[y])^ord(a[y]))-len(b)) % 0x110000)    
    for o in range(len(a)):
        a[o] = chr(ord(a[o])^o)
    
    flag = "".join(x for x in a)
    return flag

def decrypt_entry(f):
    f = list(f)
    f.reverse()
    f = "".join(i for i in f)
    return f

if __name__ == '__main__':
    flag = open('output.txt', 'r').readlines()[0]
    decrypted_flag = (((decrypt_entry(decrypt_stage1(decrypt_stage2(decrypt_finalstage(flag)))))))
    input = entry(decrypted_flag)

    if input == flag:
        print("What... how?")
        print("I guess you broke my 'beautiful' code :(")
        print(decrypted_flag)
    else:
        print("haha, nope. Try again!")

Reverse/Python Garbage Compiler/solve.py
ResetSec/PatriotCTF-2023