PicoCTF-2023-writeup
I want to share my experience with the PicoCTF I participated which lasted for 2weeks and it was really fun and fascinating to play with and I learnt a lot from it. I participated with team 8h037.
The whole team struggled to secure 1st position in Africa thanks to the team contribution. I want to share my writeup on various challenges I solved.
And you can also get the rest of the challenges writeup on my team mates github
Let get to the fun part of the challenges I solved and I hope y’all like it.
Forensics
Who Is It
Looking at the description, we are task to identify whose mail server the email is actually originated from.
Let download the file given and see what we can get from there and proceed to the next challenges.
This is the content of the file we downloaded and we got a IP which is 173.249.33.206 that is some lead there which can get us to the sender of the mail.
I decided to use the challenge name and search for whois online on google which lead me to a website.
Website Used: whois
As we can see above we we’re able to retrieve the scammer name by using the above link. That is a wrap I know right .
Flag: PicoCTF{Wilhelm Zwalina}
FIND AND OPEN
FindAndOpen a very cool challenge which two files was given, one for the zip file that need a password before we can extract it and the second file is what we need to analyse and get the first file password.
This are the two downloaded file which is flag.zip which consist the flag and a pcap file which we can use wireshark to analyse it and get what we needed from it.
By analysing the pcap file we found an encoded string that look like base64.
Let head to Cyberchef and try to decode it.
We got the secret key to the flag.zip file so let try to extract it with the key we just found and see what happen next.
Extracting the flag.zip with the key we got gave out a file name flag which contain the flag we need.
Flag: picoCTF{R34DING_L0Kd_fil56_succ3ss_cbf2ebf6}
MSB
This time we are dealing with image. Let download it and see what we have to do here.
This is the image which look corrupted and if we can recall the challenge is called MSB. Let search about that online we might get something interesting.
Site used: stegonline
As we can see in the image below the website as Bit Order of MSB so all we have to do is click on go to extract what is hidden inside.
We are able to retrive some readable ascii text so let download it and obtain the full data.
That is the extracted file we got from the online tools let try to get our flag from it.
Command Use: cat Ninja-and-Prince-Genji-Ukiyoe-Utagawa-Kunisadaflag.dat | grep picoCTF
Boom and we have our flag. Seems easy and fun right?
Flag: picoCTF{15_y0ur_que57_qu1x071c_0r_h3r01c_06326238}
Unforgotten Bits
I spent some couples of hours on this challenge I don’t even think it’s an hours 🤔 I used a complete whole day to get it done.
Let download the given files which is a disk img so I decided to use Autopsy on it.
Autopsy offers GUI access to a variety of investigative command-line tools from The Sleuth Kit, including file analysis, image and file hashing, deleted file recovery, and case management. To know more about Autopsy you might check this link out https://cipcyber.com/2020/03/digital-forensics-investigation-using-autopsy-in-kali-linux.html.
Using Autopsy
All we have to do here is click on new case.
We can name the case anything we feel like to name it so let click on new case again to proceed.
Next thing to do is click on add host.
Let click on add host again after to proceed forward.
This time we will click on add image.
Time to add our image by clicking on the add image file.
Next thing I did was to put the full path of where the disk img is located and click next.
Let click on add to move forward.
All we have to do is click on analyze to analyze the file.
Let look at the home directory to find something interesting.
All this is under /home/yone directory and as we can see we have some interesting stuff there.
I decided to look into Contents Of File: /3/home/yone/irclogs/01/04/#avidreader13.log and i got all this which is steghide credential but we don’t know for which image so let look around again.
We got some .bmp image under /home/yone/gallery directory now we can test the credential we found earlier on them before we can do that we have to use our Terminal that is the only place we can run steghide on the images.
Using the password we found earlier we we’re able to extract encoded strings let use same passwords on the others image.
Password Used: akalibardzyratrundle
I was able to get encoded txt files using same password but unfortunately the password didn’t work for the last image which is 7.bmp, We will look into that later but first let try to decoding the encrypted txt files.
Command Used: sudo openssl aes-256-cbc -d -in les-mis.txt.enc -out out.txt -K 58593a7522257f2a95cce9a68886ff78546784ad7db4473dbd91aecd9eefd508 -iv 7a12fd4dc1898efcd997a1b9496e7591 -S 0f3fa17eeacd53a9
If we can recall earlier we got some iv, key and salt in autopsy so I use that on the encoded files so we will use same methology on the rest of the encoded files we should already know how to do that so let try to figure out the 7.bmp file by going back to autopsy.
checking the Contents Of File: /3/home/yone/irclogs/02/04/#leagueoflegends.log we got a lot of reading text which is kinda boring to read although I read them all by viewing the irlogs. There was some talking about league of legends champion and so on.
I decided to check the contents of /home/yone/notes directory which has three files in it.
This look like half of the password we are looking for and they look like league of legends champions name. After roaming around for quite long I got a hit by generating a wordlists from Leagues of legend champions name to complete the half password of yasuoaatrox….
# Open the file containing the champion names
with open('champions.txt') as f:
champion_names = f.readlines()
# Remove any whitespace characters from the names
champion_names = [name.strip() for name in champion_names]
# Create a list to hold the combinations
combinations = []
# Loop through each champion name
for i in range(len(champion_names)):
# Loop through the remaining champion names
for j in range(i+1, len(champion_names)):
# Concatenate the two names and append to the combinations list
combination = champion_names[i] + champion_names[j]
combinations.append(combination)
# Write out the combinations to a new file
with open('wordlistsLOL.txt', 'w') as f:
for combination in combinations:
f.write(combination + '\n')
The champions.txt have all the names of the champions of league of legend which i compile.
Let run our script.
We just have to complete the half password now using a bash script.
#!/bin/bash
# Set the input and output file names
input_file="wordlistsLOL.txt"
output_file="new_wordlistsLOL.txt"
# Loop through each line in the input file
while read line; do
# Prepend "yasuoaatrox" to the beginning of the line and write it to the output file
echo "yasuoaatrox""$line" >> "$output_file"
done < "$input_file"
Now we run the script
And I found the password of the 7.bmp img so let use try it out.
I was able to extract a file name called ledger.1.txt.enc but when I try to decode it with the given key we found on Autopsy It didn’t work so let go back to Autopsy to dig deeper.
After spending couples of hours I Found something that look like a binary string so I took it to Cyberchef and try my luck to decrypt it but nothing seems to happen then i went back to autopsy to check for more details
Looking around lead me to browsing history that seems like a hint to the Binary strings so I went straight to google and search about how to decrypt a bits strings to ascii with golden ratio base.
I wrote this code to solve the problem and name it solve.py. Let test it out .
Finally we have gotten the salt, key and iv for the encoded ledger.enc.txt file so time to use openssl on it.
Command Used: sudo openssl aes-256-cbc -d -in ledger.1.txt.enc -out out1.txt -K a9f86b874bd927057a05408d274ee3a88a83ad972217b81fdc2bb8e8ca8736da -iv 908458e48fc8db1c5a46f18f0feb119f -S 2350e88cbeaf16c9.
Boom and we have our flag after suffering for a day but I learnt a lot.
Flag: picoCTF{f473_53413d_40405b89}
Cryptography
POWER ANALYSIS: PART 2
This time we are dealing with cryptography challenges which we are task to look for the encryption key. Let go ahead and download the given zip file.
After I extracted the given zip file as we can see above It gave out 100 txt files so I decided to read one of the files.
The plaintext and power traces seems interesting so i rushed to my google and did a little research on power analysis attack and luckily i found a writeup about a Google CTF 2022 that seems to be on power analysis attack link but we seems to have no traces.json file but we did have a zip file that contains a txt files with a plaintext and the power trace i quickly write a python code to extract the power trace from each of the files and save to trace.json.
import json
# ANSI escape codes for colors
GREEN = "\033[32m"
RESET = "\033[0m"
plaintexts = []
traces = []
for i in range(100):
filename = f'trace{str(i).zfill(2)}.txt'
pt, trace = open(filename, 'r').read().split('\n')
pt = bytes.fromhex(pt.split(' ')[-1])
assert len(pt) == 16
trace = trace.split("Power trace: ")[-1]
trace = eval(trace)
plaintexts.append(pt)
traces.append(trace)
out = []
for pt, trace in zip(plaintexts, traces):
out.append({"pt":list(pt), "pm":trace})
# Write output to file
with open("traces.json", "w") as f:
f.write(json.dumps(out))
# Print success message
print(f"{GREEN}[SUCCESS]{RESET} Output written to traces.json.")
Now let put this as trace.py to get the traces.json.
We have successly retrieve the traces.json so now it time to run our script we got from the googleCTF.
This is the first script I tried.
That is the hex but unfortunately when I try to submit it, It gave incorrect flag so I went back to google and do more research about googleCTF and I got another different script.
Link: github
This is the link that gave me the right flag so let check the script out.
Running the script gave out an error so I decided to edit it by removing some line.
I decided to remove the line I circle above then i retry the script.
I don’t know why the webshell keep on killing the script let try it on our terminal.
Boom that’s the flag we are looking right there kinda fun to play with right.
Flag: picoCTF{2f4981b159a0a78a5e222bc537f894ae}
POWER ANALYSIS: PART 1
Now let look into power analysis 1 by lauching the instance we can see a running server given all we have to do first is by getting the traces.json like we did in power analysis 2 so let check what the server does.
It ask us to provide 16 bytes of plaintext encoded as hex let get the traces.json file and move forward
This is my script i used to get the json file
So lets run it. It runs perfectly without any error that cool right.
It time to use same solve script of power analysis 2 which is the screenshot below.
I provided the solve script in power analysis 2 and you can get it if you go back to the top expalation of power analysis 2 that i did.
That’s the encryption key use for Power analysis 1 which will be our flag.
Flag: picoCTF{65cce0eab280e39d12625c7315b03fa1}
POWER ANALYSIS: WARMUP
The warmup PowerAnalysis challenge was actually hard I spend almost 4hours getting it done running my script 16 times let connect to the address with ncat.
Asking us to provide a 16 bytes plaintext encoded as hex and should leak a bit to us trying 000000000000000000000000000000ef and we got a leakage result which is 7 if we can code a script for it.
Take an example:
000000000000000000000000000000ef
000000000000000000000000000000f0
000000000000000000000000000000f1
000000000000000000000000000000f2
000000000000000000000000000000f3
000000000000000000000000000000f4
000000000000000000000000000000f5
000000000000000000000000000000f6
000000000000000000000000000000f7
000000000000000000000000000000f8
000000000000000000000000000000f9
000000000000000000000000000000fa
000000000000000000000000000000fb
000000000000000000000000000000fc
000000000000000000000000000000fd
000000000000000000000000000000fe
000000000000000000000000000000ff
We have to send 256 of that to the server so i scripted it to make it easy.
from pwn import remote
data1=b""
data3=b"000000000000000000000000000000"
i = 0
fo=open("output.txt",'wb')
while 1:
if i == 256 : break
r=remote('saturn.picoctf.net',64600)
r.recvuntil("Please provide 16 bytes of plaintext encoded as hex: ")
data2 = str(hex(i))[2:].encode()
if len(data2) == 1: data2=b'0'+data2
print(data1 + data2 + data3)
r.sendline(data1 + data2 + data3)
r.recvuntil("leakage result: ")
fo.write(r.recvline().rstrip()+b"\n")
i += 1
fo.close()
Running when it done we should get the output save in output.txt.
Now a little thing to break down when the output is 7 => the leak at the position is changing = > 0 and 8 => the leak at that position is changing = 1 so we just have to script it out to convert all 7 = 0 and 8 =1.
def convert_file(input_filename, output_filename):
with open(input_filename, "r") as input_file:
input_str = input_file.read()
output_str = ""
for char in input_str:
if char == "7":
output_str += "0"
elif char == "8":
output_str += "1"
else:
output_str += char
with open(output_filename, "w") as output_file:
output_file.write(output_str)
input_filename = "output.txt"
output_filename = "new_output.txt"
convert_file(input_filename, output_filename)
Running it creates the new output file
Now that we have it we can try brute forcing the key now since we have been given Sbox in encrypt.py file.
Sbox = (
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
)
ls=[]
with open("new_output.txt",'rb') as f:
for lines in f:
ls.append(lines.rstrip())
print(ls)
res=[]
for i in range(256):
for j in range(len(ls)):
print(i,j,Sbox[i^j],Sbox[i^j]&0x01)
if (str((Sbox[i^j]&0x01)).encode() != ls[j]) : break
if (j == len(ls) - 1): res.append(i)
print(res)
Now with the script above we can run our brute forcing to get the first key.
We got 157 which is the first key now we have the same process like 15 more times but NOTE we need to remove 00 from data3 and add to data1 just like that below.
from pwn import remote
data1=b"00"
data3=b"0000000000000000000000000000"
i = 0
fo=open("output.txt",'wb')
while 1:
if i == 256 : break
r=remote('saturn.picoctf.net',64600)
r.recvuntil("Please provide 16 bytes of plaintext encoded as hex: ")
data2 = str(hex(i))[2:].encode()
if len(data2) == 1: data2=b'0'+data2
print(data1 + data2 + data3)
r.sendline(data1 + data2 + data3)
r.recvuntil("leakage result: ")
fo.write(r.recvline().rstrip()+b"\n")
i += 1
fo.close()
Each time we got a key we need to keep editting out script till data3 is empty and data1 have everything.
data1=b"0000"
data3=b"00000000000000000000000000"
data1=b"000000"
data3=b"000000000000000000000000"
Till data3 is empty and remember any number you get the lowest should be 0 and the highest should be 1 with the same processs now that we have all the keys we can now convert it to hex to have our flag.
157 172 157 145 65 84 219 5 45 124 225 161 16 251 179 170
We can use cyberchef to convert it from decimal to hex.
That’s our flag.
Flag: picoCTF{9dac9d914154db052d7ce1a110fbb3aa}
Reverse Engineering
Virtual Machine 0
We we’re given two files to download The first one is the dae file which we can use blender on it to view in 3D while the second one is an input.txt files that contain numbers which lead to the flag but we have to multiply it by another number and it only the dae files that can give us the number to multply with the input files number.
This is what it look like after opening it with blender so all we have to do is try to open it and see what is inside the red axles and blue axles.
So I decided to delete the black blocks to show the red axles and the blue axles from there I counted all the whole tooth in red axles which is 40 in total and also counted the blue axles tooth which 8 then I divide it as 40 divided by 8 and it gave me 5.
I multiply the input.txt file which is the bigger number by 5 we got and I indicate it the input as c it was the input given on the challenge. All we have to do is convert our final number to binary and then decode from binary which will gave us the flag.
We have convert it to binary all left is to decode from binary to get the flag.
Boom and that’s our flag right there.
Flag: picoCTF{g34r5_0f_m0r3_3537e50a}
Virtual Machine 1
Virtual Machine 1 is more complicate than the first one. I spent a lot of time to get this and as you can see we we’re give an instance so let connect to the server and see what it does and download the file given which is also a dae file.
As we can see we we’re given an input number which is 11277 and the number do change because when you restart the instance and connect to the server it will bring another number so you might see some change sin number while making the writeup now let look through the dae file to get the number we can multiply it with.
This is how virtual machine 1 look like kinda stressful but it part of learning so I went to google and search about how to calculate the ratio between three adjacent gear and I found a website that help out link in 1 rotation of the axel will result in how many total rotations of the gears that is how I found out the number to be 9359 I actually use a pen and piece of paper to do the calculation which is really stressful for me. so let multiply the number of the input with the number we got.
The instance die and I restart it that is why the number change from 11277 to 8010 so by multiplying 8010 by 9359 gave us 74965590 which will be the answer we will provide to the server.
There goes our flag.
Flag: picoCTF{m0r3_g34r5_3g4d_1fe58bda}