“ 免责声明:本文涉及到的所有技术仅用来学习交流,严禁用于非法用途,未经授权请勿非法渗透。否则产生的一切后果自行承担!一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉,谢谢!”
我如何黑了我的车
这篇博文的灵感来自于我前一段时间在HN上看到的另一篇文章“我是如何黑掉我的车的”。在赞扬了这辆现代IONIQ汽车的信息娱乐系统后,作者最终破解了它。
我的2023年达契亚Sandero也有一个不错的信息娱乐系统
在我拿到车之前,我就四处寻找,看看车辆是否可以被入侵。我发现将带有 autorun.sh
脚本的 USB 驱动器插入到车辆,自动执行该脚本。网络上的各种论坛都使用这种方法来更改ivi主题和导航地图。我的目标是运行一些自定义软件。
信息娱乐系统
该系统是雷诺(达契亚是其子公司)的MediaNav Evolution,由LG(FCC ID:BEJLAN5900WR)制造。这是一个Linux的盒子。
多年来,这个系统已经有了各种各样的迭代,旧的设备使用WinCE。
该软件的导航部分由一家名为NNG(iGO?)的公司开发。显然,他们为许多其他设备提供导航软件。
MediaNav Evolution(非正式名称为MediaNav 4)
The autorun.sh
通过在各种论坛上浏览,我知道3个特殊的文件,当放在USB驱动器上时会触发一些调试功能:
-
autorun_bavn/autorun.sh
:以root身份运行的脚本 -
logfiles_bavn
:收集各种系统日志和文件的目录 -
usb_logging
:系统持续转储dlt文件的目录(专有日志系统)
日志文件包含了无线接入点(AP)的 Wi-Fi 密码。这个密码可以在用户界面上重置,但从来不会显示出来。知道这个密码允许其他设备连接到它(例如,个人电脑)。在使用无线 Android Auto 时,它会自动连接,我认为它是通过蓝牙进行初始化的。
我最感兴趣的是 autorun.sh 文件… 但它没有起作用,我无法让脚本运行。
固件
到了这一步,我决定开始检查固件,看看哪里出了问题,以及是否有其他方法可以进入。我的设备附带的是6.0.9.9版本。
我想要一个最新的更新文件,但官方网站并不提供直接下载。
它要求安装一个桌面应用程序,“Toolbox”,我最终还是安装了。这个应用程序可以用来购买地图更新,或者免费下载固件/操作系统更新。
这个过程开始于收集一些关于系统/车辆的信息到USB驱动器。在将其连接到电脑后,“Toolbox”软件便会检测到一个新的更新,并将新的更新文件放到驱动器上。
我没有进行更新,我只是想要那个文件,它是6.0.10.2版本:
makefile
>: file upgrade.lgu
upgrade.lgu: POSIX tar archive (GNU)
我还有一个较旧的更新文件,版本是6.0.9.7,我在某个随机论坛上找到的。
有时候,即使是grep也可以是一个很好的分析工具。仅仅通过在新旧固件的内容上运行grep -RF autorun.sh,我就可以看到新版本中没有匹配项。
是时候加载Ghidra,看看发生了什么事…
6.0.9.7版本具有autorun.sh功能,但该功能在6.0.10.2版本上不存在
比较这两个文件,很明显他们已经移除了 autorun.sh 这个后门。
这个名为 miscmanager 的文件也负责其他USB调试功能,这些功能仍然存在。
核心操作系统似乎来自 GENIVI/COVESA(GitHub: GENIVI/COVESA https://github.com/COVESA)。我对这些系统一点也不熟悉。他们有相当多的开源项目,未来我可能会去探索。
我反编译了其他二进制文件,试图寻找一些其他有趣的东西。找到了很多D-Bus相关的东西,当我能运行自己的软件时,这些将有助于获取车辆信息。但我的目标是首先获得root权限。
一种方法是制作一个带有后门的新更新文件,这将需要逆向工程整个升级程序,而且正如预期的那样,更新文件有一些签名,这些签名需要匹配。
直接获取root权限将是首选的方式。
Android Update App
我在官方网站上注意到,他们正在推广一种使用安卓手机应用更新地图的新方法。
Google Play上的描述承诺“消除Sneaker Network”,这是我从未听说过的一个表达,指的是不需要使用USB驱动器。
当然,我没有安装它,这样做没有意义。我只是在Google上搜索了id com.nng.pbmu.dacia,找到了许多提供.apk文件下载的网站之一。
这些年我反编译过一些安卓应用,我偏好的方式是将.apk作为.zip解包(这就是它的本质),获取.dex字节码文件,通过dex2jar将它们转换成一些.jar文件,然后用老牌的JD-GUI打开。最近我发现了jadx,它提供了一个更好的反编译应用程序的体验。
令我惊讶的是,这个应用相当复杂,似乎包括某种本地绑定,而且大部分功能是用一种类似于JavaScript的专有.xs脚本实现的。这些脚本可以在应用的资源中找到。
Android API被导出为模块,用于.xs脚本
多个本机库和.xs脚本
看起来liblib_nng_sdk.so
库负责运行这些脚本,但我没有进一步研究它。我的目标只是专注于使用什么样的协议来更新设备上的地图。
我在第一个文件里找到的。
NFTP!
是标准FTP吗?不,这不是标准的FTP或任何其他已知的协议,我可以找到。这是一个新的二进制协议,用于传输文件,在这些.xs
脚本上实现。
然后,该应用使用Android Open Accessory(AOA)作为协议的传输层。AOA对我来说是全新的,但经过一些阅读,很明显,它只是一种建立配件与Android设备USB通话标准的方式。
名称令人困惑,“配件”实际上是USB主机(在这种情况下,头单元)和Android设备是USB外设。
The Other Side
我手头的新更新文件版本是6.0.10.2,根据网站上的信息,这是新更新应用程序正常工作所需的版本。这自然意味着该文件中有一些特定的服务/代码来处理车载单元端的更新。
经过一番挖掘,我找到了它。这是另一组.xs脚本,它们在一个原生解释器上运行。还有一个原生二进制文件,aoa2sock,它通过提供传输协议的管道来桥接USB(AOA)和.xs脚本之间的差距。
很明显,这个手机更新功能是后来加上的,这些二进制文件/脚本不是标准升级文件系统的一部分,它们是在系统更新时从一个.ipk包文件(yellowtool.ipk)中单独安装的。它们内部使用的名称是YellowTool / YellowBox。而且这是整个系统中唯一用这些.xs脚本编写的部分,其他的都是原生二进制文件。
大部分系统使用原生二进制文件和Qt应用程序
移动的更新应用程序功能使用.xs脚本
由于这些脚本是纯文本格式的,尽管编码风格糟糕,但理解这些协议的功能以及它提供的访问类型相对比较容易。
构建后门
到了这一步,仅仅通过阅读代码,我已经相当确定有可能在 /navi 目录下写入任意文件,如果我修改一些文件,这将给我提供完全的访问权限。
我需要做的就是创建一个假的安卓更新应用,并使用AOA模式进行连接。
在Linux内核有一种叫做“gadget模式”的东西,其中运行Linux的设备可以作为一个USB外围设备(而不是主机)。
我能让一个树莓派作为安卓设备在AOA模式下工作吗?
Gadget模式可以通过使用configfs从用户空间配置(只需写入特定的/sys/kernel/config/ 文件),这种方式不需要编写任何内核代码,但它仅限于内核中已经实现的特定“功能”(例如串行端口、大容量存储、以太网适配器等)。
不出所料,这正是谷歌的工程师们实现AOA的方式,他们在内核中添加了一个新的“accessory”功能。他们甚至试图推动它进入上游,但无疾而终,目前它不是Linux内核的一部分。我认为它可能永远不会是,它可能太特殊了,而且这是一个有点奇怪的协议。
在了解更多关于AOA的信息后,很明显它涉及到一种握手过程,其中配件请求安卓设备进入AOA模式,之后,设备就像一个串行端口一样工作(一个“原始”的数据管道),接下来的工作就取决于开发者(这是一个简化的说法,还有其他模式,更多信息请阅读相关文档)。
所以或许我可以使用串行gadget功能来伪造一个已经在accessory模式下的安卓设备,而不用实现握手过程。
测试设置
该系统的结构如下:
安卓端:更新应用程序 / “nftp” (.xs 脚本) <=> AOA <=> USB
车载单元端:USB (主机) <=> aoa2sock <=> “nftp” (.xs 脚本) <=> [读写系统文件]
为了测试,我使用了两个树莓派。
因为车载单元和树莓派都是基于ARM架构的,我能够运行固件中的aoa2sock二进制文件和.xs解释器,这模拟了车载单元并充当了USB主机。
另一个树莓派充当了USB外设(使用On-The-Go,OTG端口),当使用gadget模式正确配置时,它表现得像一个处于AOA模式的安卓设备。
树莓派 Zero 2 W 可以通过 OTG 端口供电,并且将作为安卓设备。
在尝试了多种 gadget 配置之后,我从 aoa2sock 看到了一些有希望的调试信息,这是从固件中提取的二进制文件,它在车载单元端创建了一个在 USB AOA 和奇怪的 “nftp” 协议(.xs 脚本)之间的管道。
但它没有工作……
“未找到 AOA 端点”:我的伪造车载单元没有识别到我的伪造安卓设备
>: file aoa2sock
aoa2sock: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=XXXXXXXX, with debug_info, not stripped
在用 Ghidra(感谢调试信息)检查 aoa2sock 二进制文件并阅读内核代码之后,我终于找到了问题所在。内核的串行端口 gadget 使用的 USB 子类与 AOA 使用的不同,且无法从用户空间更改。
“这是一个错误吗?我认为AOA使用USB_SUBCLASS_VENDOR_SPEC作为通用接口是正确的。”
修补内核
最终我不得不下载内核源码,并对 f_serial.c gadget 功能进行了补丁,以更改 USB 子类。在编译内核模块并使用 modprobe 加载它之后,它终于起作用了,aoa2sock 二进制文件识别到了设备。
我的伪造安卓设备终于连接到了我的伪造车载单元
剩下的工作就是以某种方式重新创建那个 “nftp” 协议。我并不真的想使用专有的 .xs 文件实现,所以我用Python写了自己的版本。
此时,我拥有了所有的部分,树莓派现在取代了安卓应用:
树莓派端:
Python 脚本("nftp" 实现) <=> USB Gadget 模式(模拟 AOA)
车载单元端(与之前相同):
USB (主机) <=> aoa2sock <=> "nftp" (.xs 脚本) <=> [读写系统文件]
创建后门涉及发出 “nftp” 命令来编辑 /navi 目录下的特定文件,并注入一个调用 bash 脚本的命令,这个 bash 脚本(也使用 “nftp” 上传)包含了作为 root 运行的有效载荷。
H4cking Time
经过我使用双树莓派设置进行了大量测试后,我相信这个方法会奏效…
树莓派连接到信息娱乐主机
正在设置更新…
准备好“使用手机更新”,该选项仅在版本6.0.10.2之后可用
等待连接
是时候将树莓派置于小工具模式(我使用SSH连接到它)了。
发送并运行有效载荷…
成功啦!我有root权限。
该有效载荷只是调用我在分析固件时发现的特定D-Bus方法,它显示了一个带有自定义文本和标题的弹出窗口。文本是
id
命令的输出。
最后,在将有效负载替换为更有用的东西之后,一个简单的socat
反弹shell,我有了完全的访问权限。
原文始发于微信公众号(安全脉脉):我如何黑了我的车-雷诺 MediaNav Evolution