Reverse Engineering the firmware on a Kenwood DDX9903S

I bought and really like my Kenwood Excelon DDX9903S headunit. I had it in my WRX, and moved it to my LS430. It supports Android Auto and CarPlay, which I find really useful when driving.

However, it has a nag screen every time it boots up. This got me curious as to how it worked, and see if it could be patched to skip this disclaimer. I figured it probably ran Linux on a SoC, as pretty much everything does nowadays. So I grabbed the latest firmware for it (mine was already updated to it), and started probing.

Extract that and you get 3 folders under S_V2_7_0008_0600/:


In each there’s a .nfu file, which I’ve never encountered before. I ran binwalk on each:

[BOOT_V2_7_0008_0600_release]$ binwalk Boot_2.7.0008.0600.nfu
248776 0x3CBC8 Android bootimg, kernel size: 0 bytes, kernel addr: 0x4F525245, ramdisk size: 1226848850 bytes, ramdisk addr: 0x6C61766E, product name: "ERROR: Cannot read kernel image"
1571592 0x17FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
2358024 0x23FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
3209992 0x30FB08 ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)

Surprise, surprise, it runs Android. But, I’m thinking this image is possibly just the firmware updater, and not what I am looking for.

[SOC_V2_7_0008_0600]$ binwalk Soc_V2_7_0008_0600.nfu
5767936 0x580300 Android bootimg, kernel size: 16823168 bytes, kernel addr: 0x80008000, ramdisk size: 0 bytes, ramdisk addr: 0x81000000, product name: ""
5784320 0x584300 Linux kernel ARM boot executable zImage (little-endian)
5800283 0x58815B gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
41943040 0x2800000 Zip archive data, at least v2.0 to extract, compressed size: 14612206, uncompressed size: 14696448, name: 16dnx_2.5s_fbios_bootimg.img
56555332 0x35EF744 Zip archive data, at least v2.0 to extract, compressed size: 16765150, uncompressed size: 16842752, name: TCC893X_recovery.img
73320560 0x45EC870 Zip archive data, at least v2.0 to extract, compressed size: 210950775, uncompressed size: 1825360896, name: automotive-linux-16DDX-image.ext4
284271426 0x10F1A342 Zip archive data, at least v2.0 to extract, compressed size: 87690, uncompressed size: 524288, name: fbios_dual.bin
284359188 0x10F2FA14 Zip archive data, at least v2.0 to extract, compressed size: 168, uncompressed size: 223, name: filelist.txt
284359426 0x10F2FB02 Zip archive data, at least v2.0 to extract, compressed size: 29903609, uncompressed size: 39549952, name: qboot_ddx.bin
314263106 0x12BB4642 Zip archive data, at least v2.0 to extract, compressed size: 33193, uncompressed size: 5242880, name: sbios_dual.bin
314296995 0x12BBCAA3 End of Zip archive, footer length: 22

Here we go. A kernel with a sane size and name string, some recovery images, and what looks like a filesystem image! qboot_ddx.bin must be part of Ubiquitous’ QuickBoot software. It does boot awfully fast, so that explains that. Would be interesting to see full kernel and init output on a stereo headunit. Well, once anyway.

Running binwalk on MAIN_V1_0_2758_0400/MainFw_1.0.2758.0400.mfu didn’t output anything. Not sure what that is.

I tried unzip to extract Soc_V2_7_0008_0600.nfu. Seemed to work, though it complained about a 41MB extra bytes at the beginning. I was really just interested in the filesystem image for the moment:

[SOC_V2_7_0008_0600]$ unzip Soc_V2_7_0008_0600.nfu
Archive: Soc_V2_7_0008_0600.nfu
warning [Soc_V2_7_0008_0600.nfu]: 41943040 extra bytes at beginning or within zipfile
(attempting to process anyway)
inflating: 16dnx_2.5s_fbios_bootimg.img
inflating: TCC893X_recovery.img
inflating: automotive-linux-16DDX-image.ext4
inflating: fbios_dual.bin
inflating: filelist.txt
inflating: qboot_ddx.bin
inflating: sbios_dual.bin

Running binwalk on the .ext4 verifies it is an ext4 filesystem image. I ran binwalk on the others and nothing was notable except the presumed QuickBoot file, qboot_ddx.bin which had images, and what looks like Qt library .qml files for some type of GUI. Also a Pandora image and other images. Hmm…

I decided to mount the ext4 image to take a look.

[SOC_V2_7_0008_0600]$ sudo mount -o loop automotive-linux-16DDX-image.ext4 /mnt/temp
[SOC_V2_7_0008_0600]$ cd /mnt/temp/
[temp]$ ls
bin dev home lost+found Music proc sbin sys temp usr
boot etc IMG_DEC_WORK media nand1 RAMDISK sdcard Syslog Temp var
DB filesave lib mnt opt run share system tmp

Interesting things appear to be in: /opt/jkpf:

bin etc lib rsc script

That appears to be where lots of magic happens. Whenever I’m done disassembling the rest of the car for a particularly annoying remote start installation, I’ll come back to it.

8 thoughts on “Reverse Engineering the firmware on a Kenwood DDX9903S

  1. I know its been a couple of months but I’m also very interested in where you are going with this. I found your post because I started poking around on the firmware on my DNX693s which is very similar…. I’m not a programmer though so I just started hunting for strings to begin with. Then I tried extracting the big one with 7zip but that gave me the opposite. It extracted 42mb and ignored the rest… I ended up with the linux arm kernel config. lol

    On a side note – the DNX693S and if you like the larger screen a couple of other models have Garmin GPS built in. On these models with the Garmin GPS that part is quite easy to get into and mess with. Shoot me an email and I’ll send you info on that end of it. I really would love to get rid of the annoying startup caution. The prior year models did not have that. I think it might be mandated by Apple for their Carplay…

  2. Hello,

    If you develop any decoding processes or scripts, consider adding them to a GitHub repository. I have a theory that a lot of these head units are similar and possibly interchangeable once extracted far enough. Specifically the DDX9903s might be able to run the newer firmware of the DDX9904s. Of course there might be side effects (since the 9904s doesn’t have an HDMI input), but I would imagine if done properly the process could be reverted if the main OS was loadable.

    I was personally investigating this same process myself for my DDX9702S. I wanted to see if I could leverage the firmware of the DDX9704S (with a two year newer firmware). Personally, I want the updated Android App, so some other losses in functionally might be worth it to me.

    Thanks for your post, it saved me some digging.

  3. My file structure looks like this:


    Also take a look at this link!
    Its an open source application to open the automotive-linux-17DDX-image.ext image

    Now I guess I need to install a Linux distort to see what’s different.

  4. @Joe,

    I haven’t looked at it in a while, but I would be sure to post any scripts or progress.

    Two problems remain:
    -Finding the point in the binary where the warning screen is shown
    -Modifying that binary

    I found the Qt QML files where the warning is, with the help of the other commentator. But without a debugger attached it will be hard to determine what part of the binary to modify.

    If I can get access via a JTAG/UART (likely), or run the firmware in a virtual environment (unlikely), I can progress more.

  5. Supposedly the DDX9904s has a modifiable timeout for the warning screen (times out after 10 seconds), if you compared the firmware versions between these two models, maybe it would be enlightening to a way to “fix” the DDX9903s.

    I’m interested in the outcome because I am in the market for a new headunit and I’m considering both the 9903 and the 9904. The 9903 will be the winner if the nag screen can auto-time out since it still has the HDMI input (which I am interested in doing some sort of RasPi based carputer)

    • Haven’t touched it in a while, but as far as I can tell, the unit continues to function fine it just has the nag screen as visual overlay. That is, it will resume Bluetooth audio, or even Android Auto if that was used last there’s just the stupid nag over the top.

      So I’m tempted to just bork the GUI layout for that portion. Either set it offscreen or see if removing it would cause it to just move along to without it (not likely). This being possible because of the QML GUI layout format of flat files.

  6. Nick,
    I was following you along until you got to the part that you didnt know what part of the binary to modify, but then you posted later saying its working fine. Did you figure out what part to modify or did you find a way to put the DDX9904s firmware on your DDX9903s?

    • I think you are referring to my last comment where I posit that the nag screen is just an overlay over whatever actual activity is beneath it, and that I could circumvent having to patch a binary if it loads the GUI from the QML files on the filesystem by changing the width/height, x/y, or transparency, or removing the button, or whatever. I haven’t tried that. I still don’t know how get access to modify the filesystem on the device.

      I haven’t touched it but I do need to open it back up and try and fix my mic. I will see if there’s a JTAG or something exposed then.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.