第三届盘古石杯国际电子数据取证比赛决赛 2025

2025年第三届盘古石杯决赛(鸿蒙程序分析)

围绕 第三届盘古石杯国际电子数据取证比赛决赛 的公开复盘与解题记录。

上传者:zhoufish 发布日期:2026-05-28 32 次阅读

程序分析


反编译工具地址:https://github.com/ohos-decompiler/abc-decompiler

1、分析鸿蒙手机检材中“笔记.hap”文件,该软件应用名称是?【标准格式:ABCD】

PGSDBW

软件应用名称在 module.json 文件中通过 labellabelId 进行标识。label 的值为 $string:app_name,这表明应用名称是一个字符串资源引用,实际的名称存储在字符串资源文件中,labelId16777216 也用于标识该字符串资源。

image-20250618003320490.png


2、分析hap检材,软件的包名是?【标准格式:com.pgs.main】

com.example.pgsdsj

app 配置部分有关于包名的信息,具体如下:

image-20250618004337961.png


3、分析hap检材,软件图标md5的后六位是?【标准格式:a48b31】

448b23

在 笔记/module.json 文件里,能看到软件图标的引用信息:

{
    "app": {
        // ...
        "iconId": 16777218,
        "icon": "$media:foreground",
        // ...
    }
    // ...
}

找到\笔记\resources\base\media

另外,笔记/resources/base/media/layered_image.json 文件中也进一步关联了媒体资源,找到对应名字的图片

{"layered-image":{"background":"$media:16777217","foreground":"$media:16777218"}}

image-20250618004753798.png

文件名称: foreground.png
MD5: 7fb165b876a11c792bd38b1830448b23

4、分析hap检材,软件代码保存的文件名称是?【标准格式:class.dex】

modules.abc

通常是 ArkTS(HarmonyOS 应用开发的编程语言)编译后生成的字节码文件,分析这种文件可以从多个角度进行


5、分析hap检材,软件的入口类是?【标准格式:MainActivity】

EntryAbility

根据提供的 笔记/module.json 文件内容,软件的入口类可以通过 module 部分的 mainElement 字段以及 abilities 数组来确定。

分析 mainElement 字段

module 部分有如下配置:

"mainElement": "EntryAbility",

表明 EntryAbility 被指定为软件的主要元素,通常意味着它在应用启动时起到关键作用。

查看 abilities 数组中的 EntryAbility

abilities 数组中,有一个名为 EntryAbility 的能力项,其相关配置如下:

{
    "exported": true,
    "iconId": 16777218,
    "startWindowIconId": 16777225,
    "icon": "$media:foreground",
    "startWindowIcon": "$media:startIcon",
    "startWindowBackgroundId": 16777223,
    "description": "$string:EntryAbility_desc",
    "label": "$string:EntryAbility_label",
    "skills": [
        {
            "entities": [
                "entity.system.home"
            ],
            "actions": [
                "action.system.home"
            ]
        }
    ],
    "srcEntry": "./ets/entryability/EntryAbility.ets",
    "descriptionId": 16777220,
    "labelId": 16777221,
    "startWindowBackground": "$color:start_window_background",
    "name": "EntryAbility"
}

这里明确了 EntryAbility 的源代码入口文件为 ./ets/entryability/EntryAbility.ets,并且其技能(skills)包含了与系统主界面相关的实体和动作,进一步说明它是应用启动时的入口。

所以软件的入口类是 EntryAbility,对应的源代码文件是 ./ets/entryability/EntryAbility.ets


6、分析hap检材,软件的入口密码是?【标准格式:abc-134】

pgsdbw-2025

要先进行反编译

ark_disasm.exe modules.abc modules.txt

在关于LoginPage的代码中,有一个固定密码的定义:

lda.str "pgsdbw-2025"
stobjbyname 0x14, "FIXED_PASSWORD", v10

7、分析hap检材,软件存储笔记的数据库名称是?【标准格式:tmp.db】

notepad.db

从文档中关于DatabaseHelper的定义部分可以找到数据库名称的相关信息:

func_main_0函数中,明确定义了数据库名称为:

lda.str "notepad.db"
sta v11
lda v11
stlexvar 0x0, 0x1

因此,软件存储笔记的数据库名称是 ​notepad.db​。


8、分析hap检材,数据库的打开密码是?【标准格式:Abc123】

HuaweiNotePad123

关键代码

.function any &entry.src.main.ets.utils.DatabaseHelper&.func_main_0(any a0, any a1, any a2) <static> {
	newlexenvwithname 0x4, { 9 [ i32:4, string:"DOMAIN_DB", i32:0, string:"DB_NAME", i32:1, string:"SQL_CREATE_NOTES_TABLE", i32:2, string:"SQL_CREATE_NOTES_UPDATE_TRIGGER", i32:3, ]}
	mov v0, a0
	mov v1, a1
	mov v2, a2
	lda.str "notepad.db"
	sta v11
	lda v11
	stlexvar 0x0, 0x1
	lda.str "/data/storage/el2/database"
	sta v7
	lda.str "notes"
	stmodulevar 0x1
	ldai 0x2
	sta v11
	lda v11
	stlexvar 0x0, 0x0
	tryldglobalbyname 0x0, "Uint8Array"
	sta v11
	createarraywithbuffer 0x1, { 16 [ i32:72, i32:117, i32:97, i32:119, i32:101, i32:105, i32:78, i32:111, i32:116, i32:101, i32:80, i32:97, i32:100, i32:49, i32:50, i32:51, ]}
	sta v13
	sta v12
	newobjrange 0x2, 0x2, v11
	sta v8
	lda.str "CREATE TABLE IF NOT EXISTS "
	sta v11
	ldlocalmodulevar 0x1
	throw.undefinedifholewithname "DB_TABLE_NOTES"
	add2 0x4, v11
	sta v11
	lda.str " (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT,
  content TEXT NOT NULL, -- Encrypted content
  created_at INTEGER DEFAULT (strftime('%s', 'now')),
  updated_at INTEGER DEFAULT (strftime('%s', 'now'))
);"

DatabaseHelper.func_main_0 函数解析(数据库初始化部分)

这段代码是 DatabaseHelper 模块的主初始化函数,主要负责配置数据库基本信息并定义笔记表结构。以下是详细解释:

函数签名与词法环境

.function any &entry.src.main.ets.utils.DatabaseHelper&.func_main_0(any a0, any a1, any a2) <static> {
    newlexenvwithname 0x4, { 9 [ i32:4, string:"DOMAIN_DB", i32:0, string:"DB_NAME", i32:1, string:"SQL_CREATE_NOTES_TABLE", i32:2, string:"SQL_CREATE_NOTES_UPDATE_TRIGGER", i32:3, ]}
    // 后续代码...
}
  • 函数作用​:作为数据库工具类的入口函数,在模块加载时执行初始化。
  • 词法环境​:创建名为 0x4 的词法环境,包含数据库相关的常量定义:
    • DOMAIN_DB(索引0):数据库模块的域标识
    • DB_NAME(索引1):数据库名称
    • SQL_CREATE_NOTES_TABLE(索引2):创建笔记表的SQL语句
    • SQL_CREATE_NOTES_UPDATE_TRIGGER(索引3):创建更新触发器的SQL语句

数据库基本配置

mov v0, a0
mov v1, a1
mov v2, a2
lda.str "notepad.db"
sta v11
lda v11
stlexvar 0x0, 0x1
lda.str "/data/storage/el2/database"
sta v7
lda.str "notes"
stmodulevar 0x1
ldai 0x2
sta v11
lda v11
stlexvar 0x0, 0x0
  • 数据库名称​:定义数据库文件名为 notepad.db,存储到词法环境的 DB_NAME 位置(索引1)。
  • 存储路径​:指定数据库文件的存储路径为 /data/storage/el2/database(Android系统中常见的应用数据存储位置)。
  • 表名导出​:将 "notes" 导出为模块变量,作为笔记表的表名(DB_TABLE_NOTES)。
  • 初始化标识​:将数值 2 存入词法环境,可能用于标记数据库初始化状态。

加密密钥定义(与数据库加密相关)

tryldglobalbyname 0x0, "Uint8Array"
sta v11
createarraywithbuffer 0x1, { 16 [ i32:72, i32:117, i32:97, i32:119, i32:101, i32:105, i32:78, i32:111, i32:116, i32:101, i32:80, i32:97, i32:100, i32:49, i32:50, i32:51, ]}
sta v13
sta v12
newobjrange 0x2, 0x2, v11
sta v8
  • 加密密钥​:创建16字节的 Uint8Array 作为数据库加密的密钥,对应ASCII字符为 Huaw eiNotePad123(字节转换见下方)。
  • 密钥用途​:该密钥用于ChaCha20算法,对数据库中存储的笔记内容进行加密/解密。

密钥字节转换表​:

笔记表创建SQL语句

lda.str "CREATE TABLE IF NOT EXISTS "
sta v11
ldlocalmodulevar 0x1
throw.undefinedifholewithname "DB_TABLE_NOTES"
add2 0x4, v11
sta v11
lda.str " (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT,
  content TEXT NOT NULL, -- Encrypted content
  created_at INTEGER DEFAULT (strftime('%s', 'now')),
  updated_at INTEGER DEFAULT (strftime('%s', 'now'))
);"
  • SQL语句结构​:创建名为 notes 的表(表名从模块变量 DB_TABLE_NOTES 获取)。
  • 表结构字段​:
    1. id:整数类型,主键,自动递增
    2. title:文本类型,存储笔记标题
    3. content:文本类型,非空,存储加密后的笔记内容(注释明确标注为加密内容)
    4. created_at:整数类型,默认值为当前时间戳(通过 strftime('%s', 'now') 获取)
    5. updated_at:整数类型,默认值为当前时间戳,记录更新时间
  • 加密说明​:content 字段明确注释为 Encrypted content,表明该字段存储的是经过加密处理的笔记内容,与前文定义的加密密钥配合使用。

数据库初始化核心逻辑

  1. 基础配置​:定义数据库名称、存储路径和表名,确保数据持久化存储。
  2. 加密支持​:定义ChaCha20算法的加密密钥,为 content 字段的加密提供基础。
  3. 表结构设计​:创建包含加密内容字段的笔记表,自动记录创建和更新时间,保证数据完整性。

这段代码是数据库模块的基础,后续的数据库操作(如插入、查询、更新)均基于此表结构和加密配置展开。


9、分析hap检材,数据库中笔记内容采用什么加密算法?【标准格式:Sal20】

ChaCha20

在txt中可以明确看到数据库中笔记内容的加密算法相关信息:

CryptoUtils模块中,存在多个与ChaCha20加密相关的方法定义,如:

  • chacha20Encrypt:ChaCha20加密方法
  • chacha20Decrypt:ChaCha20解密方法

此外,在数据库操作insertNote中,明确使用了encryptedContent字段存储加密后的内容,且加密逻辑通过CryptoUtilsencrypt方法实现,该方法内部调用了chacha20Encrypt

所以数据库中笔记内容采用 ChaCha20算法 进行加密。


10、分析hap检材,数据库中笔记内容加密秘钥是?【标准格式:Abc123】

NotePadContent12

关键代码

.function any &entry.src.main.ets.utils.CryptoUtils&.func_main_0(any a0, any a1, any a2) <static> {
	newlexenvwithname 0x3, { 7 [ i32:3, string:"CHACHA_KEY", i32:0, string:"CHACHA_IV", i32:1, string:"DOMAIN_CRYPTO", i32:2, ]}
	mov v0, a0
	mov v1, a1
	mov v2, a2
	ldai 0x3
	sta v5
	lda v5
	stlexvar 0x0, 0x2
	tryldglobalbyname 0x0, "Uint8Array"
	sta v5
	createarraywithbuffer 0x1, { 16 [ i32:78, i32:111, i32:116, i32:101, i32:80, i32:97, i32:100, i32:67, i32:111, i32:110, i32:116, i32:101, i32:110, i32:116, i32:49, i32:50, ]}
	sta v7
	sta v6
	newobjrange 0x2, 0x2, v5
	sta v5
	lda v5
	stlexvar 0x0, 0x0
	tryldglobalbyname 0x4, "Uint8Array"
	sta v5
	createarraywithbuffer 0x5, { 12 [ i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, ]}
	sta v7
	sta v6
	newobjrange 0x6, 0x2, v5
	sta v5
	lda v5
	stlexvar 0x0, 0x1
	ldhole
	sta v7
	defineclasswithbuffer 0x8, &entry.src.main.ets.utils.CryptoUtils&.#~@0=#CryptoUtils:(any,any,any), { 31 [ string:"chacha20Encrypt", method:#~@0>#chacha20Encrypt, method_affiliate:1, string:"chacha20Decrypt", method:#~@0>#chacha20Decrypt, method_affiliate:1, string:"initializeState", method:#~@0>#initializeState, method_affiliate:0, string:"generateKeyStream", method:#~@0>#generateKeyStream, method_affiliate:1, string:"quarterRound", method:#~@0>#quarterRound, method_affiliate:5, string:"rotateLeft", method:#~@0>#rotateLeft, method_affiliate:2, string:"base64Encode", method:#~@0>#base64Encode, method_affiliate:1, string:"base64Decode", method:#~@0>#base64Decode, method_affiliate:1, string:"encrypt", method:#~@0>#encrypt, method_affiliate:1, string:"decrypt", method:#~@0>#decrypt, method_affiliate:1, i32:10, ]}, 0x0, v7
	sta v5
	sta v6
	lda v5
	ldobjbyname 0x9, "prototype"
	sta v8
	lda v5
	sta v3
	lda v3
	sta v5
	newobjrange 0xb, 0x1, v5
	stmodulevar 0x0
	ldundefined
	returnundefined
}

CryptoUtils.func_main_0 函数解析

这个函数是 CryptoUtils 模块的主初始化函数,主要负责配置加密相关的密钥、初始化类定义,并注册加密/解密方法。以下是详细解释:

函数签名与基本结构

.function any &entry.src.main.ets.utils.CryptoUtils&.func_main_0(any a0, any a1, any a2) <static> {
    // 函数主体...
}
  • 作用​:作为模块的入口函数,在模块加载时执行初始化操作。
  • 参数​:接收三个任意类型参数(a0, a1, a2),但实际未在函数内使用。
  • 静态属性​:通过 <static> 标识为静态函数,无需实例化即可调用。

词法环境与变量初始化

newlexenvwithname 0x3, { 7 [ i32:3, string:"CHACHA_KEY", i32:0, string:"CHACHA_IV", i32:1, string:"DOMAIN_CRYPTO", i32:2, ]}
mov v0, a0
mov v1, a1
mov v2, a2
ldai 0x3
sta v5
lda v5
stlexvar 0x0, 0x2
  • 词法环境创建​:定义了一个名为 0x3 的词法环境,包含三个键值对:
    • CHACHA_KEY(索引0):ChaCha20加密算法的密钥
    • CHACHA_IV(索引1):ChaCha20算法的初始化向量(IV)
    • DOMAIN_CRYPTO(索引2):加密模块的域标识
  • 变量操作​:将数值 3 存入变量 v5,并存储到词法环境的索引 0x2 位置。

加密密钥与IV的初始化

tryldglobalbyname 0x0, "Uint8Array"
sta v5
createarraywithbuffer 0x1, { 16 [ i32:78, i32:111, i32:116, i32:101, i32:80, i32:97, i32:100, i32:67, i32:111, i32:110, i32:116, i32:101, i32:110, i32:116, i32:49, i32:50, ]}
sta v7
sta v6
newobjrange 0x2, 0x2, v5
sta v5
lda v5
stlexvar 0x0, 0x0

tryldglobalbyname 0x4, "Uint8Array"
sta v5
createarraywithbuffer 0x5, { 12 [ i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, i32:0, ]}
sta v7
sta v6
newobjrange 0x6, 0x2, v5
sta v5
lda v5
stlexvar 0x0, 0x1
  • ​**ChaCha20密钥(CHACHA_KEY)**​:
    • 创建一个16字节的 Uint8Array,字节值对应ASCII字符 NotePadContent12(十进制数值转换见下方)。
    • 该密钥用于ChaCha20算法的加密/解密过程。
  • ​**初始化向量(CHACHA_IV)**​:
    • 创建一个12字节的 Uint8Array,初始值全为0。
    • IV用于确保相同密钥加密不同数据时的随机性,避免密文重复。

CryptoUtils类的定义与方法注册

ldhole
sta v7
defineclasswithbuffer 0x8, &entry.src.main.ets.utils.CryptoUtils&.#~@0=#CryptoUtils:(any,any,any), { 31 [ 
    string:"chacha20Encrypt", method:#~@0>#chacha20Encrypt, method_affiliate:1,
    string:"chacha20Decrypt", method:#~@0>#chacha20Decrypt, method_affiliate:1,
    string:"initializeState", method:#~@0>#initializeState, method_affiliate:0,
    string:"generateKeyStream", method:#~@0>#generateKeyStream, method_affiliate:1,
    string:"quarterRound", method:#~@0>#quarterRound, method_affiliate:5,
    string:"rotateLeft", method:#~@0>#rotateLeft, method_affiliate:2,
    string:"base64Encode", method:#~@0>#base64Encode, method_affiliate:1,
    string:"base64Decode", method:#~@0>#base64Decode, method_affiliate:1,
    string:"encrypt", method:#~@0>#encrypt, method_affiliate:1,
    string:"decrypt", method:#~@0>#decrypt, method_affiliate:1,
    i32:10
]}, 0x0, v7
  • 类定义​:创建 CryptoUtils 类,包含以下核心功能方法:
    1. ChaCha20加解密​:chacha20Encryptchacha20Decrypt
    2. 状态初始化​:initializeState(设置ChaCha20初始状态矩阵)
    3. 密钥流生成​:generateKeyStream(生成加密用密钥流)
    4. 核心轮函数​:quarterRound(ChaCha20的单轮混淆运算)
    5. 位运算​:rotateLeft(左旋转位移操作)
    6. Base64编解码​:base64Encodebase64Decode
    7. 高层加解密接口​:encryptdecrypt(封装ChaCha20流程)
  • 方法附属标识​:method_affiliate 表示方法类型(如1为实例方法,0为静态方法)。

模块导出与返回

lda v5
ldobjbyname 0x9, "prototype"
sta v8
lda v5
sta v3
lda v3
sta v5
newobjrange 0xb, 0x1, v5
stmodulevar 0x0
ldundefined
returnundefined
  • 原型链设置​:将类的原型对象赋值给 prototype 属性,确保实例可继承方法。
  • 模块导出​:通过 stmodulevarCryptoUtils 类导出为模块的默认导出对象。
  • 返回值​:函数最终返回 undefined,表示初始化完成。

函数核心功能

  1. 密钥与IV配置​:设置ChaCha20算法的加密密钥和初始化向量。
  2. 类定义​:创建 CryptoUtils 类并注册加密相关方法。
  3. 模块初始化​:将类导出为模块的公共接口,供其他模块调用。

该函数是整个加密模块的入口,确保ChaCha20算法的各个组件正确初始化,为笔记内容的加密/解密提供基础支持。