登录后更精彩...O(∩_∩)O...
您需要 登录 才可以下载或查看,没有账号?立即注册
×
unidbg初探
由来前天有个吧友发了个使用unidbg模拟某app协议,觉得有点意思,于是今天来试试。
优势unidbg 是一个基于 unicorn 的逆向工具,可以黑盒调用安卓和 iOS 中的 so 文件。unidbg 是一个标准的 java 项目。
由于现在的大多数 app 把签名算法已经放到了 so 文件中,要想破解签名算法,必须能够破解 so 文件。C++ 的逆向远比 Java 的逆向要难得多了,所以好多时候是没法破解的,那么这个时候还可以采用 hook 的方法,直接读取程序中算出来的签名,但是这样的话,需要实际运行这个应用,需要模拟器或者真机,效率又不是很高(比如frida的rpc调用,就需要后台运行应用)。unidbg 就是一个很巧妙地解决方案,他不需要直接运行 app,也无需逆向 so 文件,而是通过在 app 中找到对应的 JNI 接口,然后用 unicorn 引擎直接执行这个 so 文件,所以效率也比较高。(复制百度)
需要工具安卓模拟器(真机也可以)
Fiddler(用于抓包)
jadx(用于反编译apk)
jeb(用于反编译apk)
firda(用于分析apk)
idea(用于写代码)
apk(分析的apk)
前提
由于脱壳和反编译不是本文的重点,那么假设你已经脱壳并得到dex,且用jex和jadx定义到加密的地方。如下图
并且得到一组加密参数(原文两个参数)
原文
[Bash shell] 纯文本查看 复制代码 参数一:/v1/login/mobile/code?mobile=13888888888&country_code=0086&__plat=android&__version=2.21.0&__app=inyu
参数二:1607237431
密文 4e02b282da566a80b86c25cd2cb6e1ec
正文开始
2、导入到IDEA中
unidbg项目用Java编写,并且上面下载的是一个标准的maven项目。我这里演示导入到IDEA中。
3、测试unidbg
项目中的src/test/java/com/bytedance/frameworks/core/encrypt路径中有一个TTEncrypt测试用例,直接执行其中的main方法。
4、编写调用类TestJni
基本上是个模板,需要改的地方,已经注释表明
[Java] 纯文本查看 复制代码 package com.tanran.test;
import com.github.unidbg.Module;
import com.github.unidbg.arm.ARMEmulator;
import com.github.unidbg.linux.android.AndroidARMEmulator;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import java.io.File;
import java.io.IOException;
public class TestJni extends AbstractJni {
// ARM模拟器
private final ARMEmulator emulator;
// vm
private final VM vm;
// 载入的模块
private final Module module;
private final DvmClass TTEncryptUtils;
/**
*
* @param soFilePath 需要执行的so文件路径
* @param classPath 需要执行的函数所在的Java类路径
* @throws IOException
*/
public TestJni(String soFilePath, String classPath) throws IOException {
// 创建app进程,包名可任意写
emulator = new AndroidARMEmulator("io.liuliu.music");
Memory memory = emulator.getMemory();
// 作者支持19和23两个sdk
memory.setLibraryResolver(new AndroidResolver(23));
// 创建DalvikVM,利用apk本身,可以为null
vm = ((AndroidARMEmulator) emulator).createDalvikVM(null);
vm.setVerbose(true);
vm.setJni(this);
// (关键处1)加载so,填写so的文件路径
DalvikModule dm = vm.loadLibrary(new File(soFilePath), false);
// 调用jni
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
// (关键处2)加载so文件中的哪个类,填写完整的类路径
TTEncryptUtils = vm.resolveClass(classPath);
}
/**
* 调用so文件中的指定函数
* @param methodSign 传入你要执行的函数信息,需要完整的smali语法格式的函数签名
* @param args 是即将调用的函数需要的参数
* @return 函数调用结果
*/
private String myJni(String methodSign, Object ...args) {
// 使用jni调用传入的函数签名对应的方法()
Object value = TTEncryptUtils.callStaticJniMethodObject(emulator, methodSign, args).getValue();
return value.toString();
}
/**
* 关闭模拟器
* @throws IOException
*/
private void destroy() throws IOException {
emulator.close();
System.out.println("emulator destroy...");
}
public static void main(String[] args) throws IOException {
// 1、需要调用的so文件所在路径
String soFilePath = "unidbg-android/src/test/resources/myso/libinyu-lib.so";
// 2、需要调用函数所在的Java类完整路径,比如a/b/c/d等等,注意需要用/代替.
String classPath = "water/android/io/inyustring/InyuString";
// 3、需要调用方法,再jadx中找到对应的方法,然后点击下面的Smail,复制方法的Smail代码。
String methodSign = "getUrlSign(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;";
TestJni testJni = new TestJni(soFilePath, classPath);
// 输出getGameKey方法调用结果
System.err.println(testJni.myJni(methodSign,"/v1/login/mobile/code?mobile=13888888888&country_code=0086&__plat=android&__version=2.21.0&__app=inyu","1607237431"));
testJni.destroy();
}
}
5、运行看结果
虽然报了个错,但是结果还是输出来了。(与目标结果一致)有大神如果知道哪里的问题,请告知下小弟。
参考资料
附件
|