For this write up, I’ll be covering a couple challenges I solved on my own and with teammates as a part of the “Unusually Skilled Comedy Group” team.
Misc
For this challenge, we were provided with a custom version of rockyou.zip and asked to find a phone number in a specific format. Originally I used the following grep command to find the phone number, but this was incorrect.
grep -n -Eo '[2-9][0-9]{2} [2-9][0-9]{2}-[0-9]{4}' rockyou.txt
Eventually, the challenge was updated to be more specific about the phone number format we are looking for. With the new information, we can update our grep command to find the right number and build the flag.
grep -n -Eo '\([2-9][0-9]{2}\) [2-9][0-9]{2}-[0-9]{4}' rockyou.txt
# Flag
PCTF{7731484_4043037283}
For this challenge we were given a pyjail instance to connect to in order to get RCE and grab the flag.
After a couple tries unable to get the right command working, a teammate crafted the right command based off the ML data provided to us for the challenge and got code execution:
names = ['Alice', 'Bob', 'Charlie']; print(', '.join(names));import os;os.system('ls')
After that we were able to work together and find the flag in the MLjail directory.
# Flag
PCTF{M@chin3_1earning_d0_be_tR@nsformati0na1_1818726356}
In this challenge, we are given “binary” data and asked to retrieve the flag.
Inside the Binary.txt file we have the following data
1111111111001000101010111010111111101011111111110110110110110000011010010010111111111111110010100100000000000010101111111111001010000000000000000000001010011011110010100100101111111111111111111100101000000000000000000000000000000000101011111100101000000000000101001101100101001001010010100000000000010100000010100010100000010100110110010100100101111111110010100000000000000000000000000000000000000000000010101111111111100101000000000000000000000000000000000000000101001101100101001001011111111111111111001010000000000000000000000000000000001010111111001010000000000001010100101000000000000000000000000000000000000000000000101011111110010100000000000000000000010100110111111111111111100101000000000000000000000000000000000000000000000101001100101001001000000000000000101000000000000000000000000000000000000000000101011111111111111111001010000000000000000000000000000000000000000000001010010111111111111111111111001010011111111111111100101001000000000000000000000000000000000000101001101111111111111111110010100010100100000000000000000010101111111111111111100101001111111111111111111111110010100000000000000000000000000000000000000000000000000000000000010100010100101111100101000000000000000000101000000000000000000000000000000000000000000000000000000000101001100101001001000000000000000000000000000000000000000000000000000000101001101100000000101000101000101011111111001010000000000000000000000000001010010010111111111111111111111111111111001010
I pasted this in CyberChefbut something did not seem right. Next I tried using dCode, since its really good at finding obscure ciphers and recognizing certain esolangs. In this case the language was “Spoon” a variation of BrainFuck. Using the decoder below we were able to grab the flag.
# Flag
PCTF{Sp00N_F33d_M3_11191}
Crypto
This challenge give us a zip file containing the following 4 images name CT.png, E.png, P.png, and Q.png.
Base off the number provided in the E.png it looks like this challenge is a RSA challenge. First thing we need is the values stored in the images. We can write a quick script to grab the numbers for us.
import pytesseract
from PIL import Image
import zipfile
import io
zip_file_path = 'captcha.zip'
numbers_by_file = {}
with zipfile.ZipFile(zip_file_path, 'r') as zip_file:
for file_info in zip_file.infolist():
with zip_file.open(file_info) as image_file:
image_data = io.BytesIO(image_file.read())
image = Image.open(image_data)
text = pytesseract.image_to_string(image)
numbers_by_file[file_info.filename] = text.strip().replace('\n', '')
print("Extracted numbers from images:")
for filename, numbers in numbers_by_file.items():
print(f"File: {filename}")
print(numbers)
print()
Now that we have the numbers we can compute N and decrypt the ciphertext. I used old code from a stack exchange answer for cracking RSA with only P, Q and E here and modified it with the values from the images.
from Crypto.Util.number import long_to_bytes
def egcd(a, b):
x,y, u,v = 0,1, 1,0
while a != 0:
q, r = b//a, b%a
m, n = x-u*q, y-v*q
b,a, x,y, u,v = a,r, u,v, m,n
gcd = b
return gcd, x, y
def main():
p = 7527565288418755379118789957530427076474039495543602083672348770256244095402036827619210939155084186558527991001416646223350394559200222136096290672620194046126089002573360386593945150101317675173
057700316606471628486091098227506432346405018697409551766559221455707084352171005229868679760065796785568861540646342004018597383111352750465452533499482446950296601400868072892711411018627895197517923591
176491459985639613689428210227397923927166207167955929720553146932674003689276217756458335550664768069962889032841021939171934241000687175363437889931960990549836012868054326027883264698694686444486185583
762669459368222607046399890727374413013120165732458568705964510138621688460411449629769138288402047039035190589255542166789323375789824161838155744235939032031400618213129792883048948055291135484453597540
209164579615434056700434993786181497421632771003680753769768381924812350959136243541142152894864273583373712496459340912621586984787690809449131910182836822992274485485726201782117587752263992487363518238
832534254288596088398229677484177507507686789971916315914538558932103335242240408103004160072749522484357238490351377136090192610067378320509257519686534889414957624453789692368934902209319606170823721750
80757226428538037
q = 8803989692514528873086609175044861825628469040762871212917631687192741367465664916782680375109055919907717988697827144203833465583973723938489509441206456492083214567582946673775066189473181551915
568665645106601935615196852212174018096535176437390844707120093383196201539117509481781873779885806706212766634354295130391941665246658483310785092427784613259080286256126451766470575519315094238460254803
659635132783562148038255836216563447739681569358221167132942712097162083329669587140334985754001009294326576994446974083417845801906741057097454593159063741448156437290667991084937174177536267352666109651
588884223495374817925754797014288771952303835682966025945538057936621381893578843605997661372509874453885582079473059498759161347500044343797673324121276924817772696548994110408630410938731281871308227080
398647736593779904530771825596205792732076017215430202328681374833734381093370188063335169650075077161830757689263363702694937070286531987440314209440674628659000962477051919207175751497035243357062167592
909200647239735079256741892427443718905662784266026896968964427120466103067327980316488655497720619874492496816125345999586041351369953257908601589629600397275561756249485524067629858316407423202900626311
20287472335619521
e = 65537
ct = 547590045996470261225144068564632591573787420865767654212444036810572966678309584960972626777469094681032974328164904149749600259672136934210403710935407987419571508025184041271895067424156324469
024810966606852261431391688357761512441188128187458484503164121214384836360742836216967714420625882111057022247970965942848303921794789346337737893197243612818268465250465877044258806243922230727023881404
970938005953190967778288998431676016702769147989927719939182760311480334264809421162220015621090135416401880927503987522127265969654408291660790352126419357164108533856843237323171953026076531105728648328
324923086143326956880262885203796912258527629468067372572383012312176987519524843551719189468646956945850613317182997989942974331541493738246229851690400679853822266008368822574537577425351978286434342026
984605691841085815076342812086868023146780043716604629194888656921833024316612560619555137422446188904342302733188575919468514004498619801759424982795897844061952346726879066178817850934595446457909109453
837848675711241549430795712234153989264410262939683540458865005615713268101445833037375744808596085053241804888891701971868711759992716579549993335302912988330587350904650760602395488347207624117794040982
092935808682384669215975260316456957005280536323748748451859327148084313706338115025237168232332534517867166295513314043649722568822723980570806206350360190837033224939468341892520615348593265252930033163
747357910048800707270329959279250125176893733926396824275827180145794109603384095258309396482826564465328137465494645467473805118722935849245504408363355846668577679514586108364779800765168640592142304039
838955302308914087893023063252032349069709839176651451588638893935334633671625047109023175942570562397231739366947453236019232243950959163541616500487920026686827091185458918470395565313445637882007182680
733646365466964964492493047008454896836188780586371966370294876198020858848707820674621729887685898963936365043959397213677672399150215969434394621340356476956194967721227263377291913870111556540279774436
032833389518938555906361035170116045111581111048932758951598288290256975575396734603373938570048755291566401584397815342661811437979695992858063766385621604576552328916703837820995591294013715783944373602
881462604795099961134208159255804708926010191436116381452002653737716505049107799043258685780634928186042043269235310046607045310234994163743652142826561145366664556272951154058573009377757365555437978827
13184445755824314743287083
# compute n
n = p * q
# Compute phi(n)
phi = (p - 1) * (q - 1)
# Compute modular inverse of e
gcd, a, b = egcd(e, phi)
d = a
# Decrypt ciphertext
pt = pow(ct, d, n)
print("Flag is : " + str(long_to_bytes(pt).decode()))
if __name__ == "__main__":
main()
# Flag
PCTF{I_H0P3_U_U53D_0CR!}
In this challenge we were provided with multiple hashes. Each hash corresponds to a single character for the flag.
SHA 511993d3c99719e38a6779073019dacd7178ddb9
SHA1 32096c2e0eff33d844ee6d675407ace18289357d
MD2 ae8033c09e7cf93b230414cd919da992
MD4 189bb272d916eea5b99b2a572ad93e9a
MD5 f95b70fdc3088560732a5ac135644506
SHA224 7e27c59a202f5e2b2b3b5458300140ef7aa7edc3a97a605b788546a1
SHA256 c3641f8544d7c02f3580b07c0f9887f0c6a27ff5ab1d4a3e29caf197cfc299ae
SHA384 1861ebe932dc65c5f04d33f6972b13acc8b1e572344016bf3cc950f60bfad6fdc0e32f0318e8bba57cf756eac0a49fce
SHA512 9032fb94055d4d14e42185bdff59642b98fe6073f68f29d394620c4e698a86fb2e51351ca6997e6a164aae0b871cf789fbc6e0d863733d05903b4eb11be58d9c
SHA3_224 d22e03747b83667e3e84c78e9fb49f7c9376334b9cb337addbdf3ff9
SHA3_256 d14a329a1924592faf2d4ba6dc727d59af6afae983a0c208bf980237b63a5a6a
SHA3_384 3bd4e7dcad9d3c02adfa7aa5388727d346278a9a7b007f497b48a4fa2a12b9545c820df150854a8f8c494275bd6fd941
SHA3_512 2d44da53f305ab94b6365837b9803627ab098c41a6013694f9b468bccb9c13e95b3900365eb58924de7158a54467e984efcfdabdbcc9af9a940d49c51455b04c
TupleHash128 aed477850ed48df54054e9d3e7b8cae7e1764d949adb68fe4f24802ec464cb6c334ef97cc0453471fac5faf0118265bc9388062ccb704d5ac4010489bee201da
TupleHash256 a130e4df9144790d9c8824f90f4c1220a3eb5aa0cb296ab1f4f41f23f3ed0800f2ac3fad4f235a4ee601a8ca8bf0be394e06e53e2f789a6272f1bc54c4901d0c
BLAKE2s 5abf6b1a79dee98ea32a98195c61a667c29a3674e79c82e43f0d19b0efa4b6f7
BLAKE2b 7ae26253cfd42a3a090c44023c234ec63d0ffe63f8ad40b7913f3f646503b7a7cb8ac571d42a311ef71508344de72f30b57e5c100b402130060ebc947e07a59b
Based off this information we know the first 5 hashes will be “PCTF{” and the last character is “}”. Now we just need to crack the rest of the hashes to get the full flag.
We could have written a script for this challenge, but since each hash was only one character in plaintext we just did it manually between myself and another teammate. We ended up doubling our work and cracking the same hashes a couple times but I used the following command and format to crack each hash.
./hashcat.exe -a 3 -m $mode hash.txt ?a
We generated the following flag but were still missing the TupleHashes plaintext: “PCTF{H@5H_8R0**S}”. I used the following code to get the plaintext for the BLAKE2s and BLAKE2b hashes. (Even tho we knew the last character was } I just wanted to verify)
import hashlib
# BLAKE2s hash
Blake2s_hash= "5abf6b1a79dee98ea32a98195c61a667c29a3674e79c82e43f0d19b0efa4b6f7"
# Blake2b hash
Blake2b_hash = "7ae26253cfd42a3a090c44023c234ec63d0ffe63f8ad40b7913f3f646503b7a7cb8ac571d42a311ef71508344de72f30b57e5c100b402130060ebc947e07a59b"
def hash_blake2s(input_string):
return hashlib.blake2s(input_string.encode()).hexdigest()
def hash_blake2b(input_string):
return hashlib.blake2b(input_string.encode()).hexdigest()
# Loop through all possible characters
for char_code in range(32, 127):
char = chr(char_code)
hashed_char2s = hash_blake2s(char)
hashed_char2b = hash_blake2b(char)
if hashed_char2s == Blake2s_hash:
print(f"Blake2s password found: {char}")
if hashed_char2b == Blake2b_hash:
print(f"Blake2b password found: {char}")
While we were attempting to crack the TupleHash128 and TupleHash256 hashes, another teammate managed to guess the missing portion of the flag for us.
# Flag
PCTF{H@5H_8R0WnS}