HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

admin 2024年6月20日09:55:46评论2 views字数 6933阅读23分6秒阅读模式
HowIHackedMyCar 2021款 现代IONIQ (一)
HowIHackedMyCar 2021款 现代IONIQ (二) Making a Backdoor
HowIHackedMyCar 2021款 现代IONIQ (三) Making Software

HowIHackedMyCar 2021款 现代IONIQ (四)Creating Custom Firmware

HowIHackedMyCar 2021款 现代IONIQ (五)CAN Bus分析

HowIHackedMyCar 2021款 现代IONIQ (六)How I Hacked my Car Again
本合集共7部分,本篇为第七部分

来源:programmingwithstyle.com,感谢greenluigi1

The port

利用第三部分中可以找到的信息。我为DAudio2开发设置了QTCreator IDE,并使用我的DAudio2 Gui Template Application作为起始模板。

有许多Doom及其类似游戏的版本,以及许多可以作为新移植起点的移植版本。我决定使用doomgeneric,这是一个特别容易移植的Doom版本。

doomgeneric声称我所要做的就是创建一个doomgeneric_myPlatform.cpp文件,并实现5个简单的函数,就这样,Doom就被移植了。

“All I had to do” Joke #5

是的,它没那么简单,我沿途遇到了一些障碍和困难。

但现在,回到开始:

我有5/6个可以实施的函数:

Function Description
DG_Init Platform-specific initialization (Creating window, allocating buffers, etc..)
DG_DrawFrame Draw the frame from the framebuffer to the window
DG_SleepMs Sleeping in milliseconds
DG_GetTicksMs Getting the ticks that passed since the launch in milliseconds
DG_GetKey Provide keyboard inputs to Doom
DG_SetWindowTitle Set the window title (Not applicable in this case)

doomgeneric很贴心地提供了一些示例移植。其中之一是X11/xlib移植。移植具有相当通用的DG_SleepMs(),DG_GetTicksMs()实现,以及一些不错的帮助方法,使DG_GetKey()更容易。我决定复制这些用于我的移植。

这让我需要实现3个函数,DG_Init(),DG_DrawFrame(),以及一些DG_GetKey()逻辑。

我在doomgeneric_daudio.cpp文件中创建了我的doomgeneric_daudio.cpp文件,并开始了初始化逻辑。

Startup
为了保持简单,我在该文件中创建了我的main()函数,并复制了初始化我的TestGuiApplication的代码。我还把我所有的“测试”占位符文本重命名为“Doom”。
HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it
在这一点上,我决定我不需要一个单独的DG_Init()函数来初始化事情,因为我有一个main()函数。我删除了它,并将其中的几个东西移动到了main()中。按照doomgeneric的Readme.md中的指示,我添加了对doomgeneric_Create();
HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

在创建这个main()函数时,我遇到了一些复杂情况,即使它非常简单。其中主要的是参数处理。

DAudio2 GUI应用程序的工作方式有些奇怪。它们不能像大多数Linux发行版那样从命令行启动。它们的启动由一个名为Helix的窗口管理器处理,参数的格式标准化,以允许启动应用程序中的特定AppViews或AppServices。

因此,我不能像通常那样将参数传递给doomgeneric_Create(),因为这可能会产生意想不到的副作用。我简单地硬编码了自己的参数并传递了它们。

漂亮的图片?

下一步是在屏幕上绘制帧

经过一些研究,我发现我可以使用一个QLabel通过这个过程显示一个帧缓冲区:

1 使用帧缓冲区生成一个QImage 2 使用QImage创建一个QPixmap 3 使用QPixmap作为QLabel的背景图像 doomgeneric写入的缓冲区称为DG_ScreenBuffer。我在MainWindow上创建了一个名为bufferQImage的字段,并设置它引用DG_ScreenBuffer。然后我用它来创建一个QPixmap,用作我的displayLabel的背景图像。MainWindow构造函数开始

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it
我还需要在有新帧要渲染时更新这个QLabel。我创建了一个名为refreshDrawingBuffer的函数,它调用displayLabel上的更新函数。根据我的研究,这应该会使得QLabel重新绘制自身。
HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it
我将DG_DrawFrame()函数连接到调用refreshDrawingBuffer()函数,并设置了一个QTimer来反复调用doomgeneric_Tick()函数,这应该会使得游戏运行。

它奏效了吗?

我现在应该有了绘制和运行Doom演示所需的代码。

为了测试这个,我需要一个WAD文件。WAD文件是Doom引擎的游戏数据文件。它们包含游戏中使用的水平、地图、敌人和纹理。我找到了原始的DOOM.WAD文件,并将其下载到我的闪存驱动器中。

为了使Doom引擎能够加载这个WAD文件,我在参数中硬编码了一个路径,告诉Doom读取“/appdata/DOOM.WAD”。

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

我编译了应用程序,然后进入了我的车辆。

为了让我的应用被Helix注册,我必须在/etc/appmanager/appconf文件夹中为它添加一个.appconf文件。我创建了一个DAudio2Doom.appconf文件,并复制到文件夹中,内容如下:

[Application]Name=com.greenluigi1.doomExec=/appdata/DAudio2Doom[DoomAppView]# ComponentName : com.greenluigi1.doom.DoomAppViewType=AppView

然后我运行了以下命令来复制我的DAudio2Doom编译后的二进制文件,将其标记为可执行文件,重启系统以便它可以读取新的.appconf文件,最后启动应用程序。

cp /run/media/B208-FF9A/DAudio2Doom /appdatachmod +x /appdata/DAudio2Doomrebootappctl startAppView com.greenluigi1.doom.DoomAppView

在运行最后一个命令后,应用程序启动了,很快就变得明显它没有工作。

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

我期望看到Doom的第一帧,但屏幕上完全空白。

然后整个车载主机重新启动了……

在这个平台上调试有点困难,因为Helix启动应用程序的方式。所以我目前调试的方法是到处放置日志语句。

所以为了弄清楚出了什么问题,是时候记录一切了。

我创建了几个帮助日志的方法,然后从Doom的日志函数中调用它们

void DG_Log(const char* logMessage){    __android_log_print(ANDROID_LOG_DEBUG, "DAudio2Doom", logMessage);}int DG_Log_printf(const char *__restrict __format, ...){    int result;    va_list args;    va_start(args, __format);    result = __android_log_vprint(ANDROID_LOG_DEBUG, "DAudio2Doom", __format, args);    va_end(args);    return result;}int DG_Log_vprintf(const char *__restrict __format, va_list ap){    return __android_log_vprint(ANDROID_LOG_DEBUG, "DAudio2Doom", __format, ap);}

再次运行后,我提取了日志,发现了几个问题,比如我忘了复制DOOM.WAD文件。我还发现当Doom遇到错误,比如找不到有效的WAD文件时,它会调用abort()函数。

应用程序中止后,车载主机的应用程序监视器发现应用程序崩溃了,并在几秒钟后重新启动了车载主机。

我禁用了abort()调用并复制了WAD文件。我更新了二进制文件,并启动了应用程序,结果发现又是一片空白。它仍然找不到WAD文件。我尝试了一些事情,比如更改参数(使用“-iwad”而不是“-file”),但什么都不起作用。所以,我更新了D_FindIWAD()函数,让它总是返回硬编码的路径“/appdata/DOOM.WAD”,这消除了错误。

但是空白屏幕仍然存在。我仍然错过了一些东西。

我猜测有些事情可能与帧缓冲区或我读取它的方式有关。我检查的第一件事是帧缓冲区的格式。

帧缓冲区格式

帧缓冲区只是形成图像的一堆颜色数据。在存储颜色信息时,您必须选择一个格式。该格式决定了每个像素占用的数据量、存储的颜色信息类型,以及颜色的存储顺序。

我当时使用的是QImage::Format_ARGB32,这意味着QT期望数据以以下格式存储:

- Alpha (Transparency): 1 byte
- Red: 1 byte
- Green 1 byte
- Blue 1 byte

这使得每个像素共有4字节(或32位)的颜色数据。

但我甚至不确定这是否正确,当时只是猜测。

所以我看了看doomgeneric提供的示例,并看到了对SDL格式RGB888的引用。

texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, DOOMGENERIC_RESX, DOOMGENERIC_RESY);
我更新了我的代码,使用QImage::Format_RGB888格式并运行它。
HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

我尝试了几种其他的QImage::Formats,但似乎没有什么起作用。我还查看了Doom的代码,看起来每个像素应该是ARGB,但正如我之前看到的那样,那不起作用。

为了确定格式,我添加了一个“Dump”按钮,该按钮会将DG_ScreenBuffer的内容转储到我的闪存驱动器上。

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

再次加载应用程序后,我转储了帧缓冲区,并使用一个名为RAW pixels viewer的工具来查看数据。

经过调整参数,我最终得到了一个工作的图像。车载主机一直在运行Doom,只是没有正确显示!它还清楚地运行了游戏演示,这意味着游戏tick函数运行正确。

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

图像的格式是BGRA,忽略了alpha颜色通道。

如果我们不忽略Alpha通道,就是这样:

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

Doom不处理任何透明度数据,所以alpha通道总是设置为0。这意味着我的程序将其读为完全透明。这就是为什么我在某些格式上有空白屏幕。

它“正确”地显示了图像,只是它是看不见的。:|

有了这些信息,很明显我的代码有两个问题。一个是格式问题,另一个是为什么图像没有在屏幕上更新。

我将格式设置为QImage::RGB32,它应该只读取RGB并忽略Alpha通道。格式不是写成QImage::BGR32的原因是车载主机使用小端格式。实际上,这意味着通道存储和读取的顺序是相反的,即BGR而不是RGB,这正是我想要的。

接下来,我必须弄清楚为什么图像没有在屏幕上更新。经过几个小时的谷歌搜索和测试各种东西,我弄清楚了,除非QLabel的QPixmap本身更新,否则更新调用不会刷新QLabel的图像。然后我更改了函数,反复将QLabel的Pixmap设置为我早先制作的bufferQImage。

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

It is… Beautiful

在启动新的二进制文件后,我看到了Doom在汽车中运行的美丽景象。
现在,我只需要连接一些输入,很快就能开始游戏了!

The Fun Part - Inputs

我决定尽可能地使这个端口有趣,通过结合连接到车载主机的一些输入,而不是仅仅连接一个无聊的老式键盘。

正如我在以前的帖子中提到的,我在旧的固件更新中找到了大量的头文件,这些文件让我可以访问许多与车辆交互的API。不幸的是,这些头文件不再在最新的固件更新中提供。但幸运的是,现代汽车并没有真正更新任何有价值的东西,所以旧的头文件仍然有效。

(嘘。不要告诉现代汽车,但你仍然可以在最新的韩国版本的固件中找到这些文件,只需点击带有“DN8”文本的深蓝色按钮。更新甚至没有加密,所以你可以直接提取zip文件并直接获取system.img文件。请注意,更新是旧的,所以它们的工作效果可能会有所不同。)

我浏览了许多文件,并记录下一些可以在游戏中用作输入的文件。以下是最吸引我的一些:

HChassis::getSteeringAngle(); // Or IHChassisListener::onSteeringAngleChanged();HChassis::getAcceleratorPedalState(); // Or IHChassisListener::onAcceleratorPedalStateChanged();HBody::isTurnSignalSwitchOn(); // Or IHBodyListener::onTurnSignalStateChanged()IHModeChangeListener::onKeyEvent();HSeat::isSeatBeltBuckleLatched();

我最初尝试了IHChassisListener和IHBodyListener回调函数。不幸的是,我无法让它们工作,所以我直接检查了get()函数。

使用我早些时候制作的Dump按钮,我连接到每个函数并检查它们是否有效。

Function Result
HChassis::getSteeringAngle() Received number between 0-6553.5 indicating steering wheel position.
HChassis::getAcceleratorPedalState() Always returned 0.
HBody::isTurnSignalSwitchOn() Received seemingly random values with no bearing on the turn signal switches.
IHModeChangeListener::onKeyEvent() Received key numbers indicating what button on the head unit or steering wheel was pressed and a state value indicating if it was pressed, released, long pressed, or long released.
HSeat::isSeatBeltBuckleLatched() Recevied a True/False value if the specified seat belt buckle was latched.
3/5不是最好,但有效的是最重要的。
Vehicle Input Location Vehicle Input Doom Input
Steering Wheel Turning wheel Left Left Arrow Key
Steering Wheel Turning wheel Right Right Arrow Key
Steering Wheel Seek Down Key (Which is actually the up key) Up Arrow Key
Steering Wheel Seek Up Key (Which is actually the down key) Down Arrow Key
Steering Wheel Mute Button Use
Steering Wheel End Call Button Fire
Head Unit Volume Knob Press Enter
Head Unit Tune Knob Press Escape

然后我使用doomgeneric的X11示例代码中提供的键队列,将这些输入连接到Doom。

Can it run Doom?

Yes It Can!

就这样,我在汽车上有了Doom的运行安装。

它完美吗?不,首先没有音频,我必须承认输入不是最好的。我使用的某些键也被后台应用程序接收,如果你试图向前移动,它们会执行比如换歌的操作。只要没有媒体源在播放(通过按下音量旋钮)它就足够好用。

哦,当你转动方向盘时,轮胎确实会动,所以最好不要进行长时间的游戏,否则你会磨损轮胎。:p

但对于这个小演示来说,它确实很有趣!

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

原文始发于微信公众号(安全脉脉):HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom it

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月20日09:55:46
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   HowIHackedMyCar 2021款 现代IONIQ (七)Nothing to it but to Doom ithttps://cn-sec.com/archives/2857485.html

发表评论

匿名网友 填写信息