京麒CTF2024-WP-Re

re1-babyharmony

鸿蒙HarmonyOS逆向

找到的工具:HapViewer 发行版 - Gitee.com

完全不知道鸿蒙os如何逆向QAQ
那就按安卓的方法来逆但是没有工具!!!
.apk其实可以按zip的格式打开看见拥有源码的.dex文件,那么.hap是不是也可以这样!

百度一些.abc文件发现啥也没有资料QAQ,直接用txt打开发现居然有源码在里面!!

发现需要用utf-8可以解决部分中文乱码!

提取出主要的代码:

    constructor(parent, params, __localStorage, elmtId = -1) {
        super(parent, __localStorage, elmtId);
        this.context = getContext(this);
        this.__message = new ObservedPropertySimplePU('请输入flag', this, "message");
        this.__button_name = new ObservedPropertySimplePU('提交', this, "button_name");
        this.__flag = new ObservedPropertySimplePU('', this, "flag");
        this.__result = new ObservedPropertySimplePU('', this, "result");
        this.dialogController = new CustomDialogController({
            builder: () => {
                let jsDialog = new CustomDialogExample(this, {
                    textValue: this.__result,
                });
                jsDialog.setController(this.dialogController);
                ViewPU.create(jsDialog);
            }
        }, this);
        this.setInitiallyProvidedValue(params);
    }

这段代码初始化了一个flag提交框!!!

        this.observeComponentCreation((elmtId, isInitialRender) => {
            ViewStackProcessor.StartGetAccessRecordingFor(elmtId);
            Button.createWithLabel(this.button_name);
            Button.onClick(() => {
                this.context.resourceManager.getRawFileContent("bin").then((value) => {
                    var c = testNapi.check(this.flag, value);
                    if ((c & 0b100) === 0b100) {
                        this.result = '系统环境异常';
                    }
                    else if ((c & 0b10) === 0b10) {
                        this.result = 'flag格式错误';
                    }
                    else if ((c & 0b1) === 0b1) {
                        this.result = 'flag错误或系统环境异常';
                    }
                    else {
                        this.result = 'flag正确';
                    }
                    this.dialogController.open();
                });
            });
            if (!isInitialRender) {
                Button.pop();
            }
            ViewStackProcessor.StopGetAccessRecording();
        });

在txt里面找到了判断flag的按钮!!var c = testNapi.check(this.flag, value);
发现这里就有check函数可以判断flag!
但是找不到testNapi.check方法百度一下!
发现testNapi其实就类似于安卓的Native方法:16.7:NAPI 加载原理(上) | 《ArkUI实战》
百度查一下发现方法是写在libentry.so文件里!

拖入ida直接搜索字符串找到了方法!!!
发现这个check方法是在so文件里的!

找到check方法!!

发现这个调用的原理是使用使用ArkTs调用so方法QAQ,我去问chatgpt他说是js调用so方法差点肝死我了!
js调用so方法:node-ffi-napi/node-ffi-napi:用于 Node.js N-API 样式的外部函数接口 (FFI)

// example.js
const ffi = require('ffi-napi'); // 使用 ffi-napi 模块来加载 SO 文件

// 加载 example.so 文件
const example = ffi.Library('./libentry.so', {
  'add': ['int', ['int', 'int']] // 定义 SO 文件中的 add 函数
});

// 暴露一个函数给 JavaScript 使用
function add(a, b) {
  return example.add(a, b);
}

module.exports = { add };
// main.js
const { add } = require('./example');

// 调用封装的 add 函数
const result = add(2, 3);
console.log(result); // 输出 5

去配了js的的ffi-napi库再去调用这个so文件的check方法发现报错:

然后继续百度才发现它用的是ArkTs调用so方法!!!
那继续肝,去下载一个鸿蒙开发环境:

  1. DevEco Studio-HarmonyOS SDK下载和升级-华为开发者联盟 (huawei.com)
  2. 华为官方:手把手教你使用鸿蒙 HarmonyOS 本地模拟器 - IT之家 (ithome.com)
  3. 鸿蒙手机版JNI实战(JNI开发、SO库生成、SO库使用) - 齐行超 - 博客园 (cnblogs.com)
    成功了!!!

    打开模拟器!成功剩下的就是分析so文件的具体调用了!!!

知识链接:
DevEco Studio-HarmonyOS SDK下载和升级-华为开发者联盟 (huawei.com)
华为官方:手把手教你使用鸿蒙 HarmonyOS 本地模拟器 - IT之家 (ithome.com)
手把手教你使用HarmonyOS本地模拟器 (qq.com)手把手教你使用HarmonyOS本地模拟器_harmonyos怎么本地模拟器-CSDN博客
鸿蒙 hap apk,逆向分析第一个鸿蒙OS应用-CSDN博客
华为hap安装包逆向记录 - LY 的博客 (young-lord.github.io)
[下载][原创]鸿蒙APP逆向分析-HarmonyOS-看雪-安全社区|安全招聘|kanxue.com
硬核教程:OpenHarmony和鸿蒙hap包逆向解析应用名称~_哔哩哔哩_bilibili
hap查看器的实现原理以及逆向解析应用名的初步方案 - 文章 OpenHarmony开发者论坛

安装js的ffi-napi库在kali上根本装不了一点!!!
nodejs动态调试:

re4-easy-wasm

WebAssembly分析和调试技巧
浏览器本地服务器搭建

提示:
找到注册的加密函数->主动调用->逐字节爆破密文

这道题题的分析过程:
先把网站映射到本地端口:

python -m http.server 8888

这样就可以用浏览器来进行调试了!
浏览器访问:127.0.0.1:8888 就可以访问这个页面并且进行调试了!

成功获得flag:

当然这样是不够的要去看代码QAQ

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<script src="static/wasm_exec.js"></script>
<script>
    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("static/main.wasm"), go.importObject)
        .then((result) => go.run(result.instance));

    function check_flag() {
        var flag = document.getElementById("flag").value;
        console.log("你输入的 flag 是:");
        console.log(flag);
        if (document.getElementById("flag").value === "flag{this_1s_fake_f_l_A__g}") {
            console.log("I have a gift for you!");
            console.log(console.gift("ABCCDDEE", "AABBCCDDEE"));
            alert("恭喜你,答对了!我想你应该知道 flag 是什么了 !");
        } else {
            alert("答错了,再想想吧!");
        }
    }
</script>

<body>
    <input id="flag" type="text" />
    <button id="btn" onclick="check_flag();" >Click</button>
</body>
</html>

分析发现这里的check_flag是假的,flag不在这里!!

继续分析发现了:

    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("static/main.wasm"), go.importObject)
        .then((result) => go.run(result.instance));

解释一下代码:

fetch("static/main.wasm")
  • fetch 函数从指定的 URL ("static/main.wasm") 获取 WebAssembly 文件
  • fetch 返回一个 Promise,它解析为响应对象(Response)。
WebAssembly.instantiateStreaming(fetch("static/main.wasm"), go.importObject)
  • WebAssembly.instantiateStreaming 是一个高效的加载和编译 WebAssembly 模块的方法。
  • 它接收两个参数:
    • 第一个参数是 Response 对象,这里通过 fetch("static/main.wasm") 获得。
    • 第二个参数是导入对象(go.importObject),它包含 WebAssembly 实例需要的导入值。
  • instantiateStreaming 返回一个 Promise,解析为一个包含已编译 WebAssembly 模块的对象。
.then((result) => go.run(result.instance));
  • then 方法注册一个回调函数,该函数在 Promise 解析时执行。
  • 回调函数接收一个 result 对象,该对象包含已实例化的 WebAssembly 模块实例(result.instance)。
  • 调用 go.run(result.instance) 运行 WebAssembly 模块。

然后就可以去浏览器看看具体的wasm代码了!按f12
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

调试的时候会发现存在无限debugger QAQ
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
我绕不过去!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值