程序分析
反编译工具地址:https://github.com/ohos-decompiler/abc-decompiler
1、分析鸿蒙手机检材中“笔记.hap”文件,该软件应用名称是?【标准格式:ABCD】
PGSDBW
软件应用名称在 module.json 文件中通过 label 和 labelId 进行标识。label 的值为 $string:app_name,这表明应用名称是一个字符串资源引用,实际的名称存储在字符串资源文件中,labelId 为 16777216 也用于标识该字符串资源。

2、分析hap检材,软件的包名是?【标准格式:com.pgs.main】
com.example.pgsdsj
在 app 配置部分有关于包名的信息,具体如下:

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"}}

文件名称: 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获取)。 - 表结构字段:
id:整数类型,主键,自动递增title:文本类型,存储笔记标题content:文本类型,非空,存储加密后的笔记内容(注释明确标注为加密内容)created_at:整数类型,默认值为当前时间戳(通过strftime('%s', 'now')获取)updated_at:整数类型,默认值为当前时间戳,记录更新时间
- 加密说明:
content字段明确注释为Encrypted content,表明该字段存储的是经过加密处理的笔记内容,与前文定义的加密密钥配合使用。
数据库初始化核心逻辑
- 基础配置:定义数据库名称、存储路径和表名,确保数据持久化存储。
- 加密支持:定义ChaCha20算法的加密密钥,为
content字段的加密提供基础。 - 表结构设计:创建包含加密内容字段的笔记表,自动记录创建和更新时间,保证数据完整性。
这段代码是数据库模块的基础,后续的数据库操作(如插入、查询、更新)均基于此表结构和加密配置展开。
9、分析hap检材,数据库中笔记内容采用什么加密算法?【标准格式:Sal20】
ChaCha20
在txt中可以明确看到数据库中笔记内容的加密算法相关信息:
在CryptoUtils模块中,存在多个与ChaCha20加密相关的方法定义,如:
chacha20Encrypt:ChaCha20加密方法chacha20Decrypt:ChaCha20解密方法
此外,在数据库操作insertNote中,明确使用了encryptedContent字段存储加密后的内容,且加密逻辑通过CryptoUtils的encrypt方法实现,该方法内部调用了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算法的加密/解密过程。
- 创建一个16字节的
- **初始化向量(CHACHA_IV)**:
- 创建一个12字节的
Uint8Array,初始值全为0。 - IV用于确保相同密钥加密不同数据时的随机性,避免密文重复。
- 创建一个12字节的
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类,包含以下核心功能方法:- ChaCha20加解密:
chacha20Encrypt和chacha20Decrypt - 状态初始化:
initializeState(设置ChaCha20初始状态矩阵) - 密钥流生成:
generateKeyStream(生成加密用密钥流) - 核心轮函数:
quarterRound(ChaCha20的单轮混淆运算) - 位运算:
rotateLeft(左旋转位移操作) - Base64编解码:
base64Encode和base64Decode - 高层加解密接口:
encrypt和decrypt(封装ChaCha20流程)
- 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属性,确保实例可继承方法。 - 模块导出:通过
stmodulevar将CryptoUtils类导出为模块的默认导出对象。 - 返回值:函数最终返回
undefined,表示初始化完成。
函数核心功能
- 密钥与IV配置:设置ChaCha20算法的加密密钥和初始化向量。
- 类定义:创建
CryptoUtils类并注册加密相关方法。 - 模块初始化:将类导出为模块的公共接口,供其他模块调用。
该函数是整个加密模块的入口,确保ChaCha20算法的各个组件正确初始化,为笔记内容的加密/解密提供基础支持。