It is no mystery that, in my spare time, I enjoy a spot of photography, and you can imagine that, with that, comes a significant amount of gadgetry, tweakery, and so on. One of the tools of the hobby, is the flashgun – usually just referred to as “flash”, but for reasons that will come clear in a moment, I will use the “old school” name for them – and indeed last year, stuck at home, I bought myself a Godox TT685C (the C stands for Canon, as each camera manufacturer has its own set of protocols and connectors).
One thing that shouldn’t surprise the techies out there, but would definitely surprise my mother (who had the same hobby back in the days) is that modern camera equipment comes with upgradeable firmware. And indeed, the TT685 series is not only upgradeable, but supposedly cross-flashable (see why I call them flashguns, now?) so that you use a C model as a remote flash for a Sony camera (assuming you have the right remote trigger, and so on). So when I bought the flashgun, I decided to go and check if an update was available — it was, with software for Windows and macOS.
Despite the fact that I do now use Windows 10 daily, I couldn’t get the firmware update to work. Every time it failed to connect to the device, and eventually I realized there was no bug important enough for me to go ahead and find a way to update the firmware, so I set it to the side altogether.
A few weeks ago, mostly out of boredom, I decided to give it another chance. So I downloaded the software again, tried flashing the firmware and… figured out that the problem is that the Godox-provided software uses a custom built binary of libusb-win32, which is not signed, and is not supported on Windows 10. I know that there are ways to force the installation of unsigned drivers, but I thought I would try something difference, and make the problem easier to solve in the long run.
After all, I have been capturing and reversing a lot of USB stuff up to now, why wouldn’t I try to reverse the firmware update of a flashgun? Well, let’s strap in for the ride because it has been highs and lows!
First Item: Windows XP
The unsigned libusb-win32 drivers don’t install on Windows 10, so my usual “start a 30 days trial install” option was not available. My second option of “use the Windows 7 Ultimate license I bought at release” also failed, because the drivers were still not signed. I could have used something like Zadig to force the WinUSB install and see if it worked with the Godox software, but as with any reverse engineering effort, it’s a good idea not to complicate your life with external variables.
So instead, I decided to install Windows XP in a virtual machine. This shouldn’t have been particularly difficult given that back in the days when I was running my own MSP company I actually had a physical copy of Windows XP with a legit license key and everything… except that all of that stuff is archived somewhere in Italy, and not anywhere I can access easily.
But you know, it’s the Internet, and it shouldn’t be that difficult to get a hold of Windows XP, right? The other problem is trying to run Windows XP in a virtual machine with
qemu. Turns out most of the documentation around this is horribly out of date, and not particularly useful. The short version of it is that you need to make sure you install Windows XP SP3, which will work mostly out of the box, unlike the RTM version, that kept getting my mouse input stuck on one of the four corners — I had to use only the keyboard to navigate it!
And if you’re thinking “It’s okay, navigating with the keyboard just to upgrade a flashgun is not impossible”, you would have to install SP3 anyway, because without that you would end up with an error message just telling you «The procedure entry point CheckRemoteDebuggerPresent could not be located in the dynamic link library KERNEL32.dll.» — I’m putting the full message here so that people can find it if they search.
The answer is to use Windows XP SP3, although technically this API was introduced in SP1.
Once you have the right operating system, with a working mouse pointer and an update software that works, you will have to click English, unless you installed explicitly a Chinese version of XP, because otherwise you won’t be able to see a thing in the UI. Not that there’s much to see in the UI, but it’s a good starting point.
Second Item: The Capture
This is probably the easiest part. Since my last blog post on USB captures I have started using Remote Desktop to use my NUC – this is actually something that is making me a bit upset because it does mean I have a 24″ monitor to my left that I barely turn on nowadays, and I’m considering repurposing for some other use – which means I don’t have any USB input device to worry about capturing incorrectly.
So that part is very easy to set up, it’s the usual
sudo tshark -i usbmon0 -F pcapng -w - > foobar.pcapng to get a clean capture — and then connect the flashgun to the virtual machine.
Now right around this moment I should have realized something that would have made me guess a lot less: flashgun shows up with an Atmel Vendor ID. Instead I poked around a little bit the capture itself, and I could find that the first packet with a piece of firmware started with:
0080 0c 94 6b 0c 0c 94 91 0c 0c 94 02 72 0c 94 64 72
0090 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
00a0 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
00b0 0c 94 91 0c 0c 94 91 0c 0c 94 20 74 0c 94 91 0c
00c0 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
00d0 0c 94 eb 73 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
00e0 0c 94 ad 72 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
00f0 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c 0c 94 91 0c
Now if you google this right now, you should be seeing a tweet of mine, though originally I started looking for some of these sequences of hex digits and I found this file, that includes what looks like a
readelf output including:
Disassembly of section .text:
0: 0c 94 6a 10 jmp 0x20d4 ; 0x20d4 <__ctors_end>
4: 0c 94 87 10 jmp 0x210e ; 0x210e <__bad_interrupt>
8: 0c 94 87 10 jmp 0x210e ; 0x210e <__bad_interrupt>
c: 0c 94 6b 18 jmp 0x30d6 ; 0x30d6 <__vector_3>
Code language: HTML, XML (xml)
And hey, those look very similar to the ones I have above! The file said MEGA32, and the filetype was reported as
elf32-avr, so that is a strong clue that whatever the firmware is, it’s using AVR opcodes, which suggests it’s an AVR microcontroller, just like an Arduino! (And my Birch Books – oh the irony of having taken pictures of the ATmega48 based board with what now looks like a flashgun using the same microcontroller family!)
Now as it turns out, since this is clearly an Atmel-based controller, Richard Hughes pointed me at fwupd’s plugin which implements the DFU protocol, which in turn points at the official specs. This provided me with two important positive news: the first is that I most likely won’t have to write a flashing tool completely from nothing — avrdude exists, or maybe we could get it to work with fwupd itself; the second is that writing a tool to extract the firmware from the capture itself is not going to be useful only for the Godox flashguns. It’ll likely work with a capture of any other AVR(32) update.
Third Item: The… Key?
Okay, this is going to be anticlimactic: I have not finished this work yet, so I don’t have any working script that people can use to extract the flashable firmware from what Godox is providing. The reason why this turned out to be quite a bit more work than I originally expected is to be found in the size of the files.
The firmware file that I downloaded from Godox website, once extracted, is 267477 bytes (262KiB). When capturing the full upgrade process, the full capture gets to 323KiB, and since I know that the upgrade process is going through an Erase-Write-Verify cycle, that’s too small for the whole file to be processed. Indeed, my first, dirty script to extract that firmware is suggesting me that the size of the firmware as it is sent to the microcontroller is 93KiB in size (95242 bytes).
I also couldn’t find any substring from the “recovered” firmware in the downloaded file, which suggests me that Godox have “scrambled” their firmware (if I would venture a guess it’s not really cryptographically encrypted, just… well, scrambled.) And while there is English text in the UI of the flashgun itself, there’s no references to any English text in the recovered file, at least not in ASCII.
So this has been confusing me, but unfortunately I haven’t had much time to dedicate to this since before taking my two weeks to visit Lithuania. And since then, between fights with WordPress, Windows and monitor updates, and particularly interesting work problems, I haven’t actually got back to try to complete more of this.
My original plan was to set up a new VM to run Ghidra in, and then do a bit of snooping around to figure out what the original software is doing, and document it. As I said, I doubt this is going down the route of cryptographically encrypting and signing the firmware file — but it would explain why the firmware file is so much bigger than the recovered firmware. It may also include more firmware than it actually sent, for instance a bootloader or other recovery base components that are not generally required.
There is another, more circuitous option that I could be following, and it would be fun, but slightly pointless, and does require investing a tinsy bit more cash on something that, honestly speaking, is totally unnecessary. And that would involve me grabbing a compatible board, flash a well-known firmware onto it while capturing the traffic, and make sure I can extract it back in the right format.
This may sound like a bit of an overreach, just to update a flashgun. The only actually good reason I have to even consider doing that, is that it would be a nice puzzle for my brain to solve, and a new tool in my toolbelt of things I know how to solve. And if you haven’t been following this blog since the beginning of the pandemic and related lockdowns, you’re excused for not having noticed now we moved from my original Birch Books project, which had me play around with microcontrollers and PCB design for an unnecessary LEGO build, to the more recent custom, Home Assistant integrated thermometers.
So expect some more follow ups on this topic, some of which will probably derail in implementing more USB protocols as part of usbmon-tools rather than in the actual details of the Godox flashgun itself.