*Zinky zoogle, zeep zop beep bop zatas zoshed?

Datas moshed? Vorp? 👨*

https://alien-interference.tuctf.com

The URL leads to a website with a button, which upon being clicked plays audio and displays a saucer moving around a strange background.

Screenshot of https://alien-interference.tuctf.com

The “chaotic” look of the background hints that this may be a kind of steganography challenge. Oftentimes, this look may come from an image being XOR’ed with another image or file. We also see various stripes of same-color pixels in the background, further suggesting the image was mixed with another file with some kind of structure to it.

Viewing the page source, we see the background in file challenge.bmp, linked as image/audio (a nonexistent MIME type).

<link type = "image/audio" href="challenge.bmp">

The source also contains code that checks some properties of the four.wav header.

const checkFile = async (filename) => {
    const response = await fetch(filename);

    const buffer = await response.arrayBuffer();
    const view = new DataView(buffer);

    const chunkID = String.fromCharCode(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3));
    const format = String.fromCharCode(view.getUint8(8), view.getUint8(9), view.getUint8(10), view.getUint8(11));
    console.log(`chunkID: ${chunkID}, format: ${format}`);

    if ((view.getUint8(20) | view.getUint8(21) << 8) !== 7) { // The voices tell me this is very important.
        alert('Encoding Error!');
        return;
    }
}


document.getElementById("play-button").addEventListener("click", () => {
    document.getElementById("modal-overlay").classList.add("hidden");

    document.getElementById("content").style.display = "block";

    const allFiles = ["four.wav", ]; // TODO

    for(let file of allFiles) {
        checkFile(file);
    }

    const audioElem = document.getElementById('bgmusic');
    audioElem.src = allFiles[0];
    audioElem.volume = 0.5; // you're welcome.
    audioElem.play();
});

Both of these hint at the flag being hidden in these two files. As such, we focus on finding similarities between the two files challenge.bmp and four.wav. Looking at the files in a hex editor like HexEd.it, we see that the files seem quite similar in terms of content, just with an offset.

Screenshot of the hex dump of challenge.bmp
Screenshot of the hex dump of four.wav

In the images above, we find an offset of 0x5c92f - 0x5c8f5 = 58 between the start of two similar chunks. Indeed, we can confirm that offsetting four.wav by shifting it 58 bytes to the left results in the most bytes matching up with challenge.bmp.

We create a new file with the first 58 bytes (header) of challenge.bmp and fill most of the remaining bytes with the XOR between challenge.bmp with the shifted version of four.wav. We pad the file with the remaining bytes of challenge.bmp in order to ensure the bmp file header data matches up with the size of the file.

with open("challenge.bmp", "rb") as challenge:
    f1 = challenge.read()

    with open("four.wav", "rb") as four:
        f2 = four.read()

        with open("flag.bmp", "wb") as flag:
            offset = 58
            for i in range(offset):
                flag.write(f1[i].to_bytes())
            for i in range(offset, len(f2)):
                flag.write((f1[i - offset] ^ f2[i]).to_bytes())
            for i in range(len(f2), len(f1)):
                flag.write(f1[i].to_bytes())

Viewing the resulting image yields the flag.

The flag image (viewer discretion advised due to creepiness)

The flag

Flag: TUCTF{wh0_gl33p3d_up_my_gl0rps}

The final solve script can be found here.