Over the USB Video Class interface, there’s an XU (Extension Unit) command that kicks the device into “mass storage” mode. This then lets us transfer a staged firmware update to the device’s internal FAT filesystem, which the device then applies to itself on reboot. This route does require user intervention to reboot with a replug, but there’s actually another command channel that exposes arbitrary read/write of files and a reboot command over the USB vendor class. With this, we can fully flash the device without any user interaction. Once the firmware is in the right place, there’s effectively no anti-tamper, just an appended MD5 hash to ensure integrity.
The indicator LED turns out to have a well-structured set of “patterns” in the firmware that dictate color, blink pattern, etc. that are indexed into for various device states. I had Claude write a tool to patch out the table entry for camera activity, fix up the integrity hash, and flash it to the camera. A quick test showed that the green LED that normally illuminates while recording no longer turned on. Horrifying! On this device, the gimbal itself also deflects down when not recording, so it’s not completely stealth, but it still doesn’t feel great.
The LED behavior before and after patching.
GitHub repo - 1.2 hours of Claude churn, 13 prompts from me
My ASUS ROG Swift PG42UQ monitor was actually where I started, because I got annoyed at the pop-up overlay that comes up every once in a while that tells me to run “pixel cleaning”. I have never intentionally run pixel cleaning on this monitor and I never will, I don’t care, and I would like for that overlay to go away forever. Maybe there’s a debug menu or something that can turn it off, or worst case we patch a branch in the firmware?
Claude found that the firmware has effectively no protection whatsoever - there’s a two-slot A/B scheme and a simple checksum, but ultimately we can write whatever we want to the thing. Firmware updates run over an I2C bus bridged over USB.
The pixel cleaning warning turns out to have no native way to disable it, and it’ll always show up after 8 hours of runtime. Oh well. Claude did find the appropriate area to patch to kill the functionality though. I haven’t actually been brave enough to write a modified firmware to the thing yet - it’s a pretty expensive monitor - but I’ll get there at some point.
Another neat thing was exploring the DDC/CI interface. This is the control channel available over the display cable itself, allowing the host to change inputs and other settings. I believe ASUS offers this through their Windows utility, DisplayWidget, but that does little for me on Linux. So, now I have a shell script that can flip through some of the DDC/CI features like the hardware crosshair or zoom overlays, FPS counter, and countdown timer. I might set up some of these on hotkeys in the future for easy access.
GitHub repo - 4.2 hours of Claude churn, 32 prompts from me
At this point, there’s less actual incentive to keep popping these devices and more just morbid curiosity. My microphone, the Shure MV7, connects over USB and obviously has some amount of smarts to it, with on-device digital volume controls and such.
The firmware for this one turned out to be hidden inside the Windows software, MOTIV Mix, so Claude installed that in Wine, found the update server, and pulled it down. I wasn’t on the latest, so there was actually a reasonable incentive here to get this working just to update my microphone from Linux. The firmware turned out to contain both DSP and MCU firmware, and was honestly pretty boring as you might expect. Again, no real security on the firmware flash itself.
However, the update protocol revealed that the entire thing actually runs over a USB HID vendor class protocol
that implements a full plaintext command shell, with 48 different commands. Since it’s HID, we can actually
hit this over WebHID from a webpage in Chrome, so I had Claude build a
web interface for using the shell. There’s all sorts of
interesting settings in here including a dozen DSP knobs, arbitrary memory read/write, LED control, and a 4-tier
user privilege system whose
entire authentication
is a string comparison against the name of the tier you asked for. su sup just works, and the top tier can
disable the touch panel so you can’t mute at the device, and drive the mute LED independently of whether the
microphone is actually muted. It’s the webcam LED trick again, on a microphone. Obviously, be aware that you
could probably break your device if you use that UI and do something stupid with it.
The WebHID shell interface. The DSP knobs on the left are the device’s own settings; the console on the right is the plaintext command shell talking over HID.
GitHub repo - 1.5 hours of Claude churn, 10 prompts from me
The Elgato Cam Link 4K is just an HDMI video capture device, and honestly was just more of the same. The interesting thing for this one was that I let it go fully unattended - I literally kicked off the process before going to sleep and woke up to a teardown and functioning firmware updater. The firmware contains an MCU image and an FPGA bitstream for the actual HDMI handling, so you could potentially do something fun with the FPGA if you went deep enough into the reverse engineering there. There’s no protection on the firmware update path.
I was able to pull out all the EDID information used for negotiating video parameters, so we know exactly what resolutions, refresh rates, color spaces, and chroma subsampling options are offered to devices.
The vendor HID protocol does include tunneled access to the internal I2C bus, which is kinda neat as you can poke the internal HDMI receiver registers.
GitHub repo - 2.4 hours of Claude churn, 10 prompts from me