Skip to content

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.

Pasted image 20220826222430.png

Fight Boss

  • So I shall attempt to fight the boss straight away and I realised that there is an impossible boss to beat "Dragon".

Pasted image 20220826222452.png Pasted image 20220826222821.png Pasted image 20220826232930.png

Pasted image 20220829150133.png Pasted image 20220829150209.png Pasted image 20220829150120.png

Mine Gold

  • In the Mine Gold function I find out that after every "Mining" activity, the amount of Gold

Pasted image 20220826222632.png

Pasted image 20220826222546.png Pasted image 20220826222559.png

Go Shopping

Pasted image 20220826222706.png

battleevent.py

battleservice.py

command.py

Pasted image 20220829150803.png

workevent.py

Pasted image 20220826233015.png

Exploitation

  • Therefore from the above code, we can see that in battleservice.py has a function __compute_battle_outcome() which will iterate through the variable command and count the number of BOSS_ATTACK, ATTACK and HEAL.
  • 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 file command.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 the Command() class like below.

Pasted image 20220829151730.png

  • 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.

Pasted image 20220829152358.png

  • Now we will proceed to fighting the last boss and as can be seen, because we overpowered the previous bosses, our health remains full.

Pasted image 20220829152500.png

  • From below, we won the final boss and we got out flag!

Pasted image 20220829152553.png

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.

Pasted image 20220829153647.png Pasted image 20220829153526.png Pasted image 20220829153506.png

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")

Pasted image 20220829163804.png

Sending Payload Challenges

Pasted image 20220829181142.png

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

Pasted image 20220829181215.png

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")

Pasted image 20220829181155.png

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.

Pasted image 20220829193859.png

  • 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

Pasted image 20220830003212.png

  • We can tell that the 8 continuous bytes that was changed was f766 35ab therefore the flag for this challenge is TISC{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

Pasted image 20220830005958.png Pasted image 20220830010014.png Pasted image 20220830010030.png Pasted image 20220830201738.png

Recon

message.png

Pasted image 20220830010622.png Pasted image 20220830010558.png

message.png ADS

Pasted image 20220830013120.png Pasted image 20220830013140.png Pasted image 20220830015328.png

broken.pdf

Pasted image 20220830011441.png

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.

Pasted image 20220830021155.png

  • The mounting was successful as can be seen above and we see an image file below.

Pasted image 20220830021044.png

  • Following this link and the below comment :

Pasted image 20220830203643.png

  • Following the instructions above we get the following :

Pasted image 20220830204744.png Pasted image 20220830203020.png

  • 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,

Pasted image 20220830203210.png

  • There is a flag.ppsm file (macro-enabled powerpoint) and it corresponds with the PK header which stands for ZIP or compressed format - Powerpoint files are a kind of zipped files.

Pasted image 20220830203231.png

  • Using 7zip, we unzipped the ppsm file and we checked Media to see if there is any media within the powerpoint.

Pasted image 20220830203411.png Pasted image 20220830203509.png Pasted image 20220830203454.png

  • We opened one of the images and it says to get a MD5 hash of the sound clip to get the flag.

Pasted image 20220830203434.png

  • We get the hash of the sound clip with certutil and the result is below :

Pasted image 20220830204043.png

Flag : TISC{f9fc54d767edc937fc24f7827bf91cfe}