Building own update-files with libjcisecurity-patch (TEST)
Hello all!
The libjcisecurity-Patch
(for Version EU_70.00.100A and EU_70.00.335C, that are identical files)
The intention of this howto is to get back the sovereignty over our CMU to bypass the Mazda lock out.
IMPORTANT: This is (for now) theoretically! I have not tested it! But I will... because I also want the newest firmware.
There can also be errors in this howto! Nobody is perfect, and I'm not Nobody. ;-)
There are some advantages of this method:
1.) We are able to build clean and correct running firmware with our extensions and under our control.
2.) We can always use the regular update method for recovery with most important modifications directly included.
3.) If something went wrong we can do a small "cmu_recovery".
4.) We can use "ID7_recovery_(v1/2) further - but we mustn't because we are always able to install our own "*_update"-files
Too much and hard work has been done by so many users - Thanks for that! - to expand the functionality of the CMU. This shouldn't be in vain.
Base of this howto is the work from user
"Duck" (Andrew) who passed away in 2014. He has done the most important part!
- mazda3revolution.com/forums/site-news-updates/222618-infotainment-project-91.html#post2283538
R.I.P Duck - God save him!
Plz read this (from user Duck):
- mazda3revolution.com/forums/2014-2018-mazda-3-skyactiv-audio-electronics/57714-infotainment-project-30.html#post936866
- mazda3revolution.com/forums/2014-2018-mazda-3-skyactiv-audio-electronics/57714-infotainment-project-33.html#post942642
- mazda3revolution.com/forums/2014-2018-mazda-3-skyactiv-audio-electronics/57714-infotainment-project-34.html#post944242
- mazda3revolution.com/forums/2014-2018-mazda-3-skyactiv-audio-electronics/57714-infotainment-project-44.html
(I'm not able to put links in)
So we have to build your own firmware update file whenever a new firmware update is released.
I work with GNU/Linux and prefer Debian. You can use any other GNU/Linux distribution too (Ubuntu,...).
Required Debian-Packages: binutils-arm-none-eabi, radare2, bsdiff, hexcurse, whois
You can install them in a "root"-terminal with the command:
# apt-get install binutils-arm-none-eabi radare2 bsdiff hexcurse whois
NOTICE: You have to expand the "*_update.up" and the jci root file system in the known way.
Now, let's take a look at "/jci/lib/libjcisecurity.so".
With this information you can patch every "libjcisecurity.so" yourself.
# /usr/bin/arm-none-eabi-objdump -d libjcisecurity.so | less
In the pager "less", search for "RSA_verify" -> press "/" and type: RSA_verify (press "n" for next match).
Code:
390c: e51b0014 ldr r0, [fp, #-20] ; 0xffffffec
3910: ebfff7d8 bl 1878 <EVP_PKEY_get1_RSA@plt>
3914: e1a01000 mov r1, r0
3918: e24b20cc sub r2, fp, #204 ; 0xcc
391c: e24b3f73 sub r3, fp, #460 ; 0x1cc
3920: e3a00c01 mov r0, #256 ; 0x100
3924: e58d0000 str r0, [sp]
3928: e58d1004 str r1, [sp, #4]
392c: e3a00e2a mov r0, #672 ; 0x2a0
3930: e1a01002 mov r1, r2
3934: e3a02020 mov r2, #32
3938: ebfff75c bl 16b0 <RSA_verify@plt>
393c: e1a03000 mov r3, r0
3940: e50b301c str r3, [fp, #-28] ; 0xffffffe4
3944: e51b301c ldr r3, [fp, #-28] ; 0xffffffe4
3948: e3530001 cmp r3, #1
394c: 1a000012 bne 399c <verifySignature+0x838>
Take a look at "394c:" -> Hint: (i386) MSB:'1200001a' <-> (arm) LSB:'1a000012' is "bne 0x50" (bne == branch if not equal)
Code:
# rasm2 -a arm -b 32 -d '12 00 00 1A'
-> bne 0x50
# rasm2 -a arm -b 32 -d '00 00 A0 E1'
-> mov r0, r0
So if we modify "libjcisecurity" at address '394c:' with a new instruction (arm) '0000A0E1' (mov r0, r0 == No operation) <-- means: 'DO NOTHING',
we should be able to build our own "*_update.up"-files without the SHA256 signature and install them with the regular update routine.
Hint: We can't sign the update files correctly (and the md5 comment at the beginning of the zip file ist a "Red Herring")
because we haven't the (private) signing certificate from Mazda. It's not in the wild.
So I make a copy of "libjcisecurity.so" to "libjcisecurity-patched.so" and modified the code wiht a HEX-editor
like the genius user "Duck" (God save him!) did:
Code:
390c: e51b0014 ldr r0, [fp, #-20] ; 0xffffffec
3910: ebfff7d8 bl 1878 <EVP_PKEY_get1_RSA@plt>
3914: e1a01000 mov r1, r0
3918: e24b20cc sub r2, fp, #204 ; 0xcc
391c: e24b3f73 sub r3, fp, #460 ; 0x1cc
3920: e3a00c01 mov r0, #256 ; 0x100
3924: e58d0000 str r0, [sp]
3928: e58d1004 str r1, [sp, #4]
392c: e3a00e2a mov r0, #672 ; 0x2a0
3930: e1a01002 mov r1, r2
3934: e3a02020 mov r2, #32
3938: ebfff75c bl 16b0 <RSA_verify@plt>
393c: e1a03000 mov r3, r0
3940: e50b301c str r3, [fp, #-28] ; 0xffffffe4
3944: e51b301c ldr r3, [fp, #-28] ; 0xffffffe4
3948: e3530001 cmp r3, #1
394c: e1a00000 nop ; (mov r0, r0)
I modified "libjcisecurity-patched.so" with the command
Code:
# hexcurse libjcisecurity-patched.so
You can use any other hex-editor.
After modification I used "bsdiff" to create a usable patchfile "patch-libjcisecurity.bsdiff" (for everyone, you can download it here).
(Usage: # bsdiff oldfile newfile patchfile)
Code:
# bsdiff libjcisecurity.so libjcisecurity-patched.so patch-libjcisecurity.bsdiff
You can use the command
(Usage: bspatch oldfile newfile patchfile)
Code:
# bspatch libjcisecurity.so libjcisecurity-patched.so patch-libjcisecurity.bsdiff
to get an modified "libjcisecurity-patched.so" (This is important!)
You can check the correct modification with the command
Code:
# radiff2 libjcisecurity-patched.so libjcisecurity.so
0x0000394c 00 => 12 0x0000394c
0x0000394e a0e1 => 001a 0x0000394e
replace original "libjcisecurity.so" with our patched version "libjcisecurity-patched.so" for future updates
- /jci/lib/libjcisecurity.so -> rootfs1upd:e0000000001.dat
(Must also be replaced per "scp" on current running CMU if Version is EU_70.00.100A! to test it!)
REMBER: The "libjcisecurity.so" is the same in "EU_70.00.100A" and "EU_70.00.335C".
I don't know if it is the same version like in "NA_70.00.100A" and "NA_70.00.335C" - but i guess it is.
replace with an account (jci) with known password (jci)
- /etc/passwd -> /config-mfg/passwd -> passwdupdate:e0000000002.dat
Original:
Code:
cmu:$5$phNsaxamJ/6XE4D7$7N55BFA26mj2HtlpxF9cIXzT01GxfgZcWg9UU9vlYo4:0:0:root:/root:/bin/sh
service:x:1001:1001:Service User:/root:/bin/false
hmi:x:1002:1002:HMI User:/root:/bin/false
browser:x:1003:1003:Browser User:/root:/bin/false
Modified:
Code:
jci:$5$QJv0sVo/wdUU87LY$j8xWDbdB9VZKya2MYbUL9bxiQ1iHV3SBPhFXvHvkTl5:0:0:root:/root:/bin/sh
cmu:$5$phNsaxamJ/6XE4D7$7N55BFA26mj2HtlpxF9cIXzT01GxfgZcWg9UU9vlYo4:0:0:root:/root:/bin/sh
service:x:1001:1001:Service User:/root:/bin/false
hmi:x:1002:1002:HMI User:/root:/bin/false
browser:x:1003:1003:Browser User:/root:/bin/false
Hint: You can create own passwords with the command (from package: "whois")
Code:
# mkpasswd -m sha256crypt
type (blind) "jci", Enter, voilá: "$5$hP59Q4/tGMEGY9Xy$vhv9L81k3SfOFD2QUgQSa2ZdTFovRIpFqQ3CQpLC3BB"
replace (add an own ssh key) for passwordless login
- /config-mfg/authorized_keys -> passwdupdate:e0000000001.dat
use the command
Code:
# ssh-keygen -t rsa -f id_rsa
to get a new key pair, two files in actual directory "id_rsa" (secret key) and "is_rsa.pub" (public key, normally in the users home directory "~/.ssh/").
Take a look at "id_rsa.pub":
Code:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8H9x3ngKviOIyXIUsy35taOmdV5XiE2rsK6Xv5sBVo47utNs4wgRrxvE+2enELuGe/mLR9RwCMwYkOx
Fcj0ojeM9eWXQIXe1VrJlLkwMsddKdwN10TE5z8TWYdTxwYfNZo6vKQZRXkq2+1BiVDEyM1fAEHg+3TsCoqzIoVu0kuKJi/nOaXL30zNrIjESYZqE0Tol
FeIqmMQJSWkoGpPcKffipenukCiY7L+o6nRtoih+5f1FIP5SgweJzA1bNGM4rFM6kZHYjtaynR4jYwZaRN4kC77p5fXwQyA7ROA7KujrWIiNqV8DxMCmUNc8S70/
1dl+PA6Wun1KSPyX9GQp user@host
Append own public key to "authorized_keys" (Attention: ">>" not ">"!)
Code:
# cat id_rsa.pub >> authorized_keys
Difference (Example!):
Original:
Code:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0FHSD2wtMIG566piYM/v6zEKddd44+KaTz7Nmb4ffbVXcQB09jgND0zNZDgY+CemB3ashofP4O6XS
ZizyI5x730ShYLL0xiGGe/qU0PLjwuHbsWWGsU4NdRHtaAL0xhdXkLg82TnOowbzHsz2gyzeXdVmfrc5GZs5MJcDIuWdocmUyZW3VjEhS8Kv73Os
MjbstjPnTkRzOZm+7HOp3nKMBI49xym3aXGb39RW+B5+EcjQUVS1jC92L4sfuatu4EsWpQ/jQI4k6hasA6x43hhO2mjt2nB5o4h0OcEv
/cNdeDvp3ZvIqVwyNGjQGvrwp7iwECfqrbTwlxrPce1m5mB
Modified:
Code:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf0FHSD2wtMIG566piYM/v6zEKddd44+KaTz7Nmb4ffbVXcQB09jgND0zNZDgY+CemB3ashofP
4O6XSZizyI5x730ShYLL0xiGGe/qU0PLjwuHbsWWGsU4NdRHtaAL0xhdXkLg82TnOowbzHsz2gyzeXdVmfrc5GZs5MJcDIuWdocmUyZW3VjEhS
8Kv73OsMjbstjPnTkRzOZm+7HOp3nKMBI49xym3aXGb39RW+B5+EcjQUVS1jC92L4sfuatu4EsWpQ/jQI4k6hasA6x43hhO2mjt2nB5o4h0OcEv/cNdeDvp3ZvIqVwyNGjQGvrwp7iwECfqrbTwlxrPce1m5mB
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8H9x3ngKviOIyXIUsy35taOmdV5XiE2rsK6Xv5sBVo47utNs4wgRrxvE+2enELuGe/mLR9Rw
CMwYkOx/Fcj0ojeM9eWXQIXe1VrJlLkwMsddKdwN10TE5z8TWYdTxwYfNZo6vKQZRXkq2+1BiVDEyM1fAEHg+3TsCoqzIoVu0kuKJi
/nOaXL30zNrIjESYZqE0TolFeIqmMQJSWkoGpPcKffipenukCiY7L+o6nRtoih+5f1FIP5SgweJzA1bNGM4rFM6kZHYjtaynR4jYwZaRN4k
C77p5fXwQyA7ROA7KujrWIiNqV8DxMCmUNc8S70/1dl+PA6Wun1KSPyX9GQp user@host
In the future, if the "authorized_key" is replaced in the CMU you can use the command
Code:
# ssh -i id_rsa jci@CMU-IP-ADDRESS
to connect to CMU with pulic key authentication and without password.
replace by a corrected version with enhanced PATH
- /etc/profile -> rootfs1upd:e0000000001.dat
to repair this errors: GStreamer should find it's video libraries.
Code:
00:00:44.914 Std[] Error (: ) (gst-plugin-scanner:3019): GStreamer-WARNING **:
Failed to load plugin '/usr/lib/gstreamer-0.10/libmfw_gst_mpeg2dec.so': lib_mpeg2_dec_arm11_elinux.so.2.2.0: cannot open shared object file:
No such file or directory
00:00:44.977 Std[] Error (: ) (gst-plugin-scanner:3019): GStreamer-WARNING **:
Failed to load plugin '/usr/lib/gstreamer-0.10/libmfw_gst_h264dec.so': lib_H264_dec_arm11_elinux.so.2.6.1: cannot open shared object file:
No such file or directory
00:00:46.393 Std[] Error (: ) (gst-plugin-scanner:3019): GStreamer-WARNING **:
Failed to load plugin '/usr/lib/gstreamer-0.10/libmfw_gst_mpeg4aspdec.so': lib_MPEG4ASP_dec_arm11_elinux.so.1.2.1: cannot open shared object file:
No such file or directory
Difference:
Code:
> export LD_LIBRARY_PATH="/jci/lib:${OPERA_ROOT}/3rdpartylibs/freetype:/usr/lib/imx-mm/audio-codec:/usr/lib/imx-mm/parser:/usr/lib/imx-mm/video-codec:/data_persist/dev/lib:${LD_LIBRARY_PATH}"
---
< export LD_LIBRARY_PATH="/jci/lib:${OPERA_ROOT}/3rdpartylibs/freetype:/usr/lib/imx-mm/audio-codec:/usr/lib/imx-mm/parser:/data_persist/dev/lib:${LD_LIBRARY_PATH}"
re-enable password logins (and ssh port from 36000 back to 22)
- /etc/ssh/sshd_config -> rootfs1upd:e0000000001.dat
Difference:
Code:
> Port 22
...
< #ListenAddress 0.0.0.0
---
> ListenAddress 0.0.0.0
...
< PasswordAuthentication no
---
> PasswordAuthentication yes
...
< ChallengeResponseAuthentication no
---
> ChallengeResponseAuthentication yes
enable ssh access (from everywhere) in firewall
- /jci/scripts/jci-fw.sh -> rootfs1upd:e0000000001.dat
Difference:
Code:
< $IPTABLES -A INPUT -p tcp -i wlan0 --dport 36000 -m state --state NEW,ESTABLISHED -j DROP
< $IPTABLES -A INPUT -p tcp --dport 36000 -m state --state NEW,ESTABLISHED -j ACCEPT
---
> #$IPTABLES -A INPUT -p tcp -i wlan0 --dport 36000 -m state --state NEW,ESTABLISHED -j DROP
> $IPTABLES -A INPUT -p tcp -m multiport --destination-ports 22,24000,36000 -m state --state NEW,ESTABLISHED -j ACCEPT
...
< #$IPTABLES -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
---
> $IPTABLES -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
...
< $IPTABLES -A INPUT -p icmp --icmp-type echo-request -j DROP
---
> #$IPTABLES -A INPUT -p icmp -icmp-type echo-request -j DROP
re-enable "autorun" hook
- /jci/scripts/start_normal_mode.sh -> rootfs1upd:e0000000001.dat
Difference (Line 49):
Code:
> if [ -e /data_persist/dev/bin/autorun ] ; then
> /data_persist/dev/bin/autorun &
> fi
update md5 hashes in
- rootfs1upd/e0000000002.dat
with the new hashes for the new files, therefore, calculate the md5sum of every modified file with the command
OR (possibly faster)
modify the update script
- rootfs1upd/e0000000003.dat
and comment out this lines to disable the md5 file check completely
Code:
# # Verifying rootfs
# echo "==>Verifying rootfs using checksum\"..."
# if [ ! -f ${_checksum_file} ] ; then
# echo -e "\n==> ERROR: Failed to find \"${_checksum_file}\" file !!!\n"
# exit 1
# fi
# md5sum -c ${_checksum_file}
# _res=$?
# if [ "${_res}" -ne 0 ] ; then
# echo -e "\n==> ERROR: checksum failed returned '${_res}' !!!\n"
# exit 1
# fi
Explanation of "main_instructions.ini"
Code:
[Settings]
PackageID = 1555469319 <-- this is "# date -u --date='@1555469319' --> "Mi 17. Apr 02:48:39 UTC 2019"
CompressionType = GZIP
TotalStepsCount = 1121 <-- summary of the last column of the 21 counts below
[Instructions]
Count = 21
1 = Execute, "cleandatapersist", "execute.ini", 4 <-- steps of "Count" in "execute.ini"
2 = Execute, "bootstrap", "execute.ini", 7
3 = ImageUpdate, "ibc2", "binary.ini", 2
4 = ImageUpdate, "fail-safe", "binary.ini", 2
5 = Execute, "checksumoption", "execute.ini", 5
6 = ImageUpdate, "ibc1", "binary.ini", 3
7 = Execute, "linux1", "execute.ini", 6
8 = Execute, "getoldflavor", "execute.ini", 4
9 = Execute, "rootfs1upd", "execute.ini", 8
10 = Execute, "getnewflavor", "execute.ini", 4
11 = Execute, "passwdupdate", "execute.ini", 12
12 = Execute, "gps", "execute.ini", 6
13 = FileUpdate, "resources", "files.ini", 1020
14 = Execute, "usersettingsbackup", "execute.ini", 4
15 = Execute, "usersettingsrestore", "execute.ini", 4
16 = Execute, "usersettingscleanup", "execute.ini", 4
17 = Execute, "preloaddata", "execute.ini", 8
18 = Execute, "compactwnn", "execute.ini", 5
19 = Execute, "neutralizeid7", "execute.ini", 4 <-- this should be removed!
20 = Execute, "systemupdateid", "execute.ini", 2
21 = Execute, "vip", "execute.ini", 7
[Instructions_Ext] <-- failsafe instructions, when something went wrong
Count = 25
1 = Execute, "cleandatapersist", "execute.ini", 4
2 = Execute, "bootstrap", "execute.ini", 7
3 = BreakPoint, "failsafeos", "Start", 0
4 = ImageUpdate, "ibc2", "binary.ini", 2
5 = ImageUpdate, "fail-safe", "binary.ini", 2
6 = Execute, "checksumoption", "execute.ini", 5
7 = BreakPoint, "failsafeos", "End", 0
8 = BreakPoint, "reinstall", "Start", 0
9 = ImageUpdate, "ibc1", "binary.ini", 3
10 = Execute, "linux1", "execute.ini", 6
11 = Execute, "getoldflavor", "execute.ini", 4
12 = Execute, "rootfs1upd", "execute.ini", 8
13 = Execute, "getnewflavor", "execute.ini", 4
14 = Execute, "passwdupdate", "execute.ini", 12
15 = Execute, "gps", "execute.ini", 6
16 = FileUpdate, "resources", "files.ini", 1020
17 = Execute, "usersettingsbackup", "execute.ini", 4
18 = Execute, "usersettingsrestore", "execute.ini", 4
19 = Execute, "usersettingscleanup", "execute.ini", 4
20 = Execute, "preloaddata", "execute.ini", 8
21 = Execute, "compactwnn", "execute.ini", 5
22 = Execute, "neutralizeid7", "execute.ini", 4 <-- this should be removed!
23 = Execute, "systemupdateid", "execute.ini", 2
24 = Execute, "vip", "execute.ini", 7
25 = BreakPoint, "reinstall", "End", 0
[DataStorage]
Count = 4
UPType = "Reinstall"
SubUPType = "Mass"
ReTransmit = "1"
NewPackage = "1"
- modify "main_instructions.ini"
- remove "neutralizeid7" completely from extracted file system and renumber the counts
Code:
[Settings]
PackageID = 1561825344 <-- Needs no change! But: Want a new timestamp? Use:" # date -u +%s --> "1562003976"
CompressionType = GZIP
TotalStepsCount = 1117 <-- = 1121 - 4!
[Instructions]
Count = 20 <-- = 21 - 1!
1 = Execute, "cleandatapersist", "execute.ini", 4
2 = Execute, "bootstrap", "execute.ini", 7
3 = ImageUpdate, "ibc2", "binary.ini", 2
4 = ImageUpdate, "fail-safe", "binary.ini", 2
5 = Execute, "checksumoption", "execute.ini", 5
6 = ImageUpdate, "ibc1", "binary.ini", 3
7 = Execute, "linux1", "execute.ini", 6
8 = Execute, "getoldflavor", "execute.ini", 4
9 = Execute, "rootfs1upd", "execute.ini", 8
10 = Execute, "getnewflavor", "execute.ini", 4
11 = Execute, "passwdupdate", "execute.ini", 12
12 = Execute, "gps", "execute.ini", 6
13 = FileUpdate, "resources", "files.ini", 1020
14 = Execute, "usersettingsbackup", "execute.ini", 4
15 = Execute, "usersettingsrestore", "execute.ini", 4
16 = Execute, "usersettingscleanup", "execute.ini", 4
17 = Execute, "preloaddata", "execute.ini", 8
18 = Execute, "compactwnn", "execute.ini", 5
19 = Execute, "systemupdateid", "execute.ini", 2 <-- "neutralizeid7" deleted
20 = Execute, "vip", "execute.ini", 7
^^ renumber!
[Instructions_Ext]
Count = 24 <-- =24 - 1!
1 = Execute, "cleandatapersist", "execute.ini", 4
2 = Execute, "bootstrap", "execute.ini", 7
3 = BreakPoint, "failsafeos", "Start", 0
4 = ImageUpdate, "ibc2", "binary.ini", 2
5 = ImageUpdate, "fail-safe", "binary.ini", 2
6 = Execute, "checksumoption", "execute.ini", 5
7 = BreakPoint, "failsafeos", "End", 0
8 = BreakPoint, "reinstall", "Start", 0
9 = ImageUpdate, "ibc1", "binary.ini", 3
10 = Execute, "linux1", "execute.ini", 6
11 = Execute, "getoldflavor", "execute.ini", 4
12 = Execute, "rootfs1upd", "execute.ini", 8
13 = Execute, "getnewflavor", "execute.ini", 4
14 = Execute, "passwdupdate", "execute.ini", 12
15 = Execute, "gps", "execute.ini", 6
16 = FileUpdate, "resources", "files.ini", 1020
17 = Execute, "usersettingsbackup", "execute.ini", 4
18 = Execute, "usersettingsrestore", "execute.ini", 4
19 = Execute, "usersettingscleanup", "execute.ini", 4
20 = Execute, "preloaddata", "execute.ini", 8
21 = Execute, "compactwnn", "execute.ini", 5
22 = Execute, "systemupdateid", "execute.ini", 2 <-- "neutralizeid7" deleted
23 = Execute, "vip", "execute.ini", 7
24 = BreakPoint, "reinstall", "End", 0
^^ renumber!
[DataStorage]
Count = 4
UPType = "Reinstall"
SubUPType = "Mass"
ReTransmit = "1"
NewPackage = "1"
And at the end - here's a little script to take a mostly complete backup of the CMU without NAV-SD or USB-Stick(s) in a fast way.
"backup_jci.sh"
Code:
#!/bin/bash
#
# mostly complete backup of cmu
#
DIR=Backups
DATUM=$(date +%Y%m%d_%H:%M:%S)
BCKUP=$DIR/backup_$DATUM
mkdir -p $BCKUP
cd $BCKUP
EXCLUDE="--exclude='./bootchart' --exclude='./dev' --exclude='./proc' --exclude='./sys' --exclude='./lib' \
--exclude='./media' --exclude='./tmp/media' --exclude=./mnt/sd* --exclude=./tmp/mnt/sd* --exclude=./tmp/mnt/resources"
ssh jci@CMU-IP-ADDRESS "cd / && tar $EXCLUDE -cf - ." | tar xvf -
I don't known when I have time to complete the work and build an own self-created "*_update-file" for download. Be patient please... it can take one or two months... or more. Sorry, not enough time.