Solving a Covert-Channel Data Analysis Challenge from an ICS CTF

Summary0x01 Challenge description. 0x02 Detours. This is clearly an MP3 steganography challenge. Three conventional approaches come to mind: open it as text and search for 'flag'; inspect its waveform and spectrogram for Morse code; or check the MP3 for embedded files and extract them. The first idea found nothing. The waveform and spectrogram also contained no useful information…

CTFICS SecurityICSSteganography

0x01 Challenge Description

Figure 1
Figure 1

0x02 Detours

This is clearly an MP3 steganography challenge. Three conventional approaches come to mind:

  • Open the file as text and search directly for the keyword 'flag'.

  • Inspect the audio waveform and spectrogram for information that might be converted into Morse code.

  • Check the MP3 for hidden files and extract them.

I did not expect much from the first idea, and it indeed found nothing:

Figure 2
Figure 2

Second idea:

Waveform:

Figure 3
Figure 3

Spectrogram

Figure 4
Figure 4

None of these methods reveals useful information.

Third idea: use MP3Steno to extract a possible TXT file from the MP3:

Figure 5
Figure 5

The password appears to be icsc, and extraction succeeds:

Figure 6
Figure 6

Just as I expected a promising result, I opened the file and found:

Figure 7
Figure 7
Figure 8
Figure 8

What is this? The file begins with Yy, which is not a familiar file signature, and contains almost no complete, meaningful strings. Progress stalled for a while…

After getting nowhere for a while, I changed direction.

Binwalk reveals:

Figure 9
Figure 9

A JPEG is embedded in the file. It is probably the album cover, but may still be relevant, so run strings:

Figure 10
Figure 10

There are traces of Photoshop. Could that mean…?

Extract the image:

Figure 11
Figure 11

Various image-steganography techniques produced nothing, so I abandoned that path.

0x03 Solution

After the competition, I asked several researchers and eventually learned the intended solution.

Returning to the challenge, the hint says that information is transmitted in a 'private' way.

Opening the MP3 in 010 Editor and installing the suggested plugin reveals:

Figure 12
Figure 12

There is a private bit. Extracting that byte from every mf group and concatenating the results yields the answer.

The diagram shows that ms starts at 1C1B8h, byte 115128.

Figure 13
Figure 13
TEXT
uint32 frame_sync : 12

uint32 mpeg_id : 1

uint32 layer_id : 2

uint32 protection_bit : 1

uint32 bitrate_index : 4

uint32 frequency_index : 2

uint32 padding_bit : 1

uint32 private_bit : 1

uint32 channel_mode : 2

uint32 mode_extension : 2

uint32 copyright : 1

uint32 original : 1

uint32 emphasis : 2

12+1+2+1+4+2+1+1+2+2+1+1+2=32

There are four bytes in total. private_bit is 24, so it lies in the third byte.

Extraction should therefore begin at the preceding byte—the second byte—at address 115130.

Inspect each mf group.

Figure 14
Figure 14

Each group is 414h, or 1044 bytes, long.

This leads to the following script:

TEXT
# coding:utf-8
import re
import binascii

n = 115130
result = ''
fina = ''
file = open('flag-woody.mp3','rb')
while n < 2222222 :
    file.seek(n,0)
    n += 1044
    file_read_result = file.read(1)
    read_content = bin(ord(file_read_result))[-1]
    result = result + read_content
textArr = re.findall('.{'+str(8)+'}', result)
textArr.append(result[(len(textArr)*8):])
for i in textArr:
    fina = fina + hex(int(i,2))[2:].strip('\n')
fina = fina.decode('hex')
print fina

The final flag is:

Figure 15
Figure 15

Thanks to Batsu for the help.