CSIT TISC 2022 (1)¶
Level 1 : Slay The Dragon¶
The recently launched online RPG game "Slay The Dragon" has been hot topic in the online gaming community of late, due to a seemingly impossible final boss. Amongst the multiple tirades against the forementioned boss, much controversy has been brewing due to rumors of the game being a recruitment campaign for PALINDROME, the cybercriminal organisation responsible for recent cyberattacks on Singapore's critical infrastructure.
You are tasked to find a way to beat (hack) the game and provide us with the flag (a string in the format TISC{xxx}) that would be displayed after beating the final boss. Your success is critical to ensure the safety of Singapore's cyberspace, as it would allow us to send more undercover operatives to infiltrate PALINDROME.
To aid in your efforts, we have managed to obtain the source code of the game for you. We look forward to your success!
Recon¶
- In the initial stage of my recon, I will attempt to map out what the visible functions are by connecting directly and playing the game.
./client_linux_x64 --host chal00bq3ouweqtzva9xcobep6spl5m75fucey.ctf.sg --port 18261
Main Page¶
- From the Main Page Below, we can see that there is only 3 functions we can do : #Fight Boss, #Mine Gold and #Go Shopping.
- We can also see the Player stats from the Main Page.
Fight Boss¶
- So I shall attempt to fight the boss straight away and I realised that there is an impossible boss to beat "Dragon".
Mine Gold¶
- In the Mine Gold function I find out that after every "Mining" activity, the amount of Gold
Go Shopping¶
battleevent.py¶
battleservice.py¶
command.py¶
workevent.py¶
Exploitation¶
- Therefore from the above code, we can see that in battleservice.py has a function
__compute_battle_outcome()
which will iterate through the variablecommand
and count the number ofBOSS_ATTACK
,ATTACK
andHEAL
. - From Line 28 of
battleservice.py
self.history.log_commands_from_str(self.server.recv_command_str())
we know that the server receives the command sent by the client as string and these commands are interpreted in the filecommand.py
which is within the/src/core/models
- Hence all that we need to do is to send 100 "ATTACK" strings in one
Command.ATTACK
and we will be able to beat the last boss - "Dragon". - This can be done by modifying the
ATTACK
variable in theCommand()
class like below.
- Next we will need to modify battleevent.py accordingly so that the number of "ATTACKs" done will be reflected on client side which will then be validated.
- Now we will proceed to fighting the last boss and as can be seen, because we overpowered the previous bosses, our health remains full.
- From below, we won the final boss and we got out flag!
Level 2 : Leaky Matrices¶
Looks like PALINDROME implemented their own authentication protocol and cryptosystem to provide a secure handshake between any 2 services or devices. It does not look secure to us, can you take a look at what we have got?
Understanding Protocol¶
- The three main takeaways are as below.
Exploitation¶
- Hence the secret keys can be leaked in the "Challenge Me" phase, where we will have to reverse the
AND
operation first then reverse the matrix multiplication with the response and challenge to obtain the secret.
Leaking SECRET_KEY¶
- Basing on the image of the sample implementation, we copy the important functions to test the properties of matrix.
import sys
import numpy as np
def sysout(fstr):
sys.stdout.write(fstr)
sys.stdout.flush()
def vectostr(v):
return "".join(map(str,v.reshape(-1)))
def strtovec(s, rows=8, cols=1):
return np.fromiter(list(s),dtype="int").reshape(rows,cols)
SECRET_KEY = np.round(np.random.rand(8,8)).astype("int")
if __name__ == "__main__":
print(SECRET_KEY)
print("Challenge Me")
for i in range(8):
input_vec = input(f"Challenge Me #{i} <-- ")
assert len(input_vec) == 8
assert input_vec.count("1") + input_vec.count("0") == 8
input_vec = strtovec(input_vec)
#print(input_vec)
output_vec = (SECRET_KEY @ input_vec)
sysout(f"My Response --> {vectostr(output_vec)}\n")
output_vec = (SECRET_KEY @ input_vec)&1
sysout(f"My Response --> {vectostr(output_vec)}\n")
Sending Payload Challenges¶
1 0 1 0 1 0 0 1
1 0 1 0 0 1 1 0
1 1 1 1 0 0 1 1
0 0 1 0 1 0 0 0
0 0 1 0 0 1 1 1
1 0 1 0 0 1 1 0
1 1 1 0 1 1 1 1
0 0 0 0 0 1 1 1
import sys
import numpy as np
def sysout(fstr):
sys.stdout.write(fstr)
sys.stdout.flush()
def vectostr(v):
return "".join(map(str,v.reshape(-1)))
def strtovec(s, rows=8, cols=1):
return np.fromiter(list(s),dtype="int").reshape(rows,cols)
SECRET_KEY = np.matrix('1 0 1 0 1 0 0 1;1 0 1 0 0 1 1 0;1 1 1 1 0 0 1 1;0 0 1 0 1 0 0 0;0 0 1 0 0 1 1 1;1 0 1 0 0 1 1 0;1 1 1 0 1 1 1 1;0 0 0 0 0 1 1 1')
if __name__ == "__main__":
print(SECRET_KEY)
input2 = input(f"Challenge <-- ")
input2 = strtovec(input2)
# output = (SECRET_KEY@input2)
# sysout(f"Answer --> {vectostr(output)}\n")
output = (SECRET_KEY@input2)&1
sysout(f"Answer --> {vectostr(output)}\n")
Level 3 : Patient0 - Part 1¶
Palindrome has spread some virus to corrupt machines causing incorrect readings in patients' health measurements and rending them unusable. Inspect the file and see if you can uncover the 8 corrupted bytes that renders the file system unusable?
Recon¶
- Using File we realise that this file is a NTFS drive.
- We first repair drive with test disk.
testdisk PATIENT0
- Then we compare the unrepaired file with the repaired file.
xxd PATIENT0 > PATIENT0.hex
xxd PATIENT0_repaired > PATIENT0_repaired.hex
diff PATIENT0.hex PATIENT0_repaired.hex
- We can tell that the 8 continuous bytes that was changed was
f766 35ab
therefore the flag for this challenge isTISC{f76635ab}
.
Level 3 : PATIENT 0 - Part 2¶
Palindrome must have leaked one of their passwords as the 4 corrupted bytes (Part 1 flag)! Dig deeper to find what was hidden!
Hints¶
Recon¶
- In the Recon stage, we look around the repaired file systems for clues as stated in the hints and the following clues were found : #message png, #message png ADS, #broken pdf.
message.png¶
message.png ADS¶
broken.pdf¶
Unlocking Outer¶
- Taking the ADS
$RAND
we removed the clue strings with hex editors and proceeded to mount the file with TrueCrypt (derived from the clue and hints) and used the flag for #Level 3 Patient0 - Part 1 as password.
- The mounting was successful as can be seen above and we see an image file below.
- Following this link and the below comment :
- Following the instructions above we get the following :
- As can be seen, there is a hash collision that resembles what clue 4 has given :
c01lis1on
. With this as password, we managed to unlock the hidden compartment of the encrypted volume,
- There is a
flag.ppsm
file (macro-enabled powerpoint) and it corresponds with thePK
header which stands for ZIP or compressed format - Powerpoint files are a kind of zipped files.
- Using 7zip, we unzipped the ppsm file and we checked Media to see if there is any media within the powerpoint.
- We opened one of the images and it says to get a
MD5
hash of the sound clip to get the flag.
- We get the hash of the sound clip with certutil and the result is below :
Flag : TISC{f9fc54d767edc937fc24f7827bf91cfe}