unidbg hook inline hook 使用

android 逆向 11 / 37

const 龙哥 = Function() {}

const a = 全能的傻宝,每天都会换一种姿势来分享各种操作,最近 10 月在分享密码学;
const b = 点击加入星球;
return "无敌的龙哥";

前言

unidbg 是个非常好用的工具,可以模拟手机运行环境执行 so 文件,同时也非常适合算法还原
得益于它强大的 hook debugger 功能,我们今天的主角是 hook,简单介绍使用一下
想学习 unidbg 的小伙伴,可以 call 龙哥 ();

demo

这篇文章的样本是 搜狗搜索 app,不了解的同学,可以参考一下文章
sougou搜索 app weixin公众号文章列表 so 加解密算法分析还原 | 简单分析

推荐阅读

unidbg console debugger 使用 推荐先阅读此文章对样本有个大概的了解

start

0x1

使用 IHookZz hook 一下此函数,看看参数跟返回值

public void hookSCEncryptWallEncode() {
    // 获取 HookZz 对象
    IHookZz hookZz = HookZz.getInstance(emulator);
    // enable hook
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.base + 0xA284 + 1, new WrapCallback<RegisterContext>() {
        Pointer buffer;

        @Override
        public void preCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {
            System.out.println("HookZz hook Sc_EncryptWallEncode");
            Pointer input1 = ctx.getPointerArg(0);
            Pointer input2 = ctx.getPointerArg(1);
            Pointer input3 = ctx.getPointerArg(2);
            // getString 的参数 i 代表 index, 即 input[i:]
            System.out.println("参数1:" + input1.getString(0));
            System.out.println("参数2:" + input2.getString(0));
            System.out.println("参数3:" + input3.getString(0));
            // 先保存 参数四的 内存地址
            buffer = ctx.getPointerArg(3);
        }

        @Override
        public void postCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {
            // getByteArray 参数1是起始index,参数2是长度,我们不知道结果多长,就先设置0x100吧
            byte[] outputhex = buffer.getByteArray(0, 0x100);
            Inspector.inspect(outputhex, " Sc_EncryptWallEncode output");
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}

代码跑起来

参数 123 刚好是我们传进去的

参数 4 是个 buffer 返回的数据存到了这个地址里面,函数执行完后,直接取出来即可

0x2

使用 IHookZz 的 inline hook 一下此函数,看看参数跟返回值

public void inlineHookSCEncryptWallEncode() {
    // 查看 Sc_EncryptWallEncode 执行前后 buffer 变化
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.instrument(module.base + 0x9D24 + 1, new InstrumentCallback<Arm32RegisterContext>() {
        @Override
        public void dbiCall(Emulator<?> emulator, Arm32RegisterContext ctx, HookEntryInfo info) {
            System.out.println("HookZz inline hook Sc_EncryptWallEncode");
            Pointer input1 = ctx.getPointerArg(0);
            Pointer input2 = ctx.getPointerArg(1);
            Pointer input3 = ctx.getPointerArg(2);
            // getString 的参数 i 代表 index, 即 input[i:]
            System.out.println("参数1:" + input1.getString(0));
            System.out.println("参数2:" + input2.getString(0));
            System.out.println("参数3:" + input3.getString(0));
            buffer = ctx.getPointerArg(3);
        }
    });
    hookZz.instrument(module.base + 0x9d28 + 1, new InstrumentCallback<Arm32RegisterContext>() {
        @Override
        public void dbiCall(Emulator<?> emulator, Arm32RegisterContext ctx, HookEntryInfo info) {
            Inspector.inspect(buffer.getByteArray(0, 0x100), " inline hook Sc_EncryptWallEncode");
        }
    });
}

执行代码结果都是一样的

在有些时候,一个函数可能会运行,但我们只想查看当前的运行情况,这时可能会使用到 inline hook需要注意,inline hook 的时机是目标指令执行前

0x3

使用 unicorn inline hook

public void hookUnicornBase64Encode() {
    // 使用 unicorn 进行 hook
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void onAttach(Unicorn.UnHook unHook) {
        }

        @Override
        public void detach() {
        }

        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xB372)) {
                System.out.println("Hook By Unicorn Base64Encode");
                RegisterContext ctx = emulator.getContext();
                Pointer input1 = ctx.getPointerArg(0);
                Inspector.inspect(input1.getByteArray(0, 0x100), " 参数1");
            }
            if (address == (module.base + 0xB376)) {
                RegisterContext ctx = emulator.getContext();
                Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook Base64Encode");
            }
        }
    }, module.base + 0xB372, module.base + 0xB376, null);
}

代码里是 hook Base64Encode 的执行前跟执行后,分别打印输入跟输出

结果也全部出来了,参数一就是上面 rsa 的加密结果,在使用 base64Encode

暂无评论
本文作者:
本文链接: https://www.qinless.com/?p=472
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

发表评论

返回顶部