Skip to main content

程序分析

2025-06-11


image-20250611190310271

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

PGSDSW

将.hap改成.zip解压,查看module.json文件,看到"label": "$string:app_name",现在寻找$string:app_name中的app_name字段,通常是在resources/base/strings/zh-CN/string.json中,由于没有这个文件,因此爆搜一下

image-20250611191649334

在resources.index中找到,并且能看到PGSDSW app_name,用https://github.com/Yricky/abcde解析一下

java.exe -jar .\kra-ui-linux-x64-0.1.0-main-1207df8-release.jar --cli --dump-index .\resources.index --out=out.json

{
"16777216": [
{
"type": "STRING",
"param": "base",
"name": "app_name",
"data": "PGSDBW"
}
],
"16777217": [
{
"type": "MEDIA",
"param": "base",
"name": "background",
"data": "entry/resources/base/media/background.png"
}
],
"16777218": [
{
"type": "MEDIA",
"param": "base",
"name": "foreground",
"data": "entry/resources/base/media/foreground.png"
}
],
"16777219": [
{
"type": "MEDIA",
"param": "base",
"name": "layered_image",
"data": "entry/resources/base/media/layered_image.json"
}
],
"16777220": [
{
"type": "STRING",
"param": "base",
"name": "EntryAbility_desc",
"data": "description"
}
],
"16777221": [
{
"type": "STRING",
"param": "base",
"name": "EntryAbility_label",
"data": "PGSDBW"
}
],
"16777222": [
{
"type": "STRING",
"param": "base",
"name": "module_desc",
"data": "module description"
}
],
"16777223": [
{
"type": "COLOR",
"param": "base",
"name": "start_window_background",
"data": "#FFFFFF"
},
{
"type": "COLOR",
"param": "dark",
"name": "start_window_background",
"data": "#000000"
}
],
"16777224": [
{
"type": "FLOAT",
"param": "base",
"name": "page_text_font_size",
"data": "50fp"
}
],
"16777225": [
{
"type": "MEDIA",
"param": "base",
"name": "startIcon",
"data": "entry/resources/base/media/startIcon.png"
}
],
"16777226": [
{
"type": "PROF",
"param": "base",
"name": "backup_config",
"data": "entry/resources/base/profile/backup_config.json"
}
],
"16777227": [
{
"type": "PROF",
"param": "base",
"name": "main_pages",
"data": "entry/resources/base/profile/main_pages.json"
}
]
}

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

com.example.pgsdsj

module.json中能看到包名是com.example.pgsdsj

还有其他信息:

版本名称1.0.0

编译环境:HarmonyOS 5.0.5.160

构建模式:debug

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

448b23

第一题查看module.json之后可以确定"icon": "$media:foreground"

然后又由resources.index解析出entry/resources/base/media/foreground.png

因此找到resources/base/media/foreground.png

计算得到448b23

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

modules.abc

hap的代码保存在.abc文件中,因此是modules.abc

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

EntryAbility

在module.json中搜索mainElement,找到"mainElement":"EntryAbility"

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

pgsdbw-2025

比赛的时候可以爆搜,就能搜到只有pgsdbw-2025符合这个格式

那个abcde不好用,用另一个软件jadx-dev-all,将abc拖进去后,找到entry/src/main/ets/pages,看到

    public Object #~@0=#LoginPage(Object functionObject, Object newTarget, LoginPage this, Object arg0, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
obj = arg3;
obj2 = arg4;
if ((0 == obj ? 1 : 0) != 0) {
obj = -1;
}
if ((0 == obj2 ? 1 : 0) != 0) {
obj2 = null;
}
obj3 = super(arg0, arg2, obj, arg5);
if (("function" == typeof(obj2) ? 1 : 0) != 0) {
obj3.paramsGenerator_ = obj2;
}
obj3.__passwordInput = ObservedPropertySimplePU("", obj3, "passwordInput");
obj3.__errorMessage = ObservedPropertySimplePU("", obj3, "errorMessage");
obj3.FIXED_PASSWORD = "pgsdbw-2025";
obj3.uiAbilityContext = 0;
obj3.setInitiallyProvidedValue(arg1);
obj3.finalizeConstruction();
return obj3;
}

同时在#~@0>#handleLogin函数中发现

asyncfunctionenter = (this.FIXED_PASSWORD == this.passwordInput ? 1 : 0);
……
suspendgenerator(asyncfunctionenter, asyncfunctionawaituncaught(asyncfunctionenter, router.pushUrl(createobjectwithbuffer(["url", "pages/NotepadPage"]))));

因此判断出该密码输入正确后才跳转到笔记界面,该密码就是软件入口的密码

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

notepad.db

查看DatabaseHelper类,发现_lexenv_0_1_ = "notepad.db";给数据库文件名变量赋值

然后又obj2.name = _lexenv_0_1_;

最后又relationalStore.getRdbStore(this.UIAContext, obj2)

因此答案为notepad.db

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

HuaweiNotePad123

在看NotepadPage类和DatabaseHelper类的时候,发现DatabaseHelper类的func_main_0函数

public Object func_main_0(Object functionObject, Object newTarget, DatabaseHelper this) {
newlexenvwithname([4, "DOMAIN_DB", 0, "DB_NAME", 1, "SQL_CREATE_NOTES_TABLE", 2, "SQL_CREATE_NOTES_UPDATE_TRIGGER", 3], 4);
_lexenv_0_1_ = "notepad.db";
_module_1_ = "notes";
_lexenv_0_0_ = 2;
Uint8Array(createarraywithbuffer([72, 117, 97, 119, 101, 105, 78, 111, 116, 101, 80, 97, 100, 49, 50, 51]));
_lexenv_0_2_ = ("CREATE TABLE IF NOT EXISTS " + _module_1_ + " (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT,\n content TEXT NOT NULL, -- Encrypted content\n created_at INTEGER DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER DEFAULT (strftime('%s', 'now'))\n);");
_lexenv_0_3_ = ("\nCREATE TRIGGER IF NOT EXISTS update_notes_updated_at\nAFTER UPDATE ON " + _module_1_ + "\nFOR EACH ROW\nBEGIN\n UPDATE " + _module_1_ + " SET updated_at = strftime('%s', 'now') WHERE id = OLD.id;\nEND;");
r18 = hole.#~@0=#DatabaseHelper(Object2, Object3, hole, ["initialize", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#initialize", 1, "getRdbStore", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#getRdbStore", 0, "initializeDatabaseTables", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#initializeDatabaseTables", 1, "insertNote", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#insertNote", 1, "getAllNotesRaw", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#getAllNotesRaw", 0, "getNoteByIdRaw", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#getNoteByIdRaw", 1, "updateNoteContent", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#updateNoteContent", 3, "deleteNoteById", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#deleteNoteById", 1, "closeRdbStore", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#closeRdbStore", 0, "backupDatabase", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#backupDatabase", 0, "restoreDatabase", "&entry/src/main/ets/utils/DatabaseHelper&.#~@0>#restoreDatabase", 0, 11]);
obj = r18.prototype;
_module_0_ = r18();
return null;
}

连接数据库notepad.db,配置数据库表名notes,接着构建了一个字节数组,转换后是HuaweiNotePad123

接着往后看,在看到#~@0>#getRdbStore函数的时候,注意到obj2 = createobjectwithbuffer(["name", 0, "securityLevel", 0, "encrypt", 1]);,确定数据库是加密的。接着看到这句Database encryption will be applied using the predefined key,翻译过来是将使用预定义密钥应用数据库加密,找了一圈就只有这个了。

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

chacha20

在CryptoUtil类中,能看到加密是用的chacha20Encrypt

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

NotePadContent12

在CryptoUtil类的func_main_0函数中,看到

    public Object func_main_0(Object functionObject, Object newTarget, CryptoUtils this) {
newlexenvwithname([3, "CHACHA_KEY", 0, "CHACHA_IV", 1, "DOMAIN_CRYPTO", 2], 3);
_lexenv_0_2_ = 3;
_lexenv_0_0_ = Uint8Array(createarraywithbuffer([78, 111, 116, 101, 80, 97, 100, 67, 111, 110, 116, 101, 110, 116, 49, 50]));
_lexenv_0_1_ = Uint8Array(createarraywithbuffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
r12 = hole.#~@0=#CryptoUtils(Object2, Object3, hole, ["chacha20Encrypt", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#chacha20Encrypt", 1, "chacha20Decrypt", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#chacha20Decrypt", 1, "initializeState", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#initializeState", 0, "generateKeyStream", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#generateKeyStream", 1, "quarterRound", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#quarterRound", 5, "rotateLeft", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#rotateLeft", 2, "base64Encode", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#base64Encode", 1, "base64Decode", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#base64Decode", 1, "encrypt", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#encrypt", 1, "decrypt", "&entry/src/main/ets/utils/CryptoUtils&.#~@0>#decrypt", 1, 10]);
obj = r12.prototype;
_module_0_ = r12();
return null;
}

然后对于chach20,State[4~11]是key

#~@0>#initializeState写到

public Object #~@0>#initializeState(Object functionObject, Object newTarget, CryptoUtils this) {
newobjrange = Uint32Array(16);
newobjrange[0] = 1634760805;
newobjrange[1] = 857760878;
newobjrange[2] = 2036477234;
newobjrange[3] = 1797285236;
for (i = 0; (i < 8 ? 1 : 0) != 0; i = tonumer(i) + 1) {
newobjrange[4 + i] = (_lexenv_0_0_[i * 4] << 24) | (_lexenv_0_0_[(i * 4) + 1] << 16) | (_lexenv_0_0_[(i * 4) + 2] << 8) | _lexenv_0_0_[(i * 4) + 3];
}
newobjrange[12] = 0;
newobjrange[13] = 0;
for (i2 = 0; (i2 < 3 ? 1 : 0) != 0; i2 = tonumer(i2) + 1) {
newobjrange[14 + i2] = (_lexenv_0_1_[i2 * 4] << 24) | (_lexenv_0_1_[(i2 * 4) + 1] << 16) | (_lexenv_0_1_[(i2 * 4) + 2] << 8) | _lexenv_0_1_[(i2 * 4) + 3];
}
return newobjrange;
}

因此_lexenv_0_0_就是key,即[78, 111, 116, 101, 80, 97, 100, 67, 111, 110, 116, 101, 110, 116, 49, 50],得到NotePadContent12