Daniel's Stuff


What I learned after a year of reverse engineering

Sept 5 2022

See the previous post.

In summer 2021, I started a project with a simple goal to hack Fujifilm cameras.
Since then, it's grown uncontrollably. It's become my largest open source project,
and gained some attention.

So, in the past year, what has been done?

Firmware Patches

After gaining custom code execution through the image saving process in summer 2021, I set out to
obtain a RAM dump. My attempts to do it via writing files were unsuccessful, so I decided that
PTP/USB was the way to go.

- My biggest issue was that half of the firmware update file is compressed (40%), and
unusable for firmware injections. The other half is not compressed, and can be modified. The compressed
region contains most of the important code, like PTP.

- I tried to see if I could toggle the LED and get a RAM dump over "morse code" like CHDK,
but my attempts were unsuccessful.

From my basic code execution hack, I was able to brute force search through RAM and find these things:
- "fujifilm.co.jp; ", a string returned by GetDeviceInfo in PTP/USB
- the address of a memcpy() function

Therefore, here was my plan:
plan for memcpy syncing RAM dump
A memcpy() + PTP/USB syncing memory dumper.

It took several days of testing, updating firmware, battery pulling, but eventually:

After getting a 200kb memory dump, I was able to find all the addresses of the PTP functions
and hijack them, eventually leading to a custom firmware allowing me to run any code I want
over PTP/USB:

This was a huge step forward, and it eventually allowed me to get a full 256mb RAM dump.

Difficult Reverse Engineering

After a full RAM dump, I was dissappointed by the lack of debug strings available.
In most embedded devices, you'd expect to see a ton of error messages that would be
printed to UART. For example, you might see a decompilation like this:
iVar1 = FUN_1234567(0x100);
if (iVar1 == 0) {
FUN_45678943("Malloc Error");

After seeing this in a decompiler, you would immediately know that FUN_1234567 is your
malloc() function, because of the error message. In Fujifilm's firmware, there are next
to none of these messages. Still, progress moves on slowly. Very slowly.

Scripting Language

The first thing I noticed when I started reverse engineering was a string, "AUTO_ACT.SCR".
This string appeared in almost all Fujifilm cameras since 2003-ish. I had tried to create the
file on the SD card, but nothing happened when I turned the camera on.

It wasn't until a year after the project started that I started to figure out how this
scripting language worked. In most embedded devices, a hidden script interpreter will often
report error messages like "Syntax Error", or "Invalid token". Fujifilm seems to be the outlier.

At first I started reverse engineering and running the lexer. Took me a few days to figure out that it accepted
Windows style line endings only. Unix style will make it crash and silently segfault.

After that, I was confident it was definitely a lexer for a scripting language. I was then able to
reverse the string tables and jump tables for the interpreter, and slowly piece it together.

My first test was simple, and after calling the run_auto_act function, it crashed the camera:
jump foo

I dug around more, uncovering more code until I was able to create a "count to 10" script:
set x = 1
if x >= 10 goto end
calc x = x + 1
jump lab

Seems pretty basic. What struck me was how similar this was to the scripting language I designed many years ago.
Here is the same program, but in Corescript:
var i = 0
if i = 10:kill1
set i = [add i 1]
goto countLoop

Therefore, this is solid evidence that the scripting language was written by somebody who had never written an interpreter before.

The scripting language definitely has a unique purpose though. I haven't been able to fully figure everything out yet.

Took some guesswork and time to figure out that this script is activated only when byte 0xA2 in EEPROM is set to 2.
See https://github.com/fujihack/fujihack/issues/13 for more on this.

I was able to set the EEPROM byte through my PTP/USB hack and confirmed it ran on startup.


In terms of file writing, here's what the code looks like:
char test[] = "12345678912";
char file[] = "X:\\TEST.BIN";
file[0] = fuji_drive();
void *fp = fuji_fopen(FUJI_FOPEN_HANDLER, file, 1);
fuji_fwrite(FUJI_FWRITE_HANDLER, fp, 10, test);
fuji_fclose(FUJI_FCLOSE_HANDLER, fp, 0, (char*)0);

- Took me several months to figure that out, since I was not expecting such unusual code.
- I also figured out directory reading.
- I figured out how to play beeps and light the LED, which I thought would have gotten me closer to UI code, but It didn't lead me anywhere.

In terms of drawing to the screen, I've found 3 methods:
- fuji_screen_write, which writes UTF8 rows to the screen
- Guessing screen buffer address and writing to it
- Creating rasterizer objects

creating a transparent rst object

As for button presses, I was able to figure out an IO table after reverse engineering some menu code. Seems to include a bunch of IO stuff, including accelerometer and gyroscope.

These findings led to the first ever custom "menu":


Ever since 2010, Fujifilm cameras have been shipped with SQLite. It's probably used to store some camera settings, but I'm not entirely sure. It seems like SQLite doesn't start up when the camera is turned on, but around 10 minutes later.

After reverse engineering the SQLite initialization process, I figured out how to start SQLite and execute some SQL:
image of basic SQL code running


Eventually, I decided to rename the project to "FujiHack", and made a quick logo in GIMP:
fujihack logo
I also created a Wiki packed with information, and wrote a basic web based firmware patcher/unpacker in Javascript.


Unlike some of my other projects, I've decided that this one won't be a money pit for me.
This project will be funded entirely by sponsors, and not myself. This is a way to prevent
myself from obsessing over it too much. (yes, it's an obsession)

I've currently set a goal of $120 USD for a broken Fuji X-A2 to work on, SD card, and a lens.
My current testing camera is a destroyed XF1.
I'm already 40% to my goal because of a generous donation from Picazsoo..
If the goal is not met I'll use the money to pay off domains.


In the past year, working on and off on this project, I've made a lot of progress on this project.
I've also learned a ton about linkers, ARM Assembly, makefiles, operating systems, SQLite, PTP/USB, SoCs...
It's been a great learning experience, and I don't regret getting into it.

Moving on, here are some clear goals I have in mind:
- Stable firmware patch
- Dump ROM, study bootloader
- Figure out the "IMFIDIX" SREC files
- Make some video bit rate tweaks
- Remove 30 minute video timer

After getting Tetris working, I'm planning on taking a break from this project. A tetris port
seems like a good stopping point. I doubt I'll leave forever, but this project just eats away
at my time.

Contact me: