也可移步Hor1zon公众号
https://mp.weixin.qq.com/s/aXr3E1THtLmYbAFnYnuCPA
D3_car_flag1
题目环境太垃圾了,安卓环境一直断😅
其实很简单,一开始有点懵,想加个监看进去看看,日过车的都知道scrcpy是个好工具😋
https://github.com/Genymobile/scrcpy

可是这个环境真的太卡了,上了scrcpy之后那是一点就断;背景这几个字暗示了要找到车的GPS数据,但是这个导航怎么点都点不开,还老是断服务,后边发现根本没装车载导航(地图)服务;
所以还是接着命令行操作,先来看一下应用列表 哎 您猜怎么着?
一眼就看到了一个非常可疑的APP
package:com.d3car.factory
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 
 | generic_x86_64:/ $ pm list packagespackage:com.android.cts.priv.ctsshim
 package:com.android.car.messenger
 package:com.android.providers.telephony
 package:com.google.android.car.kitchensink
 package:com.android.providers.calendar
 package:com.android.providers.media
 package:com.android.wallpapercropper
 package:com.android.car.media
 package:com.android.car.radio
 package:com.android.car.trust
 package:com.android.documentsui
 package:com.android.externalstorage
 package:com.android.htmlviewer
 package:com.android.companiondevicemanager
 package:com.android.quicksearchbox
 package:com.android.mms.service
 package:com.android.providers.downloads
 package:com.android.car.overview
 package:android.car.cluster.loggingrenderer
 package:com.android.defcontainer
 package:com.android.car.mapsplaceholder
 package:com.android.providers.downloads.ui
 package:com.android.pacprocessor
 package:com.android.certinstaller
 package:com.android.carrierconfig
 package:android
 package:com.android.contacts
 package:com.android.camera2
 package:com.android.car.systemupdater
 package:com.android.car
 package:com.android.egg
 package:com.android.mtp
 package:com.android.nfc
 package:com.android.backupconfirm
 package:com.android.provision
 package:com.android.statementservice
 package:com.android.calendar
 package:com.android.systemui.theme.dark
 package:com.android.car.hvac
 package:com.android.providers.settings
 package:com.android.sharedstoragebackup
 package:com.android.printspooler
 package:com.android.dreams.basic
 package:com.android.car.dialer
 package:com.android.webview
 package:com.android.inputdevices
 package:com.android.support.car.lenspicker
 package:com.android.bips
 package:com.android.musicfx
 package:com.android.cellbroadcastreceiver
 package:android.ext.shared
 package:com.android.onetimeinitializer
 package:com.android.server.telecom
 package:com.android.keychain
 package:com.android.printservice.recommendation
 package:com.android.gallery3d
 package:android.ext.services
 package:com.android.calllogbackup
 package:com.android.packageinstaller
 package:com.android.carrierdefaultapp
 package:com.svox.pico
 package:com.android.car.media.localmediaplayer
 package:com.android.proxyhandler
 package:com.android.inputmethod.latin
 package:org.chromium.webview_shell
 package:com.d3car.factory
 package:android.car.usb.handler
 package:com.android.managedprovisioning
 package:com.android.dreams.phototable
 package:com.android.smspush
 package:android.car.cluster.sample
 package:com.android.wallpaper.livepicker
 package:com.android.storagemanager
 package:jp.co.omronsoft.openwnn
 package:com.android.bookmarkprovider
 package:com.android.settings
 package:com.android.calculator2
 package:com.android.cts.ctsshim
 package:com.android.vpndialogs
 package:com.android.email
 package:com.android.music
 package:com.android.phone
 package:com.android.shell
 package:com.android.wallpaperbackup
 package:com.android.providers.blockednumber
 package:com.android.providers.userdictionary
 package:com.android.emergency
 package:com.android.location.fused
 package:com.android.deskclock
 package:com.android.systemui
 package:com.android.bluetoothmidiservice
 package:com.android.bluetooth
 package:com.android.providers.contacts
 package:com.android.captiveportallogin
 generic_x86_64:/ $
 generic_x86_64:/ $
 generic_x86_64:/ $
 generic_x86_64:/ $ pm path com.d3car.factory
 package:/system/priv-app/D3Factory/D3Factory.apk
 generic_x86_64:/ $
 
 PS G:\> adb pull /system/priv-app/D3Factory/D3Factory.apk
 /system/priv-app/D3Factory/D3Factory.apk: 1 file pulled, 0 skipped. 0.1 MB/s (38128 bytes in 0.354s)
 
 | 
简单逆向就可以找到flag了)
| 12
 3
 4
 5
 
 | <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:gravity="center" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
 <TextView android:textSize="@dimen/common_textsize_24" android:id="@+id/flag1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dp" android:text="d3ctf{yes_you_f1nd_b4ckdo0r}"/>
 <Button android:id="@+id/tcpdump" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="open/close tcpdump"/>
 </LinearLayout>
 
 | 
也可以用另一种方法,直接拉起应用的Activity
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | generic_x86_64:/ $ dumpsys package com.d3car.factory | grep -i activityActivity Resolver Table:
 4d5331e com.d3car.factory/.FactoryActivity filter 1beb95a
 b8e17ff com.d3car.factory/.PwdAuthActivity filter ee66505
 b8e17ff com.d3car.factory/.PwdAuthActivity filter ee66505
 android.permission.USER_ACTIVITY: granted=true
 android.permission.MANAGE_ACTIVITY_STACKS: granted=true
 android.permission.USER_ACTIVITY: granted=true
 android.permission.MANAGE_ACTIVITY_STACKS: granted=true
 generic_x86_64:/ $
 generic_x86_64:/ $
 generic_x86_64:/ $
 generic_x86_64:/ $ am start -n com.d3car.factory/.FactoryActivity
 Starting: Intent { cmp=com.d3car.factory/.FactoryActivity }
 generic_x86_64:/ $
 generic_x86_64:/ $
 generic_x86_64:/ $
 
 | 

D3_car_flag2
| 12
 
 | PS G:\> adb pull /system/priv-app/   #我甚至把所有的app都拖了下来)PS G:\> adb pull /system/priv-app/D3Factory/oat/x86_64
 
 | 

这里一开始是先去把odex转成dex
利用了baksmali-2.5.2.jar和smali-2.5.2.jar,转成的dex发现只还原了方法名,里面的核心的代码根本看不到,再试试把vdex转成dex,windows环境及其不友好,最后在ubuntu虚拟机完成了还原
所需要的工具为:https://github.com/anestisb/vdexExtractor
🤗项目下载下来后直接./make.sh gcc编译就行,然后会在bin目录下生成vdexExtractor文件😚
执行命令:./vdexExtractor -i xxx.vdex -o ./ 
最后jadx打开该dex,即可看到核心代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 
 | package com.d3car.factory;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.Toast;
 
 public class PwdAuthActivity extends Activity {
 private Context mContext;
 private Button mEnterBtn;
 private TextView mKeyText;
 private EditText mPwdText;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(2130837504);
 this.mPwdText = (EditText) findViewById(2131165185);
 this.mEnterBtn = (Button) findViewById(2131165186);
 this.mKeyText = (TextView) findViewById(2131165184);
 this.mContext = getApplicationContext();
 Log.d("D3CTF", "onCreate: ");
 this.mEnterBtn.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 PwdAuthActivity.this.verifyPWD(PwdAuthActivity.this.mPwdText.getText().toString(), PwdAuthActivity.this.mKeyText.getText().toString());
 }
 });
 }
 
 public void verifyPWD(String pwd, String key) {
 if (pwd.length() == 0) {
 Toast.makeText(this, getString(2131099707), 0).show();
 } else if (verifyPassWord(pwd, key)) {
 Log.d("D3CTF", "verifyPWD: the password is right!");
 startActivity(new Intent(this, FactoryActivity.class));
 } else {
 Toast.makeText(this, getString(2131099706), 0).show();
 }
 }
 
 public static boolean verifyPassWord(String password, String key) {
 if (key == null || key.isEmpty()) {
 return "20240419".equals(password);
 }
 return "uVQPRRYTrpvqvCv6".equals(encryptPwdByKey(password, key));
 }
 
 public static String encryptPwdByKey(String pwd, String key) {
 char[] pwd_arr = pwd.toCharArray();
 char[] key_arr = key.toCharArray();
 char[] result = new char[pwd.length()];
 for (int i = 0; i < pwd.length(); i++) {
 result[i] = (char) (pwd_arr[i] ^ key_arr[i % pwd.length()]);
 }
 return new String(result);
 }
 }
 
 | 
 
验证代码的核心在这里,其实逆向逻辑还是很简单,就是一个异或,但是这里的数据真是诱导了我,看这里的逻辑是传入了key和密码。因为即使要逆向,这两个数据你得有一个才行,一开始我以为这个20240419是key,然后逆向出密码,发现不对,这就不得不开始看一下代码的整体逻辑

这个TextView?再来看看登录页面


key就是屏幕上的字符串😂,然后直接梭脚本就行
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | data="uVQPRRYTrpvqvCv6"key="D2036445ADCGF12W7"
 pwd=""
 for i in range(len(data)):
 pwd+=chr(ord(data[i])^ord(key[i]))
 print(pwd)
 
 
 
 
 | 

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 
 | package com.d3car.factory;
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import java.io.IOException;
 
 private CheckBox mTcpDump;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(2130837506);
 this.mTcpDump = (CheckBox) findViewById(2131165189);
 if (SystemProperties.getInt("sys.tcpdump", 0) == 1) {
 this.mTcpDump.setChecked(true);
 } else {
 this.mTcpDump.setChecked(false);
 }
 this.mTcpDump.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
 @Override
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
 if (isChecked) {
 SystemProperties.set("sys.tcpdump", "1");
 try {
 Runtime.getRuntime().exec("/system/xbin/tcpdump -i any -s 0 -w /sdcard/tcpdumplog.pcap -W 1");
 } catch (IOException e) {
 e.printStackTrace();
 }
 } else {
 SystemProperties.set("sys.tcpdump", "0");
 try {
 Runtime.getRuntime().exec("pkill tcpdump");
 } catch (IOException e2) {
 e2.printStackTrace();
 }
 }
 }
 });
 }
 }
 
 | 
在adb直接使用tcpdump显示被ban了,可以看到程序后门是一个tcpdump服务

用自带的APP后门去抓包,可以看到存在mqtt服务再循环往复的发送同样的包。

抓到MQTT服务的主题&账号&密码(断的太快了 没机会传扫描工具到IVI里面扫😭扫一下应该就能扫到其他ECU了
| 12
 3
 4
 5
 6
 7
 
 | Client ID Length: 11Client ID: Gojo_Satoru
 User Name Length: 11
 User Name: abmaM_kcalb
 Password Length: 14
 Password: Ya5_1_n4C_tahW
 
 
 | 
以及两条MQTT的报文,这里的mqtt是在做can的转发,在环境中实现uds的功能
| 12
 3
 4
 5
 
 | Topic: can/514/writeMessage: 022701ffffffffff   #看到2701 血脉觉醒 是UDS服务 这里给了did为514的ecu的pincode
 
 Topic: can/514/write
 Message: 0527022dcf28ffff
 
 | 

环境中应该不存在模拟的CAN总线(向出题人求证了这一点),ivi这里应该是通过mqtt与其他ECU通信,所以可以先用22服务去读其他ecu信息,然后要过掉27服务,进入QNX拿flag,也向出题人求证了这一点,flag果然在QNX里面。这里难点在于确定qnx的did,然后就通过mqtt执行can/ecu id/write来执行诊断命令;还有就是要把环境代理到本地来发mqtt广播包;

现在没有环境也没法再具体分析操作,看了官方和W&M师傅的wp,感觉总体思路上和我的想法差不多,可以用fscan扫到一些seed2key.dll,也就是27服务密钥算法,逆向得到key,而且qnx还存在31服务,后边的过程参考W&M师傅的wp,写的很细🫡
https://blog.wm-team.cn/index.php/archives/75/#D3+car+2
D3_car_flag3
无地图服务的背景提示联想到flag应该和GPS有关

前面查看应用包发现有一个com.android.location.fused的APP,这里我的思路有点偏了)我跑过去研究这个APP,考虑从这个app中拿到gps定位,但我再也没连上过靶机😭也无法验证是否可行。
和前面一样,把odex转成dex,可以看到车机是由GPS服务的,只是需要一个APP去调用GPS权限即可拿到定位信息,下一步想法就是搞一个地图/定位APP adb install上去来获取经纬度信息。
从车机安全性考虑,一般都会采用私有证书签名,在/system/etc/security找到了车机的证书信息,通过伪造签名证书就可以让APP安装到车机上面了。

看了W&M师傅的wp真的给跪了,通过相机调用GPS信息再来拿到经纬度信息的想法真的太绝了Orzzzzzz
我倒是也打开过车机设置APP但他真的太卡了🥲基本上点两下就会断线,我就得再次启动安卓服务,然后他再次断线😭

由于环境无了,这里引用凌武出题人师傅的截图,装好定位APP就可以拿到经纬度了。

因为目前国内的车载地图服务商除了特斯拉基本都是高德,所以直接去高德搜索经纬度

然后再保利·江语海东南门这里看到出题人的用户评价,进个人主页就可以拿到flag了。
