2024 AFS-47 电子数据功能性鉴定(移动终端 APP)(2024能力验证)
一、委托事项
1.给出检材APK的SHA256值。
2.给出检材APK的包名及版本。
3.给出检材APK的安全加固方式。
4.对检材APK中的AndroidManifest.xml进行解析,给出该APK申请的Android系统定义的权限数量及具体权限。(具体权限的答案格式:android.permission.XXX)
5.检材APK第三方SDK服务商为华为技术有限公司,给出其应用唯一标识(APPID)值。(答案格式:000000000)
6.给出检材APK上传运动数据的服务器的IP地址及端口号。(答案格式:http(s)://host:port/path)
7.给出检材APK上传运动数据的加密方式及密钥。
8.检材APK是否有后台监听并录音保存的功能。如有,给出其触发的音量阈值。
9.检材APK安装后是否会自启动。如会,分析其触发条件。
10.点击检材APK主界面中“清除数据”按钮,给出清除数据的时间段。(答案格式:点击按钮的前XX天)
二、工具
鉴定专用工作站:FL-2000 取证航母
APK分析工具:APK Messenger 4.1
脱壳工具:BlackDex32 v3.2.0
反编译工具:GDA4.11
文件哈希校验工具:HashMyFiles(v2.42)
杀毒工具:火绒安全软件(版本:5.0.75.5)
抓包工具:Fiddler v5.0.20202.18177
模拟器:雷电模拟器9.0.62
三、过程
检材信息:“e-health.apk”文件大小:9,316,556字节,修改时间:2024/7/15 15:17:53,MD5:B70591D5BE85B6D642AEE7DB7ABAB24B,SHA1:C18EB06383B1FD72C20B6897037DF4C2E595FDE0,SHA256:12A3BB9371804298163A4EE50D3AFD39A2DB18ADE39F9669695DE53B605FE99C。
1.委托事项1过程
使用“鉴定专用工作站”连接送检检材,使用“哈希值校验工具”计算“e-health.apk”的校验值,SHA256:12a3bb9371804298163a4ee50d3afd39a2db18ade39f9669695de53b605fe99c。
2.委托事项2过程
使用“APK分析工具”打开“e-health.apk”,经分析,该APK包名为com.ehealth.app,版本为3.2.8,版本号为451。
3.委托事项3过程
使用“APK分析工具”打开“e-health.apk”,经分析,该APK加固方式为360加固。
4.委托事项4过程
使用“鉴定专用工作站”连接送检检材,并解压送检检材。发现解压后的目录中存在“AndroidManifest.xml”文件,对文件内容进行分析,该APK申请的Android系统定义的权限数量为13个,具体权限为:
1)android.permission.ACCESS_FINE_LOCATION
2)android.permission.INTERNET
3)com.google.android.things.permission.MANAGE_SENSOR_DRIVERS
4)android.permission.FOREGROUND_SERVICE
5)android.permission.ACTIVITY_RECOGNITION
6)android.permission.ACCESS_COARSE_LOCATION
7)android.permission.ACCESS_BACKGROUND_LOCATION
8)android.permission.RECORD_AUDIO
9)android.permission.WRITE_EXTERNAL_STORAGE
10)android.permission.READ_EXTERNAL_STORAGE
11)android.permission.ACCESS_NETWORK_STATE
12)android.permission.WAKE_LOCK
13)android.permission.RECEIVE_BOOT_COMPLETED。
5.委托事项5过程
使用“鉴定专用工作站”连接送检检材,并解压送检检材。发现解压后的目录中存在“AndroidManifest.xml”文件,对文件内容进行分析,APK第三方SDK服务商为华为技术有限公司,其应用唯一标识(APPID)为110732097。
6.委托事项6过程
使用雷电模拟器9.0.62创建安卓虚拟机,将检材安装到安卓虚拟机中,对虚拟机网络进行配置,设置代理为192.168.30.5:8888(该代理为fiddler的端口)。
使用“鉴定专用工作站”连接送检检材,启动“抓包工具”,启动安装好的检材应用“e-health”,点击skip跳过启动界面,允许程序获取弹出的所有权限,点击start后点击stop。检查“抓包工具”获取到的信息,经分析,APK上传运动数据的服务器IP及端口号为“http://47.102.128.191:3306/upload_steps”。
7.委托事项7过程
根据委托6分析过程,继续对上传的数据进行分析,使用“抓包工具”查看该上传信息的语法“{"ciphertext":"euMKmw6NqHGPoi5dSVuErn8Ivwy3zt8w2/XSgF9rhXAPoq+looJRiKYt/ulN+7K763HNa8jxNYaNaSnFslDmEQ==","iv":"rV4D3NWo9XFiVVQSxpibNQ=="} ”。
使用“脱壳工具”将送检检材进行脱壳处理,使用“反编译工具”对脱壳后的程序进行反编译。对逆向的代码进行分析,搜索关键词ciphertext,找到com.softhouse.workingout.ui.login.EncryptionInterceptor代码中存在关键词ciphertext,对EncryptionInterceptor类代码进行分析,经分析,EncryptionInterceptor类实现了Interceptor 接口,用于在网络请求和响应中对数据进行加密和解密。该拦截器通过 AES/CBC/PKCS5Padding 加密算法来处理请求体和响应体:
1)创建一个Cipher实例,指定加密算法为AES,模式为CBC,填充方式为PKCS5Padding;
2)创建一个16字节的初始化向量(IV),CBC模式需要IV来确保相同的明文每次加密得到不同的密文;
3)使用提供的加密密钥(密钥是一个byte数组(byte[]))和IV初始化Cipher实例,用于加密操作(Cipher.ENCRYPT_MODE);
4)将明文字符串转换为字节数组,使用UTF-8字符集;
5)检查转换结果是否为空,确保转换成功;
6)执行加密操作,将明文字节数组加密成密文字节数组;
7)创建一个包含加密数据的Map,包括IV和密文,分别进行Base64编码。
对反编译后的代码继续分析,在“com.softhouse.workingout.BaseApplicationKt”代码中发现密钥,byte[] uobyteArray = Base64.decode("ZS1oZWFsdGhfMjAyNF9oYXBweV9jb2RlX0NOX3NmamQ=", 2);使用Base64解密,密钥为e-health_2024_happy_code_CN_sfjd。
8.委托事项8过程
使用“脱壳工具”将送检检材进行脱壳处理,使用“反编译工具”对脱壳后的程序进行反编译。在com.softhouse.workingout.service.RecordingService下发现存在代码。
对代码进行分析,detectSpeaking 方法检测音量阈值并决定是否录音:
1)持续读取音频数据。
2)通过 getMaxAmplitude 方法计算当前缓冲区的最大音量幅度。
3)如果最大音量超过 2000,则设置 isSpeaking 标志为 true,表示检测到讲话,并将数据写入 uByteArrayOu。
4)如果最大音量低于 2000 且 isSpeaking 为 true,则表示讲话结束,保存音频数据并重置缓冲区。
startRecording方法录音自动启动:
1)初始化 AudioRecord 对象。
2)调用 AudioRecord 的 startRecording 方法开始录音。
3)设置 isRecording 标志为 true,表示正在录音。
4)启动一个新线程运行 detectSpeaking 方法,用于检测讲话。
stopRecording 方法停止录音:
1)停止录音:将 isRecording 标志设置为 false,停止录音线程。
2)停止 AudioRecord:调用 recorder 的 stop 方法停止录音。
3)释放资源:调用 recorder 的 release 方法释放音频录制器的资源。
4)清空录音器:将 recorder 设置为 null。
saveAudioToFile 方法保存录音:
1)根据当前日期和时间生成文件名。
2)将音频数据保存到应用的外部存储目录中的一个文件中。
3)保存成功后记录日志。
uploadAudio 方法上传音频:
1)检查音频数据:如果音频数据为空,记录错误日志并返回。
2)上传音频数据:使用 Retrofit 框架,通过 ApiServiceKt.getApi().uploadAudio 方法上传音频数据。创建一个包含音频数据和媒体类型 application/octet-stream 的 RequestBody,并将其传递给 uploadAudio 方法。
3)启动上传:调用 enqueue 方法异步上传音频数据,并指定回调处理上传结果。
4)记录日志:记录上传开始的日志信息。
onCreate 方法服务创建时自动启动录音;onDestroy 方法服务销毁时停止录音;onStartCommand 方法服务启动命令的处理方法,返回 START_STICKY,表示服务被杀死后会重新启动。
综上,RecordingService 是一个自动录音的服务,当音量阈值超过 2000 时开始录音并保存音频文件,在服务停止时上传音频。
9.委托事项9过程
使用“鉴定专用工作站”连接送检检材,并解压送检检材。发现解压后的目录中存在“AndroidManifest.xml”文件,对文件内容进行分析,发现该APK存在申的Android权限android.permission.RECEIVE_BOOT_COMPLETED,该权限表示允许程序开机自启动。
使用“脱壳工具”将送检检材进行脱壳处理,使用“反编译工具”对脱壳后的程序进行反编译。在com.softhouse.workingout.receiver.BootReceiver发现存在代码:
1)BootReceiver 类继承自 BroadcastReceiver,用于接收系统广播。导入了一些需要的类和库,例如 Context、Intent、WorkManager 等。
2)onReceive 方法是广播接收器的核心,当接收到广播时调用。通过检查 Intent 的 action 是否为 android.intent.action.BOOT_COMPLETED 来判断是否是设备启动完成的广播。
如果是设备启动完成的广播,则构建一个一次性的 WorkRequest,用于启动 BootWorker 后台任务,并将其加入 WorkManager 进行管理和执行。
“com.softhouse.workingout.receiver.BootWorker”代码:
1)BootWorker 类继承自 Worker,这是一个用于执行后台任务的类,依赖于 WorkManager。
2)构造方法接收 Context 和 WorkerParameters,并调用父类 Worker 的构造函数。使用 Intrinsics.checkNotNullParameter 确保传入的参数不为空。
3)创建一个Intent,使用 StubApp.getOrigApplicationContext(this.getApplicationContext()) 获取原始的应用上下文,并启动 MainActivity;
使用 addFlags(0x10000000) 设置启动意图的标志,0x10000000 是 Intent.FLAG_ACTIVITY_NEW_TASK 的标志,确保在新的任务栈中启动活动;
调用 startActivity(intent) 启动 MainActivity;
创建一个 ListenableWorker$Result 的成功结果,并返回。
综上,APK安装后会自启动,当设备完成启动时,系统广播 android.intent.action.BOOT_COMPLETED 被 BootReceiver 接收。BootReceiver 创建并提交一个后台任务请求,指定由 BootWorker 执行。BootWorker 被调度执行,启动应用的主界面 MainActivity。触发条件即 android.intent.action.BOOT_COMPLETED 广播(Android 系统广播动作(action),表示设备已经完成启动过程并准备好接受正常操作。这种广播是由系统在设备启动完成后自动发送的)。
10.委托事项10过程
使用“脱壳工具”将送检检材进行脱壳处理,使用“反编译工具”对脱壳后的程序进行反编译。在com.softhouse.workingout.ui.MainActivity中发现存在代码,对代码进行分析,该代码为清除数据相关代码,该代码清除数据的方法主要是以下函数:
1)clearStepsData()启动一个协程以执行清除数据操作:
调用 BuildersKt.launch$default 方法启动一个协程,该协程执行 MainActivity$clearStepsData$1 (com.softhouse.workingout.ui.MainActivity$clearStepsData$1;
实现了 Function2 接口,用于在 MainActivity 中清除步数数据。它的主要功能是异步执行清除操作,通过 invokeSuspend 方法实现协程的挂起和恢复,处理数据清除的逻辑)中定义的逻辑。这里的逻辑就是执行 clearStepsDataImpl 方法。
2)clearStepsDataImpl(Continuation p0)实际执行数据清除操作,删除特定时间段之前的数据:
创建一个 Calendar 实例,并将时间设置为当前时间减去15天(即过去15天)。
获取 mainRepository 实例,如果 mainRepository 为 null,则抛出未初始化异常。
调用 mainRepository.deleteStepsDataBefore(timeInMillis, p0) 方法,这个方法会删除所有在指定时间(15天前)之前的数据。
如果 deleteStepsDataBefore 方法返回 IntrinsicsKt.getCOROUTINE_SUSPENDED(),则协程会暂停,直到该方法完成。
综上,clearStepsData():用于启动协程,以异步方式清除数据。clearStepsDataImpl(Continuation p0):具体执行清除数据的逻辑,删除前15天的数据。
四、结论
1. 检材APK的SHA256值为12A3BB9371804298163A4EE50D3AFD39A2DB18ADE39F9669695DE53B605FE99C。
2. 检材APK的包名为com.ehealth.app,版本为3.2.8,版本号为451。
3. 出检材APK的安全加固方式为360加固。
4. 对检材APK中的AndroidManifest.xml进行解析,该APK申请的Android系统定义的权限数量为13个及具体权限分别为:
1)android.permission.ACCESS_FINE_LOCATION
2)android.permission.INTERNET
3)com.google.android.things.permission.MANAGE_SENSOR_DRIVERS
4)android.permission.FOREGROUND_SERVICE
5)android.permission.ACTIVITY_RECOGNITION
6)android.permission.ACCESS_COARSE_LOCATION
7)android.permission.ACCESS_BACKGROUND_LOCATION
8)android.permission.RECORD_AUDIO
9)android.permission.WRITE_EXTERNAL_STORAGE
10)android.permission.READ_EXTERNAL_STORAGE
11)android.permission.ACCESS_NETWORK_STATE
12)android.permission.WAKE_LOCK
13)android.permission.RECEIVE_BOOT_COMPLETED
5. 检材APK第三方SDK服务商为华为技术有限公司,其应用唯一标识(APPID)值为110732097。
6. 检材APK上传运动数据的服务器的IP地址及端口号为“http://47.102.128.191:3306/upload_steps”。
7. 给出检材APK上传运动数据的加密方式为加密算法为AES,模式为CBC,填充方式为PKCS5Padding,密钥为e-health_2024_happy_code_CN_sfjd。
8. 检材APK有后台监听并录音保存的功能。其触发的音量阈值为2000。
9. 检材APK安装后会自启动。其触发条件为android.intent.action.BOOT_COMPLETED 广播(Android 系统广播动作(action),表示设备已经完成启动过程并准备好接受正常操作。这种广播是由系统在设备启动完成后自动发送的)。
10.点击检材APK主界面中“清除数据”按钮,清除数据的时间段为点击按钮的前15天。