2.由于本人翻译水平有限,部分内容借助翻译软件,如有错误请指正。3.本文排版格式参考:0x01 关于这辆车 去年夏天,我购买了2021年的现代Loniq SEL(约合人民币27.41万元),这是一款功能丰富的油电混合动力车,具备多种功能,如Android Auto/Apple CarPlay、无线手机充电、天窗和座椅加热。
我非常喜欢这辆车的车载信息娱乐系统(IVI)。正如我之前提到的,它配备了Android Auto,这在这个价格范围内并不常见。车载系统的动画非常流畅,这表明系统的CPU/GPU性能不错,也可能是由于运行的软件并不臃肿。这辆车和我之前得到的其他小玩意一样,我想尝试一些创新的功能。
0x02 目标 这辆车的IVI(车载信息娱乐系统)就像大多数车型一样,类似于一台电脑。我的目标是通过技术手段获取这辆车的root权限,并在IVI上运行自己的软件。当然,要破解这类设备,首先需要了解它的工作原理。我查阅了一些公开的资料,了解到以下内容。
0x03 开发者模式 我喜欢开发者模式和测试应用程序,它们通常会带来很多乐趣,甚至可能会找到一些设置,如连接SSH服务器等。我发现我的车上的IVI可以通过软件更新打开开发者模式。只需快速点击更新按钮的左侧十次,然后点击右侧一次,即可进入开发者模式。
如果屏幕没有变化,请多次尝试,直到进入开发者模式。进入开发者模式前需要输入四位密码,根据官方的开发者文档,我确定密码是2400。进入开发者模式后,我浏览了所有可用的菜单,发现有许多调试参数和隐藏设置。其中一些菜单引起了我的注意。
基于这些功能,我使用USB驱动器收集了一些日志,并尝试使用ADB连接到IVI。我将我的手机和Android Auto连接到IVI的WIFI,扫描WIFI端口,但没有找到可以打开ADB的端口。
日志显示,系统传输了一个名为“daudio2.0v_{Date}-{Time}.tar.gz”的.tar.gz压缩包到USB。这个压缩包包含了许多文件,包括内核日志、Top命令的输出、logcat日志和BlueLink日志。
最有趣的是logcat的日志,基本上记录了在IVI上运行的每个应用程序,并将其写入到日志中。
0x04 破解过程 首先,我知道要进入系统肯定不会像打开开发者设置那么简单,我需要利用一些漏洞来获取访问权限。我认为最佳方法是对IVI上运行的程序进行逆向工程,但要做到这一点,我需要这些程序的文件。最简单的方法就是获取固件更新并解压缩。
固件 我浏览了许多日志,发现我的IVI运行的是现代的D-Audio2V操作系统的第二代,用于各种现代车辆。我发现现代官网上有一些D-Audio2V的源代码可供下载。大部分都是此项目的小补丁,用于修复WIFI功能的错误。D-Audio2V的固件更新可在更新页面的“显示音频软件更新”下找到,但我购买的车型没有更新,所以我下载了其他车型的更新进行分析。
固件以.zip压缩包的形式提供,其中包含另一个.zip压缩包,压缩包名为encsystempackage{version}.zip。查看systempackage.zip,似乎包含IVI中各种模块的固件,如GPS和HD Radio,以及系统镜像文件本身。这个更新对我的分析很有帮助,但当我试图提取系统镜像文件时,发现整个zip压缩包都被加密了。
但我并没有放弃,我在电脑上使用了一些破解压缩包的工具,如John The Ripper和Hashcat,尝试暴力破解压缩包的密码。我尝试了所有八位密码的可能性,我的电脑只能在合理的时间内破解八位密码,但没有成功。我还尝试使用了一些密码表,但也没有成功。
破解 这时,我开始思考是否可以使用其他工具或服务来破解压缩包。当我发现它可以使用已知明文攻击来破解传统的zip加密时,我意识到如果我能找到加密zip文件中至少12个字节的明文文件,就有可能解密整个zip文件。
为了找到匹配的文件,我浏览了加密压缩包的文件列表,在MODEMus路径下的modem_version.txt(37字节)文件中发现了一个很好的攻击目标,因为它的格式是可读的。
起初,我在互联网上搜索此文件,希望能找到匹配项,但遇到了许多无法访问的FTP连接,所以我采用了另一种方法。我希望现代在他们的IVI系统中重用调制解调器模块,这样如果我能从另一个IVI找到一个未加密的调制解调器更新,我就有可能找到一个匹配的modem_version.txt文件。
从现代的更新站,我发现它有一个特殊的IVI更新程序。
我安装了Navigation Updater并下载了2020-2021 Hyundai Ioniq Navigation IVI的最新版本更新包。我打开了更新包中的systempackage.tar,里面有一个调制解调器文件夹,里面是一组看起来熟悉的文件,但modemversion.txt文件的大小错误。
尽管如此,我仍然知道里面可能还有许多其他文件也可能是匹配的,但问题是哪些是匹配的呢?通过比较这两组文件,我发现有几个大小相同,但无法保证内容相同的文件。
幸运的是,zip压缩包给了我希望,我计算了压缩包中所有文件的CRC(循环冗余校验码)。CRC是一种循环冗余校验,zip提取器程序使用它来验证文件是否正确解压缩/加密。相同的文件具有相同的CRC。由于更新文件存储在tar压缩包中而不是zip压缩包,我需要从压缩包中解压缩所需的文件。
我找到了一组匹配的文件:“partition.mbn”。我找到了我想要的明文。我使用我新发现的纯文本加载了bkcrack,但是运行错误,这是为什么呢?
但最终尝试这些错误的密钥并没有打开zip压缩包。我回到Bkcrack Github问题页面,阅读了所有问题,这时我发现需要的“纯文本”不是原始文件本身,而是原始文件的正确压缩版本。我需要弄清楚现代用于压缩此ZIP的原始程序和参数。我使用Windows中的内置ZIP创建器压缩了我的partition.mbn文件,但没有成功。之后,我尝试了7Zip中可以使用的所有参数组合。
我甚至用C#编写了一个程序,用来枚举可能用来创建压缩包的每个组合,但可惜的是没有起到任何效果。我认为现代不太可能使用复杂的Windows zip程序,所以我将目光转向了Linux。我使用Kali附带的zip命令行工具创建了大量具有各种设置的zip文件。
之后,我逐一检查这些文件,在此期间我的bkcrack使用了错误的参数。正确的配置是在zip中指定文件条目,而我指定的是zip本身。在尝试了多种可能的配置之后,bkcrack找到了正确的一种。我使用bkcrack找到的“万能钥匙”制作了一个ZIP压缩包。
最终,我能够轻松地从加密的zip中提取每个文件!bkcrack还允许从找到的主密钥中恢复zip的密码,所以我尝试了,但由于计算能力的限制,它无法找到长达16个字符的任何内容。但基于我现在掌握的信息,我提取了enc_system文件夹中的system.img文件。从已知文件中,我学到了很多东西,比如Python和Perl是如何安装在系统中的,我认为这对未来的逆向工程非常有意义。
最终,我找到了应用程序的存储位置,并开始对其进行逆向工程。幸运的是,由于应用程序在Logcat文件中打印了大量的调试信息,所以许多重要的功能对于逆向工程来说都是易于获取的。
0x05 网络访问 我还发现这套系统安装了RTL8152/8153 USB以太网适配器的驱动程序。我购买了多个基于RTL8153的USB以太网适配器,希望找到一些开放的端口。其中一个适配器有一个内置的USB集线器,与IVI不兼容,但我购买的第二个是直连以太网适配器,可以成功连接到系统。不幸的是,系统只允许我访问CarPlay和Android Auto服务器,并没有其他可用端口。我扫描了指向IVI的192.168.7.110地址,但只打开了相同的CarPlay/Android Auto端口。在此之后,我查看了日志并意识到eth0设备是某种内置的以太网适配器,始终处于离线状态。因此,无论我使用什么USB适配器,它总是显示为eth1。也正是因为这一点,我意识到Wi-Fi密码在生成时被转储到日志中,这意味着我可以使用Wi-Fi进行连接。连接到Wi-Fi后,我获得了与以太网适配器相同的访问权限,最终我的笔记本电脑获得了正确的IPv4地址。由于网络访问的计划失败,我无法通过逆向工程找到任何后门或易于利用的漏洞,因此我决定尝试对固件进行更新。
固件更新 如果我能弄清楚固件更新的所有安全措施,我就可以使用自己的后门修改现有的系统映像,从而获得IVI的完全权限。在分析固件更新的系统映像时,我找不到任何二进制文件。一旦在设置中按下更新按钮,工程模式应用程序和设置应用程序将使IVI进入恢复模式。
在固件更新的encsystem文件夹中,有一个encupdateboot.img文件,我猜测这个镜像包含恢复系统。不幸的是,7Zip无法像system.img文件那样提取图像。该文件没有可读的字符串,被加密了,我猜这就是“enc”前缀的意思¯(ツ)/¯。在查看更新中的其他文件时,我发现所有带有enc前缀的文件都已加密。我再次陷入困境,如果没有加密密钥,我将无法了解系统更新的过程。我决定回顾我已经掌握的所有信息。我继续对所有可能的应用程序进行逆向工程,复查我提取的日志,并分析我之前下载的Mobis网站的开源代码。我没看错吧?
在浏览Mobis网站上的源代码时,我搜索了所有shell脚本文件。在结果中,我找到了一个名为linux_envsetup.sh的shell脚本文件。
这个文件打开了我的思路,原来这是创建系统更新zip文件的脚本。原来我硬盘上一直都有系统更新的zip密码,并且有效的加密方法、密钥和IV也在此脚本中。该脚本还提到了使用RSA签名,但不幸的是,用于此的密钥不在源代码中。
但至少我有加密密钥。为了验证是否有其他人已经走到这一步,我用谷歌搜索了加密密钥。事实证明,该脚本中的加密密钥是NIST文档SP800-38A中列出的第一个AES 128位CBC示例密钥。
现代肯定没有在实际生产环境中使用这个密钥,这只是用于测试,对吧?难道是?不,这不可能……我可以在7Zip中打开文件,但它只有一个损坏的条目。但是,在该文件上成功运行binwalk并显示解密的updateboot.img文件中包含大量内容。
使用-e(提取)参数,我提取了img文件,显示了一个裸露的Linux系统配置文件。在/usr/bin文件夹中,我发现了一个名为updateAgent的二进制文件,看起来很有希望。
因为我已经有了zip密码和加密密钥,所以我决定寻找签名密钥。幸运的是,他们不仅留下了公钥,还留下了私钥。在搜索了RSA等关键字后,我找到了公钥,但没有找到私钥。我再次用谷歌搜索了一部分私钥进行查找。
哦,他们又使用了一个非常普通的密钥。我想知道他们是否根据“RSA Encryption & Decryption Example with OpenSSL in C”进行合规操作…
0x06 等待游戏开始 现在我拥有了这座城堡的钥匙,但仍然没有适用于我这辆汽车的固件更新。我不想冒险破坏我新车的主机,所以我等待更新的到来再开始游戏。