Hackthebox Cyber Apocalypse 2023 — Hardware

InersIn
6 min readMar 24, 2023

Cyber Apocalypse 2023 start on 18 march 2023, on this event i play category pwn and hardware. But on this article i’ll only write about secret code and hm74.

1. HM74

After download the provided file, we got one file encoder.sv

And when try to connect to the server using nc , we got response like this.

Based on the file encoder.sv and the output of nc connection, i grep the binary string from the nc connection and split it by 7 char.

from pwn import *

r = remote("178.62.9.10", 31350)
context.log_level = "critical"

encoded_str = r.recvline().decode().split(": ")[-1].strip()
encoded_bits = [int(x) for x in encoded_str]
decoded_bits = []
for i in range(0, len(encoded_bits), 7):
print(encoded_bits[i:i+7])

and the output will look like this.

We know the output is encoded using encoder.sv, so first we need to make the decoder. here’s the decoder:

def hamming_decoder(encoded_bits):
p0 = encoded_bits[0] ^ encoded_bits[2] ^ encoded_bits[4] ^ encoded_bits[6]
p1 = encoded_bits[1] ^ encoded_bits[2] ^ encoded_bits[5] ^ encoded_bits[6]
p2 = encoded_bits[3] ^ encoded_bits[4] ^ encoded_bits[5] ^ encoded_bits[6]
syndrome = p2 * 4 + p1 * 2 + p0
if syndrome == 0:
return encoded_bits[2], encoded_bits[4], encoded_bits[5], encoded_bits[6]
corrected_bit = (encoded_bits[syndrome-1] + 1) % 2
corrected_bits = encoded_bits[:]
corrected_bits[syndrome-1] = corrected_bit
return corrected_bits[2], corrected_bits[4], corrected_bits[5], corrected_bits[6]

Pass the split encoded_bits to hamming_decoder function.

from pwn import *

r = remote("178.62.9.10", 31350)
context.log_level = "critical"

encoded_str = r.recvline().decode().split(": ")[-1].strip()
encoded_bits = [int(x) for x in encoded_str]
decoded_bits = []
for i in range(0, len(encoded_bits), 7):
print(hammind_decoder(encoded_bits[i:i+7]))

after removing the junk bit from the string, we got the result is only 4 character.

We add the result to list and decode the binary string by 8 character and convert it from binary string to char.

decoded_str = ''.join(str(bit) for bit in decoded_bits)
ascii_string = ''.join(chr(int(decoded_str[i:i+8], 2)) for i in range(0, len(decoded_str), 8))
print(ascii_string)

We got the result.

But the result is gibberish, after running it a few times, I got decoded string in flag format.

But there’s no real flag after running it and then I realize there’s a readable string in another gibberish string.

So I try to find the character that the most showed for each index.

So I made a script that counts the out of each char for index 0 and sort it by the most showed, and do it continuously for each index.

Here’s the full script.

The script will run and find all character of the flag

Flag: HTB{hmm_w1th_s0m3_ana1ys15_y0u_c4n_3x7ract_7h3_h4mmin9_7_4_3nc_fl49}

2. Secret Code

We given 1 file hw_secret_codes.sal and 10 gbr file, which is gbr file is pcb design and .sal is Saleae file. First we can open the gbr file using online web https://www.pcbway.com/project/OnlineGerberViewer.html

I realized the design is for 7 segment display, then i open the .sal file using Logic 2.

I export the data into csv file.

I remove the timestamp and the header, so it’s look like this.

I made python script to get only data for each channel.

data = [x.replace(",","").strip() for x in open("digital.csv").readlines()]

And if we analyze the design pcb and check the 7 segment display pin input and the output.

As you can see the segment “a” is in pin 7, and “b” is in pin 6 etc. but if we check the pcb for example for segment “a”.

Follow the line that pointed by the red arrow we know segment “a” is at channel 2 and so on. Based on the exported data from Logic 2, we need to change the order of the data each channel.

def convert(s):
n = [s[2],s[5],s[4],s[0],s[6],s[7],s[3]]
return ''.join(n)

After change the order we need to find the combination of seven segment display that in range 0–9 and A-F in other word the output must be an hex value, why? because there’s not possible to display the real flag on seven segment display.

seven_segment_combinations = {
'1111110': '0',
'0110000': '1',
'1101101': '2',
'1111001': '3',
'0110011': '4',
'1011011': '5',
'1011111': '6',
'1110000': '7',
'1111111': '8',
'1111011': '9',
'1110111': 'A',
'0011111': 'B',
'1001110': 'C',
'0111101': 'D',
'1001111': 'E',
'1000111': 'F',
}

We now can run the script.

seven_segment_combinations = {
'1111110': '0',
'0110000': '1',
'1101101': '2',
'1111001': '3',
'0110011': '4',
'1011011': '5',
'1011111': '6',
'1110000': '7',
'1111111': '8',
'1111011': '9',
'1110111': 'A',
'0011111': 'B',
'1001110': 'C',
'0111101': 'D',
'1001111': 'E',
'1000111': 'F',
}

def convert(s):
n = [s[2],s[5],s[4],s[0],s[6],s[7],s[3]]
return ''.join(n)

data = [x.replace(",","").strip() for x in open("digital.csv").readlines()]
flag = ""
for x in data:
x = convert(x)
if seven_segment_combinations.get(x):
flag+=seven_segment_combinations[x]
print(flag)

and the result is like this

At this point i was stuck for hours, but after re-read the description.

To gain access to the tomb containing the relic, you must find a way to open the door. While scanning the surrounding area for any unusual signals, you come across a device that appears to be a fusion of various alien technologies. However, the device is broken into two pieces and you are unable to see the secret code displayed on it. The device is transmitting a new character every second and you must decipher the transmitted signals in order to retrieve the code and gain entry to the tomb.

Then i realize we need to split the string by 2 char and select only the even index and remove the char that repeat it self.

flag = [flag[i:i+2] for i in range(0, len(flag), 2)]

clean = ""
for x in range(0, len(flag), 1):
if len(set(flag[x]))==1:
clean+=flag[x]
flag = ""
for x in range(0, len(clean)-1,2):
flag+=clean[x]
print(flag)

Here’s the full code.

Flag: HTB{p0w32_c0m35_f20m_w17h1n@!#}

Can’t wait for the next event.

--

--

InersIn

PARSECT // IT Security Enthusiast // STOICISM // KEEP DO SOMETHING LEGAL