IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> unidbg第十三讲 unidbg实战 -> 正文阅读

[移动开发]unidbg第十三讲 unidbg实战

主要内容

1:使用unidbg 调用函数sub_13558

2:使用unidbg 里的IHookZz进行hook函数sub_13558,读取入参和出参

3:使用unidbg 里的IHookZz进行替换函数sub_13558里的参数

4:使用unidbg 里的IHookZz进行替换函数sub_13558的返回值

代码如下:

package com.unidbg2;


import com.github.unidbg.*;
import com.github.unidbg.android.MyTraceSystemMemoryWriteListener;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.arm.context.RegisterContext;
import com.github.unidbg.hook.HookContext;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.hookzz.*;
import com.github.unidbg.hook.whale.IWhale;
import com.github.unidbg.hook.whale.Whale;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.jni.ProxyClassFactory;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.MemoryBlock;
import com.github.unidbg.pointer.UnidbgPointer;
import com.sun.jna.Pointer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import unicorn.Arm64Const;
import unicorn.ArmConst;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * AbstractJni解决的问题:
 * 如果自己在apk写java代码调用so层函数,遇到so通过反射调用java层函数时,需要自己补上java层对应的类、方法和变量,因为这些需要执行的代码是绕不过去的!
 */
public class HookInUnidbgByConsoleDebuggerV2 extends AbstractJni   implements ModuleListener {
    private static final Log logger = LogFactory.getLog(HookInUnidbgByConsoleDebuggerV2.class);
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

   private  Memory memory;

    private static AndroidEmulator createARMEmulator() {
        return AndroidEmulatorBuilder.for64Bit()
                .setProcessName("hellojni_2.0.3")
              //  .addBackendFactory(new DynarmicFactory(true))
                .build();
    }
    HookInUnidbgByConsoleDebuggerV2() {
        // 创建模拟器实例,可以自定义模拟器,参考QDReaderJni
        //emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("hellojni_2.0.3").build();
        emulator = createARMEmulator();

        // 模拟器的内存操作接口
         memory = emulator.getMemory();
        // 设置系统类库解析
        AndroidResolver resolver = new AndroidResolver(23);
        memory.setLibraryResolver(resolver);// 设置系统类库解析
    // 重点:    实现ModuleListener接口后通过下面的代码,设置模块加载监听
        memory.addModuleListener(this);

        // 创建Android虚拟机
        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/unidbg/hellojni_2.0.3.apk"));
        vm.setDvmClassFactory(new ProxyClassFactory());
        // 设置是否打印Jni调用细节
        vm.setVerbose(true);
        vm.setJni(this);

        // 加载so到虚拟内存
        DalvikModule dm = vm.loadLibrary("hello-jni", false);
        // 加载好的 libhookinunidbg.so对应为一个模块
        module = dm.getModule();

        // 执行JNIOnLoad(如果有的话)
        dm.callJNI_OnLoad(emulator);
    }


    //    调用native方法
    public void callSign2(){
        DvmClass HelloJni = vm.resolveClass("com/example/hellojni/HelloJni");
//        参考文档:https://blog.csdn.net/xubaoyong/article/details/121752455
//        public native String sign2(String str, String str2);
        String sign2 = "sign2(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;";

        DvmObject<?> dvmObject = HelloJni.newObject(null);

        String arg0 = "1234567890";
        String arg1 = "abcdefghigklmnopqrstuvwxyz";
        DvmObject result = dvmObject.callJniMethodObject(emulator, sign2,arg0,arg1);

        logger.info("call 入参:arg0="+arg0+",arg1="+arg1+",返回值是:"+result.getValue());
    }
//
    public void hookLibc(){
        IWhale whale = Whale.getInstance(emulator);
        Symbol strlen = emulator.getMemory().findModule("libc.so").findSymbolByName("strlen");
        whale.inlineHookFunction(strlen, new ReplaceCallback() {
            @Override
            public HookStatus onCall(Emulator<?> emulator, long originFunction) {
                logger.info("hookLibc strlen=" + emulator.getContext().getPointerArg(0).getString(0));
                return HookStatus.RET(emulator, originFunction);
            }
        });
    }
    public void hookLibArtSo(){

    }
    public void hookLibArtSo1(){
        Module module = emulator.getMemory().findModule("libart.so");
//        参考文档:
//        https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
        Symbol findClass =  module.findSymbolByName("FindClass");
        IWhale whale = Whale.getInstance(emulator);
        whale.inlineHookFunction(findClass, new ReplaceCallback() {
            @Override
            public HookStatus onCall(Emulator<?> emulator, long originFunction) {
                RegisterContext context = emulator.getContext();
                logger.info("hookLibArtSo strlen=" + context.getPointerArg(0).getString(0));
                return HookStatus.RET(emulator, originFunction);
            }
        });

    }

    public void hook_sub_13558(Module module){
        long start = module.base+0x13558;

        IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz
        hookZz.enable_arm_arm64_b_branch(); // 测试enable_arm_arm64_b_branch,可有可无

        hookZz.wrap(start, new WrapCallback<HookZzArm64RegisterContext>() {
            UnidbgPointer outPointer = null;
            String traceId = null;
            @Override
            public void preCall(Emulator<?> emulator, HookZzArm64RegisterContext context, HookEntryInfo info) {
                traceId =   UUID.randomUUID().toString().replaceAll("-","");

                outPointer = context.getPointerArg(0);


                UnidbgPointer in = context.getPointerArg(1);
                int length = context.getIntArg(2);
               logger.info(traceId+",emulator.attach().addBreakPoint sub_13558 入参arg1:"+in.getString(0));
                logger.info(traceId+",emulator.attach().addBreakPoint sub_13558 入参arg2:"+length);
               logger.info(traceId+",emulator.attach().addBreakPoint sub_13558 入参arg3:"+outPointer.getString(0));


            } // inline wrap导出函数

            @Override
            public void postCall(Emulator<?> emulator, HookZzArm64RegisterContext context, HookEntryInfo info) {
                int rep = context.getIntArg(0);
                logger.info(traceId+",emulator.attach().addBreakPoint sub_13558 返回结果:"+rep);
                logger.info(traceId+",emulator.attach().addBreakPoint sub_13558 返回字符串结果:"+outPointer.getString(0));
            }

        });
        hookZz.disable_arm_arm64_b_branch();
//        xHook  不能应用与这个场景

    }
    public void call_sub_13558(Module module){
        long sub_13558_address = module.base+0x13558;
        MyTraceSystemMemoryWriteListener listener = new MyTraceSystemMemoryWriteListener();
        String traceFile = "unidbg-android/src/test/resources/unidbg/hellojni_2.0.3.txt";
        PrintStream traceStream = null;
        try {
            traceStream = new PrintStream(new FileOutputStream(traceFile), true);
            emulator.traceCode(sub_13558_address, sub_13558_address+0x358,listener).setRedirect(traceStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        String inputStream = "+++++++++";
        int length = inputStream.length();
        //int128,malloc 16
        // 方法一  128个比特,分配16个字节就好
       Pointer outPutStream = memory.allocateStack(16);
        //            这个打印的是什么,https://blog.csdn.net/li_ph/article/details/9712225
//        logger.info(new Stat64(outPutStream));
        Number[] numbers =  module.callFunction(emulator,0x13558,outPutStream,inputStream,length);
        logger.info("numbers="+numbers[0].intValue());

        logger.info("outPutStream="+outPutStream.getString(0));
    }

    /**
     * 替换函数 sub_13558的参数
     * @param module
     */
    public void replace_sub_13558_arg(Module module){
        long sub_13558_address = module.base+0x13558;
        HookZz hook = HookZz.getInstance(emulator);
        hook.replace(sub_13558_address, new ReplaceCallback() {
            UnidbgPointer outPointer = null;
            String traceId = null;
            @Override
            public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
                traceId =   UUID.randomUUID().toString().replaceAll("-","");

                outPointer = context.getPointerArg(0);
                UnidbgPointer in = context.getPointerArg(1);
                int length = context.getIntArg(2);
//
                logger.info(traceId+",初始 replace_sub_13558_arg 入参arg1:"+in.getString(0));
                logger.info(traceId+",初始 replace_sub_13558_arg 入参arg2:"+length);
                logger.info(traceId+",初始 replace_sub_13558_arg 入参arg3:"+outPointer.getString(0));
                String helloInput = "hello world";
                length = helloInput.length();
                MemoryBlock helloInputBlock = emulator.getMemory().malloc(length, true);
                helloInputBlock.getPointer().write(helloInput.getBytes(StandardCharsets.UTF_8));
                // 修改r0为指向新字符串的新指针,此处注意64位的使用Arm64Const.UC_ARM64_REG_W1,32位的使用ArmConst.UC_ARM_REG_R1
                emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_W1, helloInputBlock.getPointer().peer);
                // 修改r1值为新长度
                emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_W2, length);

                in = context.getPointerArg(1);
                length = context.getIntArg(2);
                logger.info(traceId+",修改后 replace_sub_13558_arg 入参arg1:"+in.getString(0));
                logger.info(traceId+",修改后 replace_sub_13558_arg 入参arg2:"+length);
                return HookStatus.RET(emulator,originFunction);
            }

            @Override
            public void postCall(Emulator<?> emulator, HookContext context) {


                int rep = context.getIntArg(0);
                logger.info(traceId+",:"+rep);
                logger.info(traceId+",replace_sub_13558_arg 返回字符串结果:"+outPointer.getString(0));
//                super.postCall(emulator, context);
            }
        },true);
    }
    public void replace_sub_13558_result(Module module){
        long sub_13558_address = module.base+0x13558;
        HookZz hook = HookZz.getInstance(emulator);
        hook.replace(sub_13558_address, new ReplaceCallback() {
            UnidbgPointer outPointer = null;
            String traceId = null;
            @Override
            public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
                traceId =   UUID.randomUUID().toString().replaceAll("-","");
                outPointer = context.getPointerArg(0);
                return HookStatus.RET(emulator,originFunction);
            }
//            _BYTE *__fastcall sub_13558(_BYTE *result, const void *a2, unsigned __int64 length)
            @Override
            public void postCall(Emulator<?> emulator, HookContext context) {
                String helloInput = "VeryGood";
                int  length = helloInput.length();
                MemoryBlock helloInputBlock = emulator.getMemory().malloc(length, true);
                helloInputBlock.getPointer().write(helloInput.getBytes(StandardCharsets.UTF_8));

                // 修改r0为指向新字符串的新指针,此处注意64位的使用Arm64Const.UC_ARM64_REG_W1,32位的使用ArmConst.UC_ARM_REG_R0
                emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_W0, 2);

                outPointer.setString(0,helloInput);
            }

        },true);
    }


    public static void main(String[] args) throws IOException {
        HookInUnidbgByConsoleDebuggerV2 mydemo = new HookInUnidbgByConsoleDebuggerV2();

//       mydemo. hook_sub_13558(mydemo.module);
//        替换函数sub_13558的参数
//              mydemo.replace_sub_13558_arg(mydemo.module);
              mydemo.replace_sub_13558_result(mydemo.module);
//        mydemo.callSign2();
        mydemo.call_sub_13558(mydemo.module);
        mydemo.destroy();
    }

    Module libc = null;
    @Override
    public void onLoaded(Emulator<?> emulator, Module module) {

        if("libc.so".equals(module.name)){
            hookLibc();
        }else if("libart.so".equals(module.getPath())){
            hookLibArtSo();
        }else if("libhello-jni.so".equals(module.getPath())){
            //call_sub_13558(module);
        }
        logger.info(module.getPath()+"文件加载完毕,"+module.getBaseHeader());
    }
    void destroy() throws IOException {
        emulator.close();

         System.out.println("destroy");

    }
}

补充知识

1:使用unidbg 里的IHookZz进行替换函数sub_13558里的参数

 emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_W1, helloInputBlock.getPointer().peer);

此处注意,64位的使用Arm64Const.UC_ARM64_REG_W0,32位使用ArmConst.UC_ARM_REG_R0等

2:使用unidbg 里的IHookZz进行替换函数sub_13558的返回值

 emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_W0, 2);

此处注意,64位的使用Arm64Const.UC_ARM64_REG_W0,32位使用ArmConst.UC_ARM_REG_R0

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:43:51  更:2022-02-01 20:44:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 6:47:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码