<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>blog.nns.ee</title>
  <link>https://aggr.aymericbeaumet.com/sources/blog.nns.ee/</link>
  <description>Browse aymeric&#39;s, an independent, searchable archive of readable snapshots from followed feeds, preserved in Git with aggr.</description>
  <language>en</language>
  <atom:link href="https://aggr.aymericbeaumet.com/sources/blog.nns.ee/rss.xml" rel="self" type="application/rss+xml"/>
  <lastBuildDate>Mon, 2 Nov 2026 16:30:58 +0000</lastBuildDate>
  <generator>aggr</generator>
  <item>
    <title>Jailbreaking my car&#39;s navigation system just so I can change the time</title>
    <link>https://aggr.aymericbeaumet.com/items/lobste-rs/2026-11-02-jailbreaking-my-car-s-navigation-system-just-so-i-can/</link>
    <guid isPermaLink="false">urn:aggr:item:9ca3b1a4c3a5e7408e7d652d8465b1c2c39b1717</guid>
    <atom:link href="https://blog.nns.ee/2026/11/02/renault-hack/" rel="via" type="text/html"/>
    <pubDate>Mon, 2 Nov 2026 16:30:58 +0000</pubDate>
    <dc:creator>blog.nns.ee by xx</dc:creator>
    <description>Comments</description>
    <content:encoded>&lt;p&gt;The car that I drive is a 2014 Renault Latitude. It&#39;s not a fancy car by any means and is starting to show its age, but it gets me from point A to point B and does everything else reasonably well so I&#39;ve never really had any reason to complain.&lt;/p&gt;
&lt;p&gt;When I bought the car, the previous owner asked me whether I wanted a &amp;quot;navigation map SD card&amp;quot; with it.&lt;/p&gt;
&lt;p&gt;They mentioned that the car apparently needs this SD card just to change the time on the clock, but I didn&#39;t really find that believable - not that they were lying to me, but perhaps they couldn&#39;t figure out how to enter the correct settings menu. After all, videos of similar head units online showed the menu with the clock settings option right there.&lt;/p&gt;
&lt;p&gt;Since the maps on the SD card were apparently very out of date and didn&#39;t function properly, I decided I didn&#39;t need it and the previous owner tossed it.&lt;/p&gt;
&lt;p&gt;I didn&#39;t really miss it. The dashboard display did show a large &amp;quot;No maps found!&amp;quot; message taking up the majority of the display, but it didn&#39;t bother me too much.&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/img/2026-11-02-renault-hack/ui.jpg&quot;&gt;&lt;picture class=&quot;article-picture article-picture-fallback&quot; style=&quot;--image-ratio:16 / 9&quot;&gt;&lt;img src=&quot;https://blog.nns.ee/img/2026-11-02-renault-hack/ui.jpg&quot; alt=&quot;Image of the head unit display showing &amp;quot;No maps found!&amp;quot; in Estonian&quot; loading=&quot;eager&quot; decoding=&quot;async&quot; fetchpriority=&quot;high&quot; referrerpolicy=&quot;no-referrer&quot; class=&quot;progressive-image&quot;&gt;&lt;/picture&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Like most other European countries, Estonia uses daylight saving time, and we recently switched from summer time (UTC+3) to &amp;quot;winter time&amp;quot; (UTC+2), which meant that the time displayed on the dashboard was out of sync by an hour. I dived into the settings menu, hoping to easily find the &amp;quot;Set time&amp;quot; option in there.&lt;/p&gt;
&lt;p&gt;That never happened.&lt;/p&gt;
&lt;p&gt;The menu where the &amp;quot;Set time&amp;quot; option should&#39;ve been simply didn&#39;t have that option. I compared the menus with the ones in online videos, and the option was simply missing. There were two &amp;quot;Settings&amp;quot; buttons on the dash, and one of them worked but only let me change various Bluetooth and phonebook settings, with no time &amp;amp; date settings in sight. The second Settings button did not work whatsoever, instead showing a &amp;quot;No maps detected!&amp;quot; pop up message every time I pressed it.&lt;/p&gt;
&lt;p&gt;I must&#39;ve spent an hour going through various menus, pressing various buttons or button combinations hoping to land in the correct menu, searching the web for information on this particular unit simply because I refused to believe that there was no option to change the time and &lt;em&gt;I clearly must&#39;ve been missing something obvious&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#just-re-it&quot;&gt;Just RE it&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Still in denial, I decided to fetch the firmware and dig into it, hoping to find some indication on how to open the correct settings menu.&lt;/p&gt;
&lt;p&gt;Luckily, I wasn&#39;t the first to embark on this journey and someone had already done some reverse engineering work on this particular unit (&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/andronedev/carminat-tomtom-live-re/blob/main/README.md&quot;&gt;https://github.com/andronedev/carminat-tomtom-live-re/blob/main/README.md&lt;/a&gt;). While it was in French and seemingly heavily LLM-assisted, it did point me to the correct URLs for fetching the update files themselves.&lt;/p&gt;
&lt;p&gt;When extracted, the update files included a &lt;code&gt;ttsystem&lt;/code&gt; file which turned out to be an ext3 filesystem containing the device&#39;s root filesystem, which was pretty much exactly what I was looking for. The unit itself (TomTom Carminat LIVE, codename &lt;code&gt;beaumont&lt;/code&gt;) is built around a Samsung S5P6440 SoC running TomTom&#39;s custom OS based on Linux 2.6.28.10.&lt;/p&gt;
&lt;p&gt;After reverse engineering it for a while, I came to the conclusion that the previous owner was completely correct. There was absolutely no way to enter the correct settings menu without a navigation SD card inserted. In fact, the menu definition &lt;em&gt;pointing&lt;/em&gt; to the Settings applet was read from the SD card itself, and without one inserted containing the right menu definition, the unit didn&#39;t even know &lt;em&gt;how&lt;/em&gt; to enter the Settings applet.&lt;/p&gt;
&lt;p&gt;This decision by TomTom (or Renault) is still baffling to me.&lt;/p&gt;
&lt;p&gt;What made things worse was that this needed to be a &lt;em&gt;legitimate&lt;/em&gt; SD card. The system had DRM checks which rejected SD cards without the correct CID (a unique ID burned into the card) and files with signatures based on that specific CID, so I couldn&#39;t even copy the files to a blank SD card. I&#39;m guessing the DRM was in place to prevent people from pirating maps.&lt;/p&gt;
&lt;p&gt;I don&#39;t want maps. I have a phone that I use for navigation. I just want to change the damn time.&lt;/p&gt;
&lt;p&gt;I checked online and found some third parties selling the card I presumably needed, but with shipping to Estonia, it would&#39;ve cost me roughly 60 EUR, which I really didn&#39;t feel like paying.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fine&lt;/em&gt;. I&#39;ll just root it and do it myself.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#easy-wins&quot;&gt;Easy wins?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I couldn&#39;t find anyone online who&#39;d jailbroken one of these before. I found some old forum threads with long-expired image links that had some pretty generic information about the unit itself and the general consensus was that it was difficult to root.&lt;/p&gt;
&lt;p&gt;I didn&#39;t expect a Linux 2.6 system from 2011 to be incredibly hard to hack, so I naively went in looking for some easy wins.&lt;/p&gt;
&lt;p&gt;My first idea was to modify the ext3 update image itself. It seemed like I could easily just mount the filesystem, modify some init scripts to do what I want, and copy it to a blank SD card for the unit to pick up my modified image and flash it.&lt;/p&gt;
&lt;p&gt;While the system showed confirmation prompts to install vanilla, unmodified &lt;code&gt;ttsystem&lt;/code&gt; images with no problem, I could never get it to update to my modified image, and I had no idea why. I checked the updater logic present in the update file itself and couldn&#39;t see any reason why my image would be rejected.&lt;/p&gt;
&lt;p&gt;It was at this point that I set up an emulator with QEMU, a custom kernel also based on the same 2.6 version, some patches and a very simple CAN emulator for the system to actually boot - albeit reluctantly, wanting to reboot every 3 seconds, which I just patched out by ignoring reboot syscalls.&lt;/p&gt;
&lt;p&gt;I used this to test installing the modified update image in there. I then realized that I don&#39;t actually &lt;em&gt;have&lt;/em&gt; the &lt;code&gt;recovery&lt;/code&gt; partition that the device boots into to perform the update, and came to the conclusion that there must be some sort of verification layer there that I&#39;m missing.&lt;/p&gt;
&lt;p&gt;Taking a closer look at the &lt;code&gt;ttsystem&lt;/code&gt; image also pretty much confirmed this, as it had a bunch of high-entropy data appended to it, followed by some zero blocks, followed by 40 high-entropy bytes. I assumed this was a signature of some sort (40 bytes could be DSA with SHA-1), but with no access to the actual binary doing the verification, I couldn&#39;t really figure out how to attack this or if I even could.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#back-to-the-drawing-board&quot;&gt;Back to the drawing board&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&#39;d been reluctant to put the effort into building the emulator, but it turned out to be extremely useful for testing out various attacks and getting an overview of how the system behaved.&lt;/p&gt;
&lt;p&gt;For example, I found out that &lt;em&gt;most&lt;/em&gt; partitions were mounted either read-only, &lt;code&gt;noexec&lt;/code&gt; or both. Mounts from a live system:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plain&quot;&gt;&lt;span class=&quot;code-snippet&quot;&gt;rootfs on / type rootfs (rw)
none on /sys type sysfs (rw,nosuid,noexec)
none on /proc type proc (rw,nosuid,noexec)
/dev/mmcblk0p5 on /content type ext3 (rw,nosuid,nodev,noexec,noatime,nodiratime,errors=continue,data=ordered)
/dev/loop0 on / type ext2 (ro,noatime,nodiratime,errors=continue)
none on /dev type tmpfs (rw,nosuid,noexec,size=1024k)
none on /tmp type tmpfs (rw,nosuid,noexec,size=2048k)
none on /var type tmpfs (rw,nosuid,noexec,size=5120k)
none on /dev/pts type devpts (rw,nosuid,noexec,gid=5,mode=620)
none on /var/log type tmpfs (rw,nosuid,noexec,size=1024k)
/dev/mmcblk0p3 on /mnt/flash type ext3 (rw,sync,nosuid,nodev,noexec,errors=continue,data=ordered)
/dev/mmcblk1p1 on /media/sdcard type vfat (rw,sync,nosuid,nodev,noexec,noatime,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)
/dev/loop1 on /media/loopback type ext3 (rw,nosuid,nodev,noexec,noatime,nodiratime,errors=continue,commit=3600,data=journal)
none on /mnt/movi type unionfs (rw,nosuid,nodev,noexec,noatime,nodiratime,dirs=/media/loopback=rw:/media/sdcard=ro)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notably, the base FAT32 filesystem of the SD card was mounted to &lt;code&gt;/media/sdcard&lt;/code&gt;, and the system mounted a unionfs on top of it in &lt;code&gt;/mnt/movi&lt;/code&gt;, which had a writable layer pointing to an ext3 filesystem which lived as a file on the external SD. I&#39;m not 100% sure what the point of this setup was (maybe so they can use &lt;code&gt;data=journal&lt;/code&gt;, which survives power loss better?), but nevertheless all of these mounts were &lt;code&gt;noexec&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This seemed like surprisingly strong security for something from 2011.&lt;/p&gt;
&lt;p&gt;Something else that the emulator helped me with was identifying all of the files that the system tried to read from the external SD card. One of these files was &lt;code&gt;master.script&lt;/code&gt;, a script in a custom language for automating certain UI navigation actions. This was loaded every boot and I hoped this would allow me to somehow open the correct settings menu for setting the time.&lt;/p&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/img/2026-11-02-renault-hack/execute-script.jpg&quot;&gt;&lt;picture class=&quot;article-picture article-picture-fallback&quot; style=&quot;--image-ratio:16 / 9&quot;&gt;&lt;img src=&quot;https://blog.nns.ee/img/2026-11-02-renault-hack/execute-script.jpg&quot; alt=&quot;Image of the head unit display prompting the user to execute master.script&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;low&quot; referrerpolicy=&quot;no-referrer&quot; class=&quot;progressive-image&quot;&gt;&lt;/picture&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I reversed &lt;code&gt;ttn&lt;/code&gt;, the binary responsible for parsing this script, documenting its functionality as I went, but unfortunately I didn&#39;t find any way to open the menu I needed.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#more-wild-goose-chases&quot;&gt;More wild goose chases&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I still thought &lt;code&gt;master.script&lt;/code&gt; was what I should be putting my effort into, since it had a lot of functionality that could be a potential attack vector.&lt;/p&gt;
&lt;p&gt;As usual, I checked for any &lt;code&gt;system&lt;/code&gt; or &lt;code&gt;popen&lt;/code&gt; calls that would allow me to perform command injection. Unfortunately, I didn&#39;t find any constructed with user input.&lt;/p&gt;
&lt;p&gt;I thought I had hit the jackpot when, while reversing the parser, I came across a &lt;code&gt;SHEX&lt;/code&gt;/&lt;code&gt;SHELLEXECUTE&lt;/code&gt; command. It passed an arbitrary argument to &lt;code&gt;launchserver&lt;/code&gt;, which launched whatever command line was provided with &lt;code&gt;execve&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This had two obstacles. The first one was that there was still no way to get it to execute a &lt;em&gt;custom&lt;/em&gt; executable directly, as the SD card was mounted &lt;code&gt;noexec&lt;/code&gt; which prevents executables and scripts on it from running. However, this could be bypassed by not executing the script directly, but rather executing something like &lt;code&gt;/bin/sh /media/sdcard/payload.sh&lt;/code&gt;, which would go through &lt;code&gt;/bin/sh&lt;/code&gt; on the rootfs, which was &lt;em&gt;not&lt;/em&gt; mounted &lt;code&gt;noexec&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second hurdle was bigger, however. It turned out that while &lt;code&gt;launchserver&lt;/code&gt; would happily launch anything, &lt;code&gt;SHEX&lt;/code&gt; accepts only a single whitespace-delimited token. This means that I could only control &lt;em&gt;which&lt;/em&gt; binary was executed, but not pass it any arguments. Combined with the previous obstacle, this then also seemed like a dead end because I could only run scripts or binaries that were already on the rootfs. I did look through most of them, but nothing seemed very helpful.&lt;/p&gt;
&lt;p&gt;Defeated, I started looking at file writes. Maybe if I could write files to places I shouldn&#39;t be able to, that would give me some sort of leverage.&lt;/p&gt;
&lt;p&gt;Sure enough, I discovered the &lt;code&gt;LOG&lt;/code&gt; command, which let me truncate a file (defined with &lt;code&gt;#define LOGFILE log.txt&lt;/code&gt;) and write a single line to a file of my choosing. This one actually allowed spaces and regular ASCII characters, but only bytes 0x20 to 0x7E, meaning writing binary data is out of the question. As &lt;code&gt;ttn&lt;/code&gt; runs as root, any writes would also be written as root.&lt;/p&gt;
&lt;p&gt;It also had a classic path traversal vulnerability. Defining &lt;code&gt;LOGFILE&lt;/code&gt; with &lt;code&gt;../&lt;/code&gt; in it allowed me to write outside the intended logfile directory, theoretically allowing me to write printable ASCII to anywhere on the system.&lt;/p&gt;
&lt;p&gt;However, I once again ran into a wall with how the mount points were set up. I couldn&#39;t overwrite anything on the rootfs since it was mounted read-only, and everything else was mounted &lt;code&gt;noexec&lt;/code&gt; and would never be executed anyways. I also looked into whether there were any useful config files I could overwrite, but most files were a custom binary format that I couldn&#39;t write with &lt;code&gt;LOG&lt;/code&gt; or were otherwise unhelpful. This also looked like a dead end.&lt;/p&gt;
&lt;p&gt;Among other things, &lt;code&gt;master.script&lt;/code&gt; allowed displaying images on the screen (GIFs/BMPs). I spent some time setting up a fuzzing environment using Unicorn to see if I could hit any image decoder bugs causing memory corruption, and while I did get quite a few OOB reads, I didn&#39;t find any useful writes.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#borrowing-a-trick-from-kernel-exploits&quot;&gt;Borrowing a trick from kernel exploits&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I had been researching, reverse engineering and trying to come up with different strategies to run arbitrary code for a while. Much to my frustration, none of my strategies ended up working, and I took a step back to look at the bigger picture and figure out if I can make any of the puzzle pieces that I already have fit together.&lt;/p&gt;
&lt;p&gt;Among other things, I knew I could:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Execute arbitrary binaries, but with no arguments and only the ones already on the rootfs&lt;/li&gt;
&lt;li&gt;Write ASCII to paths of my own choosing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is when I had a brainwave and was reminded of a trick that kernel exploits often use: Instead of trying to get the userland to execute our script, why don&#39;t I get the &lt;em&gt;kernel&lt;/em&gt; to execute our script instead?&lt;/p&gt;
&lt;p&gt;Often, Linux kernel exploits, when being able to write arbitrary memory, overwrite the &lt;code&gt;core_pattern&lt;/code&gt; string. Normally, this dictates how coredumps are stored when a process crashes, but it &lt;em&gt;also&lt;/em&gt; accepts special syntax for piping these coredumps to a process instead (&lt;code&gt;|/bin/my-coredump-handler&lt;/code&gt;). When a crash occurs, the kernel spawns the process specified in &lt;code&gt;core_pattern&lt;/code&gt; and pipes the data in there.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;core_pattern&lt;/code&gt; also supports cmdline arguments for the spawned process. I got lucky here, since support for this landed in 2.6.24 whereas the unit&#39;s kernel was 2.6.28.&lt;/p&gt;
&lt;p&gt;Importantly, you&#39;re also able to set &lt;code&gt;core_pattern&lt;/code&gt; from &lt;em&gt;userland&lt;/em&gt; by writing the pattern to &lt;code&gt;/proc/sys/kernel/core_pattern&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I can easily use this to point &lt;code&gt;LOGFILE&lt;/code&gt; to &lt;code&gt;../../proc/sys/kernel/core_pattern&lt;/code&gt; and &lt;code&gt;LOG&lt;/code&gt; the string &lt;code&gt;|/bin/sh /media/sdcard/payload.sh&lt;/code&gt;. This would run the rootfs &lt;code&gt;/bin/sh&lt;/code&gt; and execute our script with it as root.&lt;/p&gt;
&lt;p&gt;Being able to execute arbitrary binaries also turned out to be useful even without arguments, since I needed to somehow get a program to crash, triggering a coredump. Using a DoS vuln to crash the script parser or the main UI itself wouldn&#39;t work very well, because this would immediately trigger a reboot of the whole system, killing my script.&lt;/p&gt;
&lt;p&gt;I used my emulator setup to execute pretty much every single binary on the system, and found that &lt;code&gt;/bin/dbus-monitor&lt;/code&gt; raised a SIGABRT if it couldn&#39;t connect to the system bus (which the unit didn&#39;t run), triggering a coredump. This was perfect.&lt;/p&gt;
&lt;h3&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://blog.nns.ee/2026/11/02/renault-hack/#putting-it-together&quot;&gt;Putting it together&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My final &lt;code&gt;master.script&lt;/code&gt; turned out to be quite simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C&quot;&gt;&lt;span class=&quot;syntax-source syntax-c&quot;&gt;&lt;span class=&quot;syntax-meta syntax-preprocessor syntax-macro syntax-c&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-control syntax-import syntax-define syntax-c&quot;&gt;#define&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-preprocessor syntax-macro syntax-c&quot;&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-constant syntax-preprocessor syntax-c&quot;&gt;LOGFILE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-preprocessor syntax-macro syntax-c&quot;&gt; &lt;span class=&quot;syntax-invalid syntax-illegal syntax-syntax syntax-c&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;syntax-invalid syntax-illegal syntax-syntax syntax-c&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;proc&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;sys&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;kernel&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;core_pattern&lt;/span&gt;
LOG &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;bin&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;sh &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;media&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;sdcard&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;payload&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-other syntax-member syntax-c&quot;&gt;sh&lt;/span&gt;
SHEX &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;bin&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;/&lt;/span&gt;dbus&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;-&lt;/span&gt;monitor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I initially confirmed success by simply calling &lt;code&gt;reboot&lt;/code&gt; in the &lt;code&gt;payload.sh&lt;/code&gt; script. I was very pleasantly surprised when booting the unit with the SD card inserted and pressing &amp;quot;Yes&amp;quot; at the &amp;quot;&lt;em&gt;Execute master.script?&lt;/em&gt;&amp;quot; prompt, the unit rebooted, confirming that I had code execution.&lt;/p&gt;
&lt;p&gt;The first thing I did was use this to create a full backup of the internal eMMC using &lt;code&gt;dd&lt;/code&gt;. With a more complete dump of the system, I pretty quickly figured out that the date &amp;amp; time settings that I&#39;m interested in are in &lt;code&gt;/mnt/flash/settings.dat&lt;/code&gt;, which is a custom binary format. After some more reverse engineering, I figured out the exact offset in the file which held the currently set timezone, and wrote a script to patch it to be UTC+2.&lt;/p&gt;
&lt;p&gt;That is how I was finally able to fix my car&#39;s timezone.&lt;/p&gt;
</content:encoded>
    <category>news</category>
    <category>linux</category>
    <category>reversing</category>
    <category>security</category>
  </item>
</channel>
</rss>
