本帖最后由 坦然 于 2020-12-6 16:18 编辑
由来
前天有个吧友发了个使用unidbg模拟某app协议,觉得有点意思,于是乎今天来试试,论坛里unidbg的教程也比较少,那我就来抛砖引玉,献献丑了。还望大神勿喷。
优势
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定义到加密的地方。如下图
并且得到一组加密参数(原文两个参数)
原文 参数一:/v1/login/mobile/code?mobile=13888888888&country_code=0086&__plat=android&__version=2.21.0&__app=inyu 参数二:1607237431
密文 4e02b282da566a80b86c25cd2cb6e1ec
正文开始
1、下载unidbg项目
下载地址:https://github.com/zhkl0228/unidbg
2、导入到IDEA中
unidbg项目用Java编写,并且上面下载的是一个标准的maven项目。我这里演示导入到IDEA中。
3、测试unidbg
项目中的src/test/java/com/bytedance/frameworks/core/encrypt路径中有一个TTEncrypt测试用例,直接执行其中的main方法。
4、编写我们的调用类TestJni(基本上是个模板,需要改的地方,已经注释表明)
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、运行看结果
虽然报了个错,但是结果还是输出来了。(与目标结果一致)有大神如果知道哪里的问题,请告知下小弟。
参考资料
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1321190&highlight=unidbg
https://blog.csdn.net/qq_41855420/article/details/106265603
https://www.cnblogs.com/xbjss/p/12110083.html
附件
classes9.zip
(1.94 MB, 下载次数: 119)
libinyu-lib.zip
(26 KB, 下载次数: 79)
|