211回答

17收藏

爬虫工程师的 unidbg 入门教程

信息分享 信息分享 61953 人阅读 | 211 人回复 | 2019-12-29





* 现在很多的app使用了so加密,以后会越来越多。爬虫工程师可能会直接逆向app,看java代码,完成java层的算法破解,但是如果遇到so该怎么办呢?可能你会直接破解so,但是真的会有很多爬虫工程师会去并且会破解so吗?有时候我们可以不用破解so,利用很多大佬写好的轮子即可完成so的调用。

*说到调用,就有很多方法了,比如用frida的rpc、xposed+andserver、再者就是unicorn+web框架等等,今天要说的并不是这些,而是unidbg,这框架有什么好的地方呢?看看介绍。

## 介绍(来自逸飞)

unidbg 是一个基于 unicorn 的逆向工具,可以黑盒调用安卓和 iOS 中的 so 文件。unidbg 是一个标准的 java 项目。

由于现在的大多数 app 把签名算法已经放到了 so 文件中,所以要想破解签名算法,必须能够破解 so 文件。但是我们知道,C++ 的逆向远比 Java 的逆向要难得多了,所以好多时候是没法破解的,那么这个时候还可以采用 hook 的方法,直接读取程序中算出来的签名,但是这样的话,需要实际运行这个应用,需要模拟器或者真机,效率又不是很高。

unidbg 就是一个很巧妙地解决方案,他不需要直接运行 app,也无需逆向 so 文件,而是通过在 app 中找到对应的 JNI 接口,然后用 unicorn 引擎直接执行这个 so 文件,所以效率也比较高。

* 这里重要的是目前利用unidbg+springboot做成了web服务。

## 食用

案例来自JXU2QkQyYXBwJTIwdjQuMTYuMA==

对于该app而言,是非常适合入门的一个app,未加固、算法简单、很容易找到so的jni。

先去凯神的github上下载[https://github.com/zhkl0228/unidbg](https://github.com/zhkl0228/unidbg)

下载完毕用idea打开,等待maven下载完毕。我这里已经创建好du的文件。

![](https://user-gold-cdn.xitu.io/2019/12/27/16f47d3080de78a1?w=896&h=256&f=png&s=55937)

上个代码看着比较方便,代码中有很多注释

[ttreply]

```

public class du extends AbstractJni {

//ARM模拟器

private final ARMEmulator emulator;

//vm

private final VM vm;

//载入的模块

private final Module module;

private final DvmClass TTEncryptUtils;

//初始化

public du() throws IOException {

//创建app进程,这里其实可以不用写的,我这里是随便写的,使用app本身的进程就可以绕过进程检测

emulator = new AndroidARMEmulator("com.du.du");

Memory memory = emulator.getMemory();

//作者支持19和23两个sdk

memory.setLibraryResolver(new AndroidResolver(23));

memory.setCallInitFunction();

//创建DalvikVM,利用apk本身,可以为null

//如果用apk文件加载so的话,会自动处理签名方面的jni,具体可看AbstractJni,利用apk加载的好处,

//        vm = emulator.createDalvikVM(new File("src/test/resources/du/du4160.apk"));

我这里没有用到apk,主要是没有检测其他因素。

vm = emulator.createDalvikVM(null);

//加载so,使用armv8-64速度会快很多,这里是so的文件路径,其实也可以利用apk自身的。

DalvikModule dm = vm.loadLibrary(new File("src/test/resources/du/libJNIEncrypt.so"), false);

//调用jni

dm.callJNI_OnLoad(emulator);

module = dm.getModule();

//加载so的那个类

TTEncryptUtils = vm.resolveClass("com/duapp/aesjni/AESEncrypt");

}

//关闭模拟器

private void destroy() throws IOException {

emulator.close();

System.out.println("destroy");

}

public static void main(String[] args) throws IOException {

du t = new du();

t.encodeByte();

t.destroy();

}

private String encodeByte() {

//调试

// 这里还支持gdb调试,

//emulator.attach(DebuggerType.GDB_SERVER);

//附加调试器

//        emulator.attach(DebuggerType.SIMPLE);

//        emulator.traceCode();

//这里是打断点,原地址0x00005028->新地址0x40005028 新地址需要改成0x4

//        emulator.attach().addBreakPoint(null, 0x40001188);//encode地址

//        emulator.attach().addBreakPoint(null, 0x40000D10);

Number ret = TTEncryptUtils.callStaticJniMethod(emulator, "getByteValues()Ljava/lang/String;");

long hash = ret.intValue() & 0xffffffffL;

StringObject st1 = vm.getObject(hash);

//*这里要处理下字符串

String byteString = st1.getValue();

StringBuilder builder = new StringBuilder(byteString.length());

for (int i = 0; i < byteString.length(); i++) {

if (byteString.charAt(i) == '0') {

builder.append('1');

} else {

builder.append('0');

}

}

//获取encodeByte地址

ret = TTEncryptUtils.callStaticJniMethod(emulator, "encodeByte(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",

//传参,这里需要两个字符串,所以就传入两个参数

vm.addLocalObject(new StringObject(vm, "要加密的值")),

vm.addLocalObject(new StringObject(vm, builder.toString())));

//ret 返回的是地址,

hash = ret.intValue() & 0xffffffffL;

//获得其值

StringObject str = vm.getObject(hash);

System.out.println(str.getValue());

return str.getValue();

}

}

```[/ttreply]

上边代码有jni的类是哪一个需要知道,就是下面这个类,这个其实是和加载so有关系的。

`  TTEncryptUtils = vm.resolveClass("com/*/aesjni/AESEncrypt");`

我们需要逆向app,这里不细说如何在app中寻找加载so的类。如下图,encodeByte是该app调用native层加密的入口,loadLibrary是java加载so的方法,这个类就是上述代码中填写的。

![](https://user-gold-cdn.xitu.io/2019/12/27/16f47dad71761786?w=1040&h=627&f=png&s=90723)

然后再看`"encodeByte(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"`这里,这是smali写法,不补基础,后面跟上需要传的参数,

`getByteValues` 这个方法是毒获取的一个01字符串,并且在java层进行了处理,然后再传进`encodeByte`里面,`encodeByte`这个方法最后获取的其实并不是最终需要的,需要md5才是最后的newSign。可以验证一下下。

![](https://user-gold-cdn.xitu.io/2019/12/27/16f47ee56a30abb4?w=1381&h=669&f=png&s=320545)

测试结果通过。

### 最后

启动java文件时候注意这个改成自己的平台!!!

```

VM options: -Djava.library.path=prebuilt/os -Djna.library.path=prebuilt/os

Where os may: linux64, win32, win64, osx64

```

![](https://user-gold-cdn.xitu.io/2019/12/27/16f47f8291d2ad56?w=740&h=275&f=png&s=26594)

最后这个文件放在[https://github.com/zhaoboy9692/dailyanalysis](https://github.com/zhaoboy9692/dailyanalysis)喜欢的可以star,谢谢。






分享到:
回复

使用道具 举报

回答|共 211 个

化肥

发表于 2019-12-29 17:00:23 | 显示全部楼层

回复

使用道具 举报

花儿谢了

发表于 2019-12-30 09:11:46 | 显示全部楼层

这个,没有图片你发现没
回复

使用道具 举报

strive

发表于 2019-12-30 09:17:41 | 显示全部楼层

没有图片。。。。
回复

使用道具 举报

thunder

发表于 2019-12-30 09:31:53 | 显示全部楼层

还得回复才能看。。。
回复

使用道具 举报

为了一只鸡腿

发表于 2019-12-30 10:38:49 | 显示全部楼层

还得回复才能看
回复

使用道具 举报

thunder

发表于 2019-12-30 10:46:09 | 显示全部楼层

咋 找不到  函数find method failed: encodeByte(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
回复

使用道具 举报

thunder

发表于 2019-12-30 11:08:58 | 显示全部楼层

版本 不一样。。。  新版得   public static native String encodeByte(byte[] bArr, String str);
回复

使用道具 举报

YDXX丶

发表于 2019-12-30 15:40:25 | 显示全部楼层

还得回复才能看。。
-------------------------------------
作者: zhaoboy666
来源: 夜幕爬虫安全论坛
原文链接: https://bbs.nightteam.cn/thread-196.htm
版权声明: 若无额外声明,本帖为作者原创帖,转载请附上帖子链接!
回复

使用道具 举报

administrator

发表于 2019-12-30 18:18:37 | 显示全部楼层

5666
回复

使用道具 举报