目前很多 App 的加密签名算法都在 so 文件中,强行逆向 so 的话可能会耗费大量工夫和资源。
之前用 xposed 采纳 hook 的办法从程序计算签名,然而须要模拟器或者真机运行这个利用,应用效率不高。
也用过 jtype 启动 JVM,而后通过 native 对 so 文件进行调用,因为每次都须要启动 JVM,所以效率也不高。
unidbg 他不须要运行 app,也无需逆向 so 文件,通过在 app 中找到对应的 JNI 接口,而后用 unicorn 引擎间接调用 so 文件,所以效率绝对要高不少。
unidbg 特点
- 模仿 JNI 调用 API,能够调用 JNI_OnLoad
- 反对 JavaVM,JNIEnv
- 模拟系统调用
- 反对 ARM32 和 ARM64
- 内联钩子(Inline Hook)
- Android import hook
- iOS 的一些 hook 工具 fishhook and substrate and whale hook
- 反对简略的控制台调试器,gdb 存根,实验性 IDA android 调试器服务器,指令跟踪,内存读 / 写跟踪
- 反对 iOS objc 和 Swift
unidbg 环境配置
unidbg 下载链接:https://github.com/zhkl0228/unidbg
IntelliJ IDEA 可用于编辑 unidbg 源
下载实现之后示导入到 IDEA 中,当然你须要筹备好 java 环境(jdk、maven)
抉择 Maven
期待加载实现之后,运行 src/…./encrypt 中的 TTEncrypt 测试用例
如果控制台打印相干调用信息,阐明曾经导入胜利。
加载 libcms.so
看过这篇文章的应该曾经晓得生成 xg 函数的地位,所以不具体说了。《抖音 xgorgon(0401)》
上面筹备调用 libcms.so 文件中的 leviathan 函数
首先在 src/test/resources 目录下新建文件夹 dylib,放入 libcms.so 文件
libcms.so 下载地址: https://download.csdn.net/download/weixin_43582101/12713664
而后我在 /unidbg/unidbg-android/src/test/java/com/sun/jna/ 目录下新建了 JniDispatch128.java 文件
JniDispatch128.java文件内容如下:
备注 | |
---|---|
“com/ss/sys/ces/a” | 须要调用函数所在的 Java 类残缺门路,比方 a/b/c/d 等等,留神须要用 / 代替. |
“leviathan(II[B)[B” | 须要调用的函数名,名字是 smali 语法,可通过 jadx 等工具查看 |
“vm.loadLibrary(new File)” | so 文件的门路,须要自行批改,最好为绝对路径 |
package com.sun.jna;
import com.github.unidbg.*;
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 com.github.unidbg.memory.MemoryBlock;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import java.io.File;
import java.io.IOException;
public class JniDispatch128 extends AbstractJni {private static LibraryResolver createLibraryResolver() {return new AndroidResolver(23);
}
private static AndroidEmulator createARMEmulator() {return new AndroidARMEmulator("com.sun.jna");
}
private final AndroidEmulator emulator;
private final Module module;
private final VM vm;
private final DvmClass Native;
private JniDispatch128() {emulator = createARMEmulator();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(createLibraryResolver());
vm = emulator.createDalvikVM(null);
vm.setJni(this);
vm.setVerbose(true);
// 自行批改文件门路
DalvikModule dm = vm.loadLibrary(new File("/Users/Desktop/unidbg/unidbg-android/src/test/resources/dylib/libcms.so"), false);
dm.callJNI_OnLoad(emulator);
module = dm.getModule();
Native = vm.resolveClass("com/ss/sys/ces/a");
private void destroy() throws IOException {emulator.close();
System.out.println("destroy");
}
public static void main(String[] args) throws Exception {JniDispatch128 test = new JniDispatch128();
test.test();
test.destroy();}
public static String xuzi1(byte[] bArr) {if (bArr == null) {return null;}
char[] charArray = "0123456789abcdef".toCharArray();
char[] cArr = new char[(bArr.length * 2)];
for (int i = 0; i < bArr.length; i++) {int b2 = bArr[i] & 255;
int i2 = i * 2;
cArr[i2] = charArray[b2 >>> 4];
cArr[i2 + 1] = charArray[b2 & 15];
}
return new String(cArr);
}
private void test() {String methodSign = "leviathan(II[B)[B";
byte[] data = "临时轻易写的, 这里是 url 通过解决后的 data".getBytes();
int time = (int) (System.currentTimeMillis() / 1000);
Native.callStaticJniMethod(emulator, methodSign, -1,time,new ByteArray(vm,data));
Object ret = Native.callStaticJniMethodObject(emulator, methodSign, -1,time,new ByteArray(vm,data));
System.out.println("callObject 执行后果:"+((DvmObject) ret).getValue());
byte[] tt = (byte[]) ((DvmObject) ret).getValue();
System.out.println(new String(tt));
String s = xuzi1(tt);
System.out.println(s);
}
}
运行 main 办法即可查看生成进去的 xgorgon 了
more articles
更多 douyin 技术文章,可查看专栏:
https://blog.csdn.net/weixin_43582101/category_9529769.html