795 root 0:00 [ubifs_bgt1_0] 798 root 0:00 [ubifs_bgt2_0] 808 root 0:00 ./vmf 811 root 0:00 ./pwr_agent -o -v 812 root 0:00 ./sysupdate 825 root 0:00 ./mfid 833 root 0:00 -sh 842 root 0:00 ./vgw 848 root 0:00 [irq/283-atmel_m] 872 root 0:02 ./hmi 874 root 0:03 ./media 876 root 0:00 ./pss 880 root 0:00 ./audio_proc 919 root 0:02 ./bt 921 root 0:00 ./exlap 958 root 0:02 /usr/bin/devicemanager 5 0 /usr/bin 239 393247 1 1 0 0 0 967 root 0:00 [race_daemon] 981 root 0:00 ./diag 983 root 0:00 ./diag_eol 987 root 0:00 ./screenshot 992 root 0:00 [flush-ubifs_1_0] 993 root 0:00 [flush-ubifs_2_0] 998 root 0:00 ./mdnsd -debug 1009 root 0:00 ./connect_mgr 1014 root 0:00 ./carplay_App 1021 root 0:00 ./iap2d 1024 root 0:00 ./carlife_daemon 1026 root 0:00 ./carplayd 1050 root 0:00 {clear-cache.sh} /bin/sh ./clear-cache.sh 1095 root 0:00 [flush-8:0] 1106 root 0:00 sleep 2 1107 root 0:00 ps -ef发现有很多进程,由于名字都是缩写,很难直接猜出这些程序的用途。例如vmf、mfid、vgw、hmi、exlap、diag等等这些都是鬼?他们大多没有-h –help 之类能显示信息的参数可用,想知道他们的用途,估计是要上IDA逆向一下……
经过了几天的研究,我终于知道了部分核心程序的用途。
他这套软件,大部分都是在后台工作的,只有少部分是QT编写的,有界面的。例如hmi和sysupdate。其中hmi体积最大,他就是界面主程序,他包含了所有的图形资源,多国语言字符串。
其他程序基本都没有界面,界面其实都是在hmi中。UI进程和逻辑进程之间使用类似IPC的消息机制,这个机制在这套系统中称为vmf。
那个vmf程序,起到一个消息中转站的作用,vmf可能是Virtual Message Function的缩写?他有Usage信息,显示的是vmffor linux version DOMAIN-SOCKET。
/opt/lib/libvmf_client.so这个就是vmf客户端支持库,很多程序通过调用libvmf_client.so的nw_vmf_send/receive函数来实现跨进程的IPC消息传递,这套消息机制是基于socket。在/tmp/目录有很多127.X.X.X文件,可能与此相关。在文章后面,我将详细分析这套API的原型和消息数据结构。
I have no name!@(none) ~$ ls /tmp 127.0.0.1 127.3.215.1 allgorpccomm1 127.3.104.1 127.3.219.1 carlife 127.3.106.1 127.3.241.1 devmgr_debug.txt 127.3.106.2 127.3.246.1 diag_enter_main 127.3.106.3 127.3.246.2 diag_initialize_OK 127.3.106.4 127.3.40.1 eol_enter_main 127.3.106.5 127.3.40.2 hdd 127.3.106.6 127.3.40.4 icr_device_process.txt 127.3.106.7 127.3.43.1 keyGenerationFile 127.3.106.8 127.3.44.1 race 127.3.106.9 127.3.74.1 race_key_gen_file.txt 127.3.108.1 127.3.74.2 shm_key_gen.txt 127.3.112.1 127.4.0.1 shm_key_index.txt 127.3.112.2 127.4.2.1 vaf_comm_mirrorlinkXSS 127.3.151.1 DevMgrRunning.txt var 127.3.153.1 MFISocket vmf_trace_startup 127.3.153.2 RPCClient1026 127.3.213.1 RPCSocket
pwr_agent,从名字看,显然是电源管理相关,我一直认为就是这个进程,在不断地与MCU通信,喂狗。
我用IDA把他逆了个遍,他确实有这个动作,但是他只是构造了个消息包,包发给了谁并不知道……他其实不光是电源管理,在/opt/launch.sh脚本中可以发现,脚本执行了vmf hal_init pwr_agent sysupdate mfid,就没有了。其实大多数进程,都是由pwr_agent带起来的,这在IDA逆向中能发现。
.rodata:00011183 ALIGN 4 .rodata:00011184 DCD a_Diag 8 ; "" .rodata:00011188 DCD a_VgwDevNull21 ; "./vgw > /dev/null 2>&1 &" .rodata:0001118C DCD a_PssDevNull21 ; "./pss > /dev/null 2>&1 &" .rodata:00011190 DCD a_MediaDevNull2 ; "./media > /dev/null 2>&1 &" .rodata:00011194 DCD a_Diag 8 ; "" .rodata:00011198 DCD a_Audio_procDev ; "./audio_proc > /dev/null 2>&1 &" .rodata:0001119C DCD a_BtDevNull21 ; "./bt > /dev/null 2>&1 &" .rodata:000111A0 DCD a_Diag 8 ; "" .rodata:000111A4 DCD a_HmiDevNull21 ; "./hmi > /dev/null 2>&1 &" .rodata:000111A8 DCD a_WifiDevNull21 ; "./wifi > /dev/null 2>&1 &" .rodata:000111AC DCD aCatProcDeferre ; "cat /proc/deferred_initcalls" .rodata:000111B0 DCD a_Diag_eolDevNu ; "./diag_eol > /dev/null 2>&1 &" .rodata:000111B4 DCD a_Audio_procDev ; "./audio_proc > /dev/null 2>&1 &" .rodata:000111B8 DCD a_DiagDevNull21 ; "./diag > /dev/null 2>&1 &" .rodata:000111BC DCD a_ScreenshotDev ; "./screenshot > /dev/null 2>&1 &" .rodata:000111C0 DCD a_Start_carplay ; " ./start_carplay.sh > /dev/null 2>&1 & " .rodata:000111C4 DCD a_Connect_mgrDe ; "./connect_mgr > /dev/null 2>&1 &" .rodata:000111C8 DCD a_Carlife_daemo ; "./carlife_daemon > /dev/null 2>&1 &" .rodata:000111CC DCD a_ExlapDevNull2 ; "./exlap > /dev/null 2>&1 &" .rodata:000111D0 DCD a_Launch_aa_shD ; "./launch_aa.sh > /dev/null 2>&1 &" .rodata:000111D4 DCD a_Net_windows_s ; "./net_windows.sh > /dev/null 2>&1 &" .rodata:000111D8 DCD a_ClearCache_sh ; "./clear-cache.sh > /dev/null 2>&1 &" .rodata:000111DC DCD a_Start_mdnsd_s ; "./start_mdnsd.sh > /dev/null 2>&1 &"
hal_init,这个进程很简单,只是调用了libHAL.so库中的一些初始化函数就结束了。
int __cdecl main(int argc, const char **argv, const char **envp) { int v3; // r0@1 int v4; // r0@1 int v5; // r0@1 v3=hal_gpio_init(argc, (int)argv, (int)envp); v4=hal_i2c_init(v3); v5=hal_spi_init(v4); hal_uart_init(v5); return 0;}vgw,这是关键进程,我发现把他杀了,系统过一会就重启,所以他是喂狗嫌疑对象。通过逆向,发现他调用了libHAL.so里面的spi_ipcl_read、spi_ipcl_write等函数,通过Search And Replace搜索整个opt目录也证实,只有vgw程序调用了上面的spi_ipcl_read/write接口。这个vgw是什么缩写,我没找到,可能是Vehicle Gateway或者VIP Gateway?感觉这种解释不太靠谱……
/opt/lib目录就是这套程序的库文件了。
I have no name!@(none) ~$ ls /opt/libbt libOSAL.so libAirPlay.so libOSAL.so.1 libAirPlaySupport.so libOSAL.so.1.0 libCarPlayAudio.so libOSAL.so.1.0.0 libCarPlayClient.so libdns_sd.so libCarPlayDevice.so libiap2.so libCarPlayPlatform.so libmfi.so libCarPlayPlatformDevice.so libprotobuf-c.so libCarPlayPlatformMFI.so libprotobuf-c.so.1 libCarPlayPlatformScreen.so libvmf_client.so libCarPlayPlatformSystem.so libvmf_trace.so libHAL.so libximage.so libHAL.so.1 libximage.so.1 libHAL.so.1.0 libximage.so.1.0 libHAL.so.1.0.0 libximage.so.1.0.0 libHAL.so.1.0.0.bak medialibHAL.so.1.0.0.read mirrorlinklibHAL.so.1.0.0.write screenshot
重点关注其中的2个,libOSAL.so和libHAL.so,前者是操作系统支持库,可能是为了方便跨平台开发,将一些系统级API重新封装了一下,例如线程,定时器,互斥锁等。后者是硬件层面的接口,包括uart,spi,gpio,i2c等接口的读写函数封装。其他都是carplay carlifemirrorlink等程序的支持库。
/opt里面很多程序都被strip掉了符号表。在IDA分析时没有符号帮助,很难搞懂一些函数的作用,还好这些程序都调用了日志接口log_optional来打印日志,因此能获知一些函数的真实名字,以及他们的用途。比如下面这个例子:
显然,得知这个函数名字叫pwr_agent_vmf_rcv_handle_round_comm,日志类别是radio_updown。
log_optional的消息打印是受配置文件控制的,这些配置文件以进程名作为区分,位于/opt/config或/pss1/config
例如下面这个pwr_agent的config
I have no name!@(none) ~$ cat /pss1/config/pwr_agent.conf[OPTION]ENABLE=1 <<<<<<<<<<注意这里CATALOG=0FILE=0FUNC=1LINE=0PROCNAME=0TIME=1SEC_DIGIT=2TIME_FMTSTR=%M:%SSAVESD=0[OUTPUT] <<<<<<<<<<注意这个小节start_trap=1OPTION=1INI=1radio_updown=1 <<<<<<<<<<注意这里的名字radio_updownnet_rtc=1VIP=1debug=1health=1DTC=1msg=0sync=0[TEXT]health=39radio_updown=39start_trap=39OPTION=39INI=39DTC=39VIP=39[BACKGROUD]health=49radio_updown=49start_trap=49OPTION=49INI=49DTC=49VIP=49[ATTRIBUTE]health=-1radio_updown=-1start_trap=-1OPTION=-1INI=-1DTC=-1VIP=-1
可见有很多开关,控制了哪些debug消息需要打印,哪些不打印。把一些需要的开关打开,可以方便逆向分析工作。主要开关就是ENABLE=1,OUTPUT是类别控制,控制对应的类别的日志要打印出来。
/opt/ftpdup2.sh这个脚本很有意思,他insmod了asix.ko,然后用ifconfig配置了ip地址,还启动了ftp服务。看来是开发人员为了方便网络传输文件留下来的。这个asix.ko是ASIX的usb转以太网芯片的驱动,很多常见的USB转网口的产品都是用ASIX芯片方案,例如绿联的USB百兆网卡。
I have no name!@(none) ~$ cat /opt/ftpdup2.sh #!/bin/sh #insmod mii.ko #insmod usbnet.ko insmod asix.koifconfig eth0 192.168.5.1 up while [ $? -ne 0 ] do sleep 1sifconfig eth0 192.168.5.1 up done echo network up at 192.168.5.1 cd /bin if [ ! -e /bin/ftpd ] then ln -s busybox ftpd fi if [ ! -e /bin/tcpsvd ] then ln -s busybox tcpsvd fi cd /opttcpsvd -vE 0.0.0.0 21 ftpd -w &
我试着运行了一下,确实把网卡带起来了……
/opt还有一些usbgadget驱动程序,例如g_ether.ko和g_file_storage.ko,由于这台机器前面板的USB接口实际上是CPU的USB_OTG接口,因此我怀疑开发人员用这个驱动,直接把USBOTG虚拟成MassStorage或者网卡,与开发机用USB线连起来就能传文件了,是不是很有意思……
另外我还在/opt/tools发现了两个小程序
I have no name!@(none) ~$ ls -li /opt/tools/total 16 16350 -rwxr-xr-x 1 messageb messageb 7555 Nov 23 2016 vmf_rcv 16349 -rwxr-xr-x 1 messageb messageb 7038 Nov 23 2016 vmf_send
Search AndReplace搜索后发现,这两个程序并没有被任何程序或脚本使用,应该是开发人员在开发或调试时留下的,有意思……这个vmf_send很有用,后面会用到。
0×06升级包分析
不知道网友有什么渠道,拿到了还没有发布的187B的升级包,上传到了网上,可以在百度网盘、或QQ群,找到这些升级包。用升级包给187A升级后,可以比原系统多出许多高级功能。比如苹果CarPlay,百度CarLife,还有什么超级蓝牙,我也没用过,不知道具体是怎么个超级法…
网友放出来的这些升级包,事实上可能都是开发阶段的测试包,有很多bug。有一个固件要求运行内存是512M,在256M的机器上刷了会变砖。另一个固件包支持256M内存,但也是Bug最多的版本。所以很多网友把天宝187A的机器换了内存,还有一些商家提供此类换内存服务,或者售卖已经换好内存的车机。
另外有少数商家有5314版本的升级包,这个版本与上市后的187B系统版本相同,估计算是正式版。但是这个升级包在网上找不到,貌似只掌握在少数以刷机为盈利目的的商家手上,且不外卖,在咸鱼上卖的5314据说都是假包。
接下来研究一下升级包的构造,升级包其实就是一个tar包,没有签名。
例如这个版本的包用7z打开是这样
用户名组名是wangshi,王石?看来制作升级包的系统,有是一个叫wangshi的用户,也许这个也是那位工程师的真实姓名……
看一下根目录的config.txt文件
kernel_update:1bootloader_update:1vip_update:1bt_update:1middleware_update:1[file]:[opt] [file]:[etc] [file]:[usr] [file]:[mirrorlink] [file]:[lib/firmware]
好简单的设计,一目了然啊……
其中的vip_update其实指向的是vipImage.bin,大小1MB,文件末尾有哈希。这正好是瑞萨MCU的Flash大小,那么这个MCU在软件内部就是被叫做VIP咯,VIP是什么呢?Very Important Processor?Vehicle InformationProcessor?
其实如果知道了这个MCU的地址空间布局,完全可以拖进IDA逆向一下,看看里面的具体实现……不过经过后来一番分析,已经知道了VIP的大致作用:CAN总线通讯,身份信息,电源管理等等。身份信息包括零件号,平台(PQ/MQB),序列号,车型(VW/SKODA)等。
现在知道这个MCU的代号其实就是VIP了,而且在分析软件程序的过程中,有很多字符串提到了VIP,那么我在后面文章就以VIP来称呼吧。
bt_update就是蓝牙了,这个机器的蓝牙模块是ALPS的一款模块,网上找不到任何资料。与CPU的通讯是通过UART串口。升级包bt_ac_firm目录里面的文件就是蓝牙控制芯片的固件了。
middleware就是中间件了,也就是opt那些目录,想覆盖哪个目录,写进config.txt就可以了。
升级包还有一个配置文件/opt/stdplus.ini。
[Version] AP_VER=5.4.1.1 CUSTM_PQ=Y307 CUSTM_MQB=Y307 UBOOT_VER=uboot_1.3.2 UIMAGE_VER=uImage_5.0.11 KERNL_VER=3.0.35 BT_VER=C150 VIPAP_VER=5.4.1.1 VIPBL_VER=2.0.2 [Upgrade] PACK_TYPE=VW_PQ_PSS [CODING] BT=0 CODINGS=0
里面有两个字段是必须的,Version小节的AP_VER字段,不能与主机/opt/stdplus.ini一致,否则sysupdate升级时会提示变量冲突。有Upgrade小节的PACK_TYPE,必须与主机/opt/stdplus.ini保持一致,否则不能升级。
其他字段都是可选的,根据升级需要设定即可。
另外升级包里面有一个script目录,里面有两个脚本。
看名字很容易猜得出,一个脚本是更新前执行,一个是更新后执行。
另外还有一个有意思的地方,用7z解压缩那个kernelImage,记事本打开,搜Linuxversion,可以看到编译人员的机器名和用户名,如图。
看,机器名是HP-640,用户名是changchun,难道内核编译人员来自长春?
升级包的结构清楚了,再通过逆向/opt/sysupdate,就对更新过程有了进一步了解。
0×07更新流程分析
通过逆向/opt/sysupdate可以对更新流程有个大致了解,具体的逆向分析流程我不多说了,他这个程序是qt写的,在log_optional这个日志打印函数的帮助下,很容易逆向/跟踪出具体流程。流程大致就是:验证包合法性,设置/sysupdate/flag.ini更新标志,保存包文件名,重启系统,重启后rcS脚本检查flag.ini文件,得知需要更新系统,然后走更新系统流程,启动sysupdate。sysupdate执行run_before_app_update_sh,刷内核(访问/dev/mtd,不是通过dd),替换中间件(hostapp),刷bootloader(调用kobs-ng命令),执行run_after_app_update_sh,刷蓝牙(uart传输),刷VIP(spi传输)。
这个更新流程中的重启,很有意思,不是调用的reboot命令,而是硬重启!
我打开了sysupdate的log日志功能,通过日志输出,可以大致确定他是通过调用SendUpdateStatus(this, 1)来实现重启的,因为打印了这个日志就就没有日志了。
SendUpdateStatus这个函数发出了一个vmf消息,可能被vgw接收了,然后被vgw转手发给了VIP,由VIP触发了重启动作。这个函数的名字是SendUpdateStatus,发送更新状态。估计VIP还关注了更新的状态,能够根据更新状态来产生不同的动作,而这个状态1,就对应着复位CPU。
另外我还发现,一旦这个命令发出去重启了CPU,狗就被关起来了!电源不会每隔60秒被重置一次,这是一个很有意思的发现!
0×08破解通讯协议
现在知道的情况就是,pwr_agent肯定有一个定时器,每隔一段时间喂狗,sysupdate能通知VIP更新状态,当状态为1时,VIP就关掉了狗。
现在就有了两种办法关狗,一个是利用喂狗协议,一个利用升级状态协议。都是通过协议,现在没有协议,怎么办呢,想办法抓到通讯协议就好办了。
与VIP通讯的是vgw进程,IDA看看他里面的函数,有几个spi_ipcl_xxx的函数引起了我的注意,看来是通过调用libHAL.so的spi_ipcl_xxx读写函数实现通讯。前后找了下,没有可以利用的log打印。
再看看libHAL.so的spi_ipcl_write,竟然有日志打印,这太好了……
spi_ipcl_read也调用了这个IPCL_Print_Msg,第三个参数控制了是否输出日志,可惜被传了0,估计是一个宏开关,被编译时指定的。这难不住我,用WinHex把对应的指令字节码改掉。
有两种改法,改IPCL_Print_Msg外部call的传参,也就是0改成1,把MOV R2指令改成 MOV R2,#0就可以了;还可以进入IPCL_Print_Msg内部去改,去掉对第三个参数的判断,也就是将前面的LDMEQFD指令改成NOP。
由于IPCL_Print_Msg并不能打印出这个消息是read还是write,因此我使用前一种改法,改出2个文件,libHAL.so.read和libHAL.soxssw_rite,并备份原机文件为libHAL.so.bak。另外这个printf的fmt是“ %x ”,输出内容会很不友好,我改成了 “x ”。
有了这样3个文件,我就随时可以根据一条shell命令来更换libHAL文件。
恢复libHALmount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.bak libHAL.so.1.0.0 设置IPCL read mount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.read libHAL.so.1.0.0 设置IPCL write mount -o remount rw / && cd /opt/lib && cp libHAL.so.1.0.0.write libHAL.so.1.0.0
由于我替换的是系统关键库,为了避免错误发生,我修改了启动脚本rcS,加入了一个failsafe安全模式功能。改法是这样的
这样修改后,在系统启动时,我有一秒时间来输入y回车来进入安全模式,防止修改/opt/lib库文件导致系统关键进程无法启动、系统崩溃。不过因为没有喂狗,这个安全模式是有时间限制的,复制粘贴上面的指令能迅速帮我还原备份文件。
首先我替换了libHAL.so.write文件,重启后串口终端确实打印了大量通信报文。我发现每隔1秒都有一个8字节的报文送出,且有类似递增序号的字节,没错这一定是在喂狗!
另外我也抓到了sysupdate在调用SendUpdateStatus(xxx,1)关狗并重启时的8字节报文。也在上面的图片中
这些报文都是vgw进程通过spi_ipcl_write向VIP写入的。而这些报文的实际发起者其实并不是vgw。喂狗是pwr_agent发起的。关狗重启是sysupdate发起的。
虽然我可以通过调用libHAL.so的spi_ipcl_write来实现我想要的喂狗和关狗功能了,但是这要编译一个小程序,编译程序需要准备交叉编译环境,还要把这个程序放进去……呀,好麻烦……
为了体现我的高端,我还进一步研究了进程间的通讯,也就是那个vmf消息。比如这个喂狗流程应该是这样的:pwr_agent定时器,构造了一个包,发给了vmf,vmf转给了vgw,vgw通过spi喂狗。
是不是很复杂?没错,厂商确实是这样设计的,这套消息也确实是这样工作的……因为我把vmf杀掉,vgw就收不到消息,不再喂狗了。
首先我想用sysupdate来展开分析工作,我感觉我对这个程序了解的更多一些。我先用IDA定位到SendUpdateStatus(int this, int arg_status)。这个函数第二个参数就是状态值,有1、2、3、4、5、6、7……之类的,在这里关狗重启status值为1。他构造了一个5字节的包,传给了UpdateSendVmfMsg。
构造的包其实就是5个字节, 8F 19 00 01[StatusByte]
UpdateSendVmfMsg(_BYTE*arg_databuf, int arg_datalen)函数又将收到的包调用PackVmfMsg重构了一下,然后把重构的包调用libvmf_client.so!nw_vmf_send_basic发出去了。先看看包是怎么被PackVmfMsg重构的。
char __fastcallPackVmfMsg(_BYTE arg_databuf, unsigned int arg_datalen)
目前只是知道了数据包的布局,但是具体的字段含义还不清楚,例如那个8F是什么,19是什么,00 01有可能是BigEndian的包长?不过通过交叉引用vmf的消息处理接收函数nw_vmf_receive(inthandle, char *buf, int bufsize)不难得出,这个8F其实是groupid,19是eventid。
例如下面是对pwr_agent程序的nw_vmf_receive交叉引用分析出来的log_optional。
从这个log_optional的上下文代码中,我得出了这个vmf的数据包结构:
Offset Type Value 0 byte 定值2 20 byte groupid 21 byte eventid 24 word payload_len 26 byte[] payload
看起来很简单,只要按照这个数据结构把包发出去就可以了。这时就可以利用前面分析文件系统时发现的/opt/tools/vmf_send。
这个文件很小只有7K,拖进IDA,虽然没有usage消息,但是很轻松就逆出了他的用法:
由上面main函数得出vmf_send的用法
Usage: vmf_send [groupid] [eventid][payload_dec_byte0] [payload_dec_byte1] ...
有了这个命令,理论上我只需要知道groupid和eventid,就可以用vmf_send发送vmf消息给相应的进程,控制其产生相应的动作。例如上面分析到的关狗重启vmf消息,我可以调用vmf_send命令:
/opt/tools/vmf_send143 25 1
这样vgw就会收到vmf消息,然后发送8个字节的SPI报文给VIP,触发VIP的关狗重启动作。
有了vmf的相关函数原型以及vmf消息结构,我又逆向了pwr_agent,找到了他的喂狗程序。
然后分析出了喂狗的vmf消息结构
groupid=143eventid=3payload_len=4 payload: 02XX 每秒递增0101 变量VipEnabled的值,由argv参数-v指定
现在终于可以调用tools/vmf_send来发送喂狗消息,我写了一个脚本来实现后台喂狗:
#!/bin/sh while true do for seqnum in $(seq 0 255) do echo $seqnum /opt/tools/vmf_send 143 3 2 $seqnum 1 1 sleep 1 done done
为了验证这个脚本是否有效,我重启进入failsafe模式,顺序启动vmf,启动hal_init,启动vgw,然后再运行这个脚本,过了1分多钟,狗确实被喂的很舒服,没有出来乱咬!哈哈!
现在就可以完善这个failsafe模式了,修改rcS脚本:
read -t 1 -p "Safemode[y/N]:" safemodeecho -e "\n" if [ "$safemode"="y" ];then echo "safemode" /opt/vmf & /opt/hal_init /opt/vgw & /opt/keepalive.sh > /dev/null exit 0 fi
这样系统就有了具有喂狗功能的failsafe模式,是不是很厉害!
0×09 后记
至此,我已经有了一堆PlanB,我可以放心大胆的折腾这台机器了……
接下来的研究就轻松的多了。我又研究了很多有意思的东西,例如:
a)导出187A原厂文件系统b)做了个升级包能把rootfs导出来。但是不包括蓝牙和VIP固件…c)Hack了512M版本的固件,让他在256M内存上完美的跑起来了。d)由于升级后,车机前面板键位错乱,是187B的键位,因此我Hack了hmi修改了键位。e)写了个小程序生成BITMAP并计算哈希,做了个升级包可以替换开机Logo。f)做了个升级包能进入一次failsafe模式,并加载网卡驱动,启动ftp…g)做个原机备份固件。h)有网友提供了编程器固件,从编程器固件提取uboot、kernel、rootfs。i)...
等有时间我准备把上面的abcdefgh,和新研究出来的东西发在这里,作为续集。希望这篇文章,能给同样爱好折腾硬件折腾软件的人带来一些帮助……