爬虫工程师的 unidbg 入门教程 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
zhaoboy666
V2EX    Python

爬虫工程师的 unidbg 入门教程

  •  
  •   zhaoboy666 2019-12-28 12:30:38 +08:00 6492 次点击
    这是一个创建于 2117 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 现在很多的 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 下载完毕用 idea 打开,等待 maven 下载完毕。我这里已经创建好 du 的文件。

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

    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(); } } 

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

    TTEncryptUtils = vm.resolveClass("com/*/aesjni/AESEncrypt"); 我们需要逆向 app,这里不细说如何在 app 中寻找加载 so 的类。如下图,encodeByte 是该 app 调用 native 层加密的入口,loadLibrary 是 java 加载 so 的方法,这个类就是上述代码中填写的。

    然后再看"encodeByte(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"这里,这是 smali 写法,不补基础,后面跟上需要传的参数, getByteValues 这个方法是毒获取的一个 01 字符串,并且在 java 层进行了处理,然后再传进encodeByte里面,encodeByte这个方法最后获取的其实并不是最终需要的,需要 md5 才是最后的 newSign。可以验证一下下。

    测试结果通过。

    最后

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

    VM options: -Djava.library.path=prebuilt/os -Djna.library.path=prebuilt/os Where os may: linux64, win32, win64, osx64 

    最后这个文件放在https://github.com/zhaoboy9692/dailyanalysis喜欢的可以 star,谢谢。 以上文章仅用于学习交流

    2 条回复    2019-12-29 17:44:02 +08:00
    locoz
        1
    locoz  
       2019-12-28 16:42:56 +08:00 via Android
    整挺好。可以到 bbs.nightteam.cn 也发一下,社区领域更垂直一些
    lusi1990
        2
    lusi1990  
       2019-12-29 17:44:02 +08:00
    不错 , 以后爬的时候就不用开个真机了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     983 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 22:35 PVG 06:35 LAX 15:35 JFK 18:35
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86