unidbg第六讲 com.github.unidbg.android.QDReaderJni

unidbg第六讲 com.github.unidbg.android.QDReaderJni,第1张

unidbg第六讲 com.github.unidbg.android.QDReaderJni 讲解例子
  1. 监控so文件加载成功
  2. 动态注册方法
代码
package com.github.unidbg.android;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
import com.github.unidbg.ModuleListener;
import com.github.unidbg.Symbol;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.arm.backend.DynarmicFactory;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.xhook.IxHook;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.XHookImpl;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.linux.android.dvm.jni.ProxyClassFactory;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.File;
import java.io.IOException;


public class QDReaderJni implements ModuleListener {

    private static final int SDK = 23;

    private static LibraryResolver createLibraryResolver() {
        return new AndroidResolver(SDK);
    }

    private static AndroidEmulator createARMEmulator() {
        return AndroidEmulatorBuilder.for32Bit()
                .setProcessName("a.d.c")
                .addBackendFactory(new DynarmicFactory(true))
                .build();
    }

    private final AndroidEmulator emulator;
    private final VM vm;

    private final DvmClass d;

    private QDReaderJni() {
//        创建模拟器
        emulator = createARMEmulator();
//        获取内存对象
        final Memory memory = emulator.getMemory();
//      设置AndroidResolver
        memory.setLibraryResolver(createLibraryResolver());
// 重点:    设置模块加载监听
        memory.addModuleListener(this);

//      使用模拟器创建虚拟机
        vm = emulator.createDalvikVM();
        vm.setDvmClassFactory(new ProxyClassFactory());
 // 设置是否打印Jni调用细节
        vm.setVerbose(true);

//  加载so文件
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/armeabi-v7a/libd-lib.so"), false);
// 手动调用JNI_OnLoad方法
        dm.callJNI_onLoad(emulator);

//   模拟类a.d
        d = vm.resolveClass("a/d");
    }

    private void destroy() throws IOException {
        emulator.close();
        System.out.println("destroy");
    }

    public static void main(String[] args) throws Exception {
//        初始化类
        QDReaderJni test = new QDReaderJni();
//调用方法c
        test.c();

        test.destroy();
    }

    @Override
    public void onLoaded(Emulator emulator, Module module) {
//        监控so文件加载完成后调用的方法
        if ("libcrypto.so".equals(module.name)) {
            Symbol DES_set_key = module.findSymbolByName("DES_set_key", false);
            Symbol DES_set_key_unchecked = module.findSymbolByName("DES_set_key_unchecked", false);
            if (DES_set_key_unchecked == null && DES_set_key != null) {
//                注册DES_set_key_unchecked
                module.registerSymbol("DES_set_key_unchecked", DES_set_key.getAddress());
            }
        }
    }

    private void c() throws Exception {
//    注册hook方法,对libd-lib.so里的free进行hook
        IxHook xHook = XHookImpl.getInstance(emulator);
        xHook.register("libd-lib.so", "free", new ReplaceCallback() {
            @Override
            public HookStatus onCall(Emulator emulator, long originFunction) {
                return HookStatus.LR(emulator, 0);
            }
        });

        xHook.refresh();

        final String data = "359250054370919||1551086094";
        long start = System.currentTimeMillis();
//        emulator.traceCode();
//        模拟调用jni方法boolean c(String)
        ByteArray array = d.callStaticJniMethodObject(emulator, "c(Ljava/lang/String;)[B", new StringObject(vm, data));
//       打印返回结果
        Inspector.inspect(array.getValue(), "c offset=" + (System.currentTimeMillis() - start) + "ms");

        final String key = "sewxf03hhz3ew9qcCXMHiDMk";
        final String iv = "sh331nt1";

//        加密和解密
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        DESedeKeySpec keySpec = new DESedeKeySpec(key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        byte[] encrypted = cipher.doFinal(data.getBytes());
//       打印加密后的二进制字节信息
        Inspector.inspect(encrypted, "Encrypted");

        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
        byte[] decrypted = cipher.doFinal(array.getValue());
 //       打印解密后的二进制字节信息
        Inspector.inspect(decrypted, "Decrypted");
    }

}
   备注

1:动态监测so文件加载成功需要实现接口ModuleListener,并注册自己

2:动态注册符号,需要使用方法

module.registerSymbol

3 在线arm汇编指令与HEX转换网站:https://armconverter.com/

其他

有问题请留言,一起进步。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5696677.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存