OpenHarmony开发者论坛

标题: hap查看器的实现原理以及逆向解析应用名的初步方案 [打印本页]

作者: westinyang    时间: 2023-10-28 10:25
标题: hap查看器的实现原理以及逆向解析应用名的初步方案
[md]前段时间,我开发了一个开源的跨平台的hap查看器,支持win、mac、linux,可以解析查看API9+ Stage模型的应用,后续还做了一个android版的(开源地址和软件截图见文章底部)。那今天我们来讲一下核心功能的具体实现原理,以及逆向解析应用名的初步方案是如何形成的。

# 解析应用基本信息

这点实现起来并不困难,因为hap解压后有一个名为 `module.json` 的明文的描述文件,这里包含了应用的基本信息,我们只需要通过程序读取并解析json读取需要的值即可,下面给出一些java代码片段

```java
HapInfo hapInfo = new HapInfo();
ZipFile zipFile = null;
try {
    hapInfo.hapFilePath = hapFilePath;
    zipFile = new ZipFile(hapFilePath);
    // 读取module.json
    JSONObject module = getEntryToJsonObject(zipFile, "module.json");

    // app.
    hapInfo.packageName = module.getByPath("app.bundleName", String.class);
    hapInfo.versionName = module.getByPath("app.versionName", String.class);
    hapInfo.versionCode = module.getByPath("app.versionCode", String.class);
    hapInfo.vendor = module.getByPath("app.vendor", String.class);
    hapInfo.minAPIVersion = module.getByPath("app.minAPIVersion", String.class);
    hapInfo.targetAPIVersion = module.getByPath("app.targetAPIVersion", String.class);
    hapInfo.apiReleaseType = module.getByPath("app.apiReleaseType", String.class);
} catch (Exception e) {
    e.printStackTrace();
    throw new RuntimeException("HAP file parse failed");
} finally {
    IoUtil.close(zipFile);
}
```

# 解析应用图标

我们需要先遍历`module.abilities`下所有的Ability信息,优先去找与`启动AbilityName`一致的Ability信息,如果找不到默认取第一个,然后再解析子属性中的`icon`的相对路径值,前面拼上 `resources/base/media/`,后面拼上 `.png`就是完整的图标路径了,然后根据此路径读取并加载图片即可。

```java
// module.
hapInfo.mainElement = module.getByPath("module.mainElement", String.class);

// 解析图标
JSONArray moduleAbilities = module.getByPath("module.abilities", JSONArray.class);
JSONObject targetAbility = null;
try {
    targetAbility = (JSONObject) moduleAbilities.get(0);
} catch (Exception ignore) {}
for (Object item : moduleAbilities) {
    JSONObject ability = (JSONObject) item;
    if (hapInfo.mainElement.equals(ability.get("name", String.class))) {
        targetAbility = ability;
        break;
    }
}
if (targetAbility != null) {
    String iconName = targetAbility.get("icon", String.class).split(":")[1];
    String iconPath = String.format("resources/base/media/%s.png", iconName);
    hapInfo.iconPath = iconPath;
    hapInfo.iconBytes = getEntryToBytes(zipFile, iconPath);
    hapInfo.icon = getEntryToImage(zipFile, iconPath);
}
```

# 解析应用名

> 视频讲解:https://www.bilibili.com/video/BV1jk4y1L7m3

- 由于应用名实际的值并不在json描述中,而是被编译构建打包到了 `resources.index` 文件中。
- 每一个hap安装包内都有一个名为 `resources.index` 的文件,这个就是应用工程里面所有资源文件最终打包的产物,是用一个名为 [restool](https://gitee.com/openharmony/developtools_global_resource_tool) 的开源工具进行构建的,同时 `restool` 其实就在sdk安装目录下的toolchains子目录中。
- 关键是这个并不像分析安卓的apk,有成熟的 `apktool` 等逆向工具能快速准确地反编译看到明文的资源文件
- 思来想去,还是先看看有没有什么粗糙的方法先把它读出来吧
- 我们使用 `010Editor` 分别打开几个应用内的 `resources.index` 文件,在 `十六进制视图` 下做一些分析和对比,尝试寻找有是否有一定的规律
- 最终得出了一个不是特别完善的初步解决方案,请参考下面的一些分析对照和代码片段

```java
// 特征分析(??????代表应用名称)
00 2C 00 00 00 09 00 00 00 03 00 00 01 0D 00 ?????? 00 13 00 // 设备信息
00 24 00 00 00 09 00 00 00 03 00 00 01 05 00 ?????? 00 13 00 // F-OH
00 28 00 00 00 09 00 00 00 03 00 00 01 10 00 ?????? 00 0C 00 // 搜狗输入法

// 关键特征
00 00 00 09 00 00 00 03 00 00 01

// 伪正则
00 ?? 00 00 00 09 00 00 00 03 00 00 01 ?? 00 ?????? 00 ?? 00

// 正则
(00.{2}0000000900000003000001.{2}00)(.*?)(00.{2}00)

// Java代码片段
byte[] resBytes = getEntryToBytes(zipFile, "resources.index");
String resHex = HexUtil.encodeHexStr(resBytes).toUpperCase();
String appNameHex = ReUtil.get("(00.{2}0000000900000003000001.{2}00)(.*?)(00.{2}00)", resHex, 2);
String appName = HexUtil.decodeHexStr(appNameHex);
```

- 使用这个正则表达式把分组中的第二部分取出来,再从十六进制内容转换为字符串,最终得到的就是我们想要的应用名
- 怎么说呢,这种方法算是另辟蹊径吧,弊端就是不可能适用于所有restool版本所编译构建的hap资源文件,即便是相同版本,也有可能会存在读取不够准确的情况
- 如果能根据开源的restool写出对应的资源反编译工具,才算是更好的解决方案~

# 开源地址和软件截图

## 电脑版(跨平台)

https://gitee.com/ohos-dev/hap-viewer

![](data/attachment/forum/202310/28/102206a8yn4wg5n04srvwr.png "all.png")

## 手机版(Android)

https://gitee.com/ohos-dev/hap-viewer-android

![](data/attachment/forum/202310/28/102428fi94iykzm3umdhky.png "all.png")

# 持续关注

- OHOS Dev:[https://gitee.com/ohos-dev](https://gitee.com/ohos-dev) `OpenHarmony开源项目组织,为OpenHarmony的未来而创建,Peace & Love`
- BiliBili:[https://space.bilibili.com/74433635](https://space.bilibili.com/74433635) `投稿OpenHarmony探索研究、应用开发和相关技术教程`
  

[/md]




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5