Tags: processing signals spectrogram signal 

Rating:

# Hospital Under Siege 2021: Be still my beating heart

```plain
Description:
There is some speculation that some Implantable Cardioverter Defibrillator (ICD) model
from ACME INC have a 0-day vulnerability that is being exploited in the wild. That
caused a lot of patients to go to the hospital where all the cardiologists are on duty
to quickly respond to any incident.

The MICS Intrusion Detection System (MIDS), which was recently deployed in the hospital,
generated an intrusion alert and saved the raw capture of the communication. Your
mission is to discover who the attackers were targeting.

So we would not lose track of the raw capture, Bob split the file and uploaded it into
CTF, our ticket tracking system.

Flag:
Your flag is of the format: BHVCTF{X X X} where each X is one word, alphanumeric
characters and both upper and lower case. Include the space!

("If you see something like BHVCTF19, that's OK too, just don't tell anybody ;-)" --
challenge admin)
```

... that sounds troubling! We better analyze Bob's attached raw capture of
the IDS alert to understand what's going on.

## 1. Merging the Raw Capture

According to the challenge description, Bob split the file into multiple parts:

```bash
26M mics_ips_hackrf_center_402e6_sr_10e6.cs8.aa (sha512: ea807f2945ddf3b2617b526906fb24238bd3a36462ccaccd7ce3b5079d436d5d26bbd7a4f4a691cf67384c0be9620e98b52187f3c5b70bd8b61c9293c15012b2)
26M mics_ips_hackrf_center_402e6_sr_10e6.cs8.ab (sha512: 86345906b6c6ed4addce66d8d1c5efcaf5796108413108f3f5f8a5e8119654284e739ff818a90a65ba9de7d13084665e47432189dcd3ed3e903802b65ddcc392)
26M mics_ips_hackrf_center_402e6_sr_10e6.cs8.ac (sha512: cdce46b15e3d81508890119ef4e47c3ef05b3f0afb7f02e5308a47f4e645869e97ba0e3ba16e54c9ac2ba652e9ab07c281b7daa16ba61ba66ca618c0153ca13a)
23M mics_ips_hackrf_center_402e6_sr_10e6.cs8.ad (sha512: aa91d1ec683037450aafac0817b3a6db619695f695764b7da0e43fea21f7e53281be54ea7003d3c765a6552ffa0ce4af6001347d8fcde19c3af4c86e6c8c0dea)
```

The file extensions let us suggest that he used the [split](https://www.man7.org/linux/man-pages/man1/split.1.html) utility.
If that is true, we can join all parts by concatenating them in a single file:

```bash
$ cat mics_ips_hackrf_center_402e6_sr_10e6.cs8.a{a..d} > mics_ips_hackrf_center_402e6_sr_10e6.cs8
```

## 2. The File Format

The joined file is a raw capture of some communication between a potential adversary and a victim's
Implantable Cardioverter Defibrillator (ICD). We found that `cs8` stands for `complex signed 8 byte`.
It is a raw export format for [HackRF](https://greatscottgadgets.com/hackrf/) software defined radios, where each 8-byte block is an [I/Q](http://whiteboard.ping.se/SDR/IQ) radio signal sample in
signed complex format.

## 3. Inspecting the Spectrogram with Inspectrum

We assumed that the flag is some encoded signal that is apparent to the eye once visualized.
Thus, we used [inspectrum](https://github.com/miek/inspectrum), a signal analyzer that supports
the `cs8` format, to create a [spectrogram](https://en.wikipedia.org/wiki/Spectrogram) of the raw
I/Q samples:

![spectrogram](https://i.ibb.co/xsyF4rr/inspectrum.png)

[(full size)](https://i.ibb.co/xsyF4rr/inspectrum.png)

As seen in the screenshot above, there is a signal that alternates between ~245 kHz and ~255kHz
in some kind of pattern.
Please note that these might not be the real frequencies, as we arbitrarily chose a sample rate
of 1 MHz in the control panel (left side) to generate a reference scale.

## 4. Isolating the Signal

To cut out noise, we first adjusted the maximum and minimum power threshold filter:

![spectrogram2](https://i.ibb.co/wptXtnJ/inspectrum2.png)

[(full size)](https://i.ibb.co/wptXtnJ/inspectrum2.png)

The next step was to isolate a single symbol in the spectrogam. We zoomed into
the signal by adjusting zoom and the FFT window size.
Using [inspectrum's](https://github.com/miek/inspectrum) time selection feature, we enabled
cursors and reduced the symbol count to 1.
We then visually matched the cursor region with the duration of what we assumed to be a single
symbol inside the alternating pattern around timepoint 4000000:

![spectrogram3](https://i.ibb.co/R6KHn1L/inspectrum3.png)

[(full size)](https://i.ibb.co/R6KHn1L/inspectrum3.png)

Here, a single symbol's period is roughly `9.216 ms` which is, again, relative to the arbitrarily chosen sample rate.

Then, we added a frequency plot around the active range to get a single 2D line graph of the
signal's change in frequency over time (right-click in the spectrogram).
Using the 2D representation, we derived a threshold plot (right-click in the freq. plot) that creates
a digital curve we should be able to extract and decode.

![spectrogram4](https://i.ibb.co/jHxPYcQ/inspectrum4.png)

[(full size)](https://i.ibb.co/jHxPYcQ/inspectrum4.png)

![spectrogram5](https://i.ibb.co/3rQgtBn/inspectrum5.png)

[(full size)](https://i.ibb.co/3rQgtBn/inspectrum5.png)

## 5. Extracting and Decoding the Flag

To decode the signal, we had to make a few assumptions:

1. Binary 1 is encoded as high, 0 as low
2. Each symbol is a single bit
3. The decoded flag is in ASCII (challenge description)
4. When the flag is ASCII, the most significant bit of each byte must be zero

Unfortunately, we found that assumption 4 does not hold for the signal depicted in the previous screenshots.
After further analyzing the spectrogram, we noticed that the raw capture holds **eight clusters** of transmission over time.
We manually checked our assumptions against each cluster and finally found a promising larger region with 256 symbols around timepoint 30000000:

![spectrogram6](https://i.ibb.co/5Wxv5zt/inspectrum6.png)

[(full size)](https://i.ibb.co/5Wxv5zt/inspectrum6.png)

We exported the highlighted symbols via right-click and received the following encoded bits:

```plain
0100001001001000010101100100001101010100010001100011000100111001011110110100101001100001011011010110100101100101001000000100110001111001011011110110111001110011001000000100110101000011010000110100001101011000010110000101100001010110010010010100100101111101
```

Using python, we finally decode the flag:

```python
import binascii

encoded = 0b0100001001001000010101100100001101010100010001100011000100111001011110110100101001100001011011010110100101100101001000000100110001111001011011110110111001110011001000000100110101000011010000110100001101011000010110000101100001010110010010010100100101111101

flag = binascii.unhexlify('%x' % encoded).decode('ascii')
print(flag)
```

The output is:

```plain
BHVCTF19{Jamie Lyons MCCCXXXVII}
```

However, the challenge description states that the `19` can be ignored. Thus, our submission flag is:

```plain
BHVCTF{Jamie Lyons MCCCXXXVII}
```

## (6. Trivia)

The attacker's victim was James "Jamie" Lyons of the garage rock band [The Music Explosion](https://en.wikipedia.org/wiki/The_Music_Explosion), who sadly [died of a heart attack](https://www.wistv.com/story/5469423/little-bit-o-soul-singer-jamie-lyons-dies/) in 2006.