Reverse engineering the Creative Katana V2X soundbar to be able to control it from Linux | nns.eeI recently purchased a Creative Sound Blaster Katana V2X soundbar (what a mouthful) to replace my old, cheap Logitech computer speakers. They served me well, but listening to music or watching movies was not the best-sounding experience.After arriving, I set it up and realized it had an USB port which, aside from being able to use it as an audio input, allows the user to configure the speaker: Set the EQ, set the LED lights in different modes, etc. The unfortunate part of this was the fact that it requires the (proprietary) Creative App to use. What's more, it only seems to be available for Windows, which I don't use. While using it in a VM worked, it was hardly convenient.This seemed like the perfect opportunity for something I love: Reverse engineering proprietary applications, devices and protocols and writing tools to communicate with them.<br>Initial recon<br>From just looking at the directory where the Creative App was installed, I could tell this was a .NET app. They usually have a fairly large amount of DLLs Named.Like.This.dll, each corresponding to a C# module. The .exe.config file is also a giveaway.My suspicion was confirmed when I loaded the exe and corresponding DLLs up in dnSpy, a .NET disassembler. Unfortunately, I also realized that a large portion of the modules were obfuscated and fairly hard to read.Deciding to leave this aside for now, I turned my focus on the USB comms themselves. Having no clue how the speaker even communicated with the app, I started recording all USB traffic with Wireshark and USBPcap. I did this before even opening the app, as I wanted to capture as much communication as possible.The first thing the application told me when it found my soundbar was that it needed a firmware upgrade. I let it upgrade, and inspected the USBPcap output. The actual firmware update payload was easily recognizable, as the packets were much larger than any surrounding packets, and fortunately it seemed to be a plaintext firmware blob!I did write a script to extract the entire firmware file from the packet capture - more on this later.Reverse engineering the protocol<br>In order to have captures of everything the application lets the user do, I methodologically started going through each of the options, clicking things, changing things, and creating a separate capture file for each operation. This took me around an entire day and resulted in ~100 different captures.This allowed me to analyze the packets, write down notes on what does what, and after a while I had a pretty clear picture of how the protocol works.The communication happens over the CDC ACM serial interface, and the speaker actually exposes itself on Linux over /dev/ttyACM*.All of the proprietary commands use a simple framing:5A [cmd] [len] [payload...]The 0x5A is always static and is likely just the command start marker. cmd is the command opcode for whatever you're trying to do. len, as the name suggests, is the number of payload bytes following and payload is the payload (or subcommand) itself.Responses are fairly similar, usually with a byte indicating it's a response.I won't go over all of the different commands, but as an example, here's an example command for requesting the current FW version (as a subcommand) and the corresponding response:Host -> Device: 5a 09 01 02<br>Device -> Host: 5a 09 12 02 10 "1.3.230619.1820\0"Authentication<br>Before you're even able to send commands, you're supposed to pass a challenge-response authentication to put the device in a mode where it accepts commands. I'm not really sure why this was done - maybe Creative really doesn't want people using third party applications to control the devices they own? In any case, I reverse engineered this as well.From the first capture, I could see that one of the first comms between the device and the host were as follows:Host -> Device: "whoareyou.MyApp8\r\n"<br>Device -> Host: "whoareyou" 1e 04 83 32 [32 random bytes] "\r\n"<br>Host -> Device: "unlock" [64 random bytes] "\r\n"<br>Device -> Host: "unlock_OK\r\n"<br>Host -> Device: "SW_MODE1\r\n"<br>[... binary comms ...]This seemed to be some sort of challenge-response, and the 64 random bytes made me initially consider a simple (HMAC-)SHA512. However, searching through the assemblies in dnSpy for anything calling SHA512 (or any hashing algos, for that matter) didn't come up with anything that seemed relevant. In fact, even searching simply for the string whoareyou came up with nothing. Taking a step back, I ran a grep whoareyou on all of the files, and found out that only the binary DLL CTCDC.dll matched.Loading this up in Ghidra and going through the X-refs, I ended up on the function that seemed to be responsible for the initial communication with the device, as evident by checking for responses such as Unknown command and NotYet.Analyzing this function, I was able to deduce that it wasn't using SHA at all, but rather some weird...