APP 逆向 --- du APP 逆向


APP 逆向 — du APP 逆向

第一步就是抓包

根据抓到的包,可以看出需要破解的参数 newSign 、password、uuid 还有 headers 中的参数 shumeiid/x-auth-token/duuid/duimei/shumengid 。也就是有这么多的参数是不知道的,需要去 app 中找的。

第二步 使用 jadx 打开 app

直接搜索 api,

点进去后直接查找用例,就会跳转到下图。

走到这再去点的时候,发现一些参数而且调用了 newParams, 参数 userName、type、sourcePage、countryCode 都是没有加密的,所以重点就是看看这个 password。hook 这个方法发现里面密码是已经加密过的,直接查找用例

点进去就找到 password 的加密位置。

从这个方法中可以看到密码是 MD5Util 的加密。为了验证我的判断,直接 Hook MD5Util.a方法

md5_js_code = """

    Java.perform(function () {
    var MainActivity =                       Java.use('com.shizhuang.duapp.framework.util.encrypt.MD5Util');
    MainActivity.a.overload('java.lang.String').implementation = function () {
    console.log("password: #################" + arguments[0]);
    var str2 = "12345678du";
    Java.openClassFile("/data/local/tmp/r0gson.dex").load();
    const gson = Java.use("com.r0ysue.gson.Gson");
    console.log("11111111111111111111111111111111111111111+++++++++++++++++++++")
    console.log(gson.$new().toJson(this.a(str2)));
    console("------------------------------");
    };
});
"""

打印的结果

然后点击 LoginFacade.c ,发现到了最开始的发起请求,拼接参数的地方。到这里 password 的就完事了。

然后又重新搜索参数 newSign

这里看看 OkHttp https://blog.csdn.net/qq_38851536/article/details/100146115

点进去后,发现基本参数,以及请求头这些东西都可以找到。剩下的就是这些具体的实现以及加密。

继续找到 RequestUtils.b 方法,这个方法最后就是该参数的加密位置以及加密方法。从名字看就是个 AES 加密。加密的内容就是请求参数转为字符串,然后拼接后加密。

继续进入这个 b 方法, 可以看到返回的是一个执行encodeByte 方法后的返回值。而这个方法是 native, 加载的 so 文件为 JNIEncrypt

剩下的就是关于这个加密参数的 Hook.

第三步直接 HOOK 这个方法,查看具体都加密了哪些东西

可以看到 java 层加密的就是这么多的东西,剩下的就是 native 层

参考文章

爬虫工程师的unidbg入门教程

通过 unidbg 直接调用 so 文件

直接去 github上下载 https://github.com/zhkl0228/unidbg

参考上面大佬文章中的代码,进行简单的修改。我逆向的版本中 encodeByte 方法有更新,简单修改一下,就可以了

public class du extends AbstractJni {
    //ARM模拟器
    private final AndroidEmulator emulator;
    //vm
    private final VM vm;
    //载入的模块
    private final Module module;

    private final DvmClass TTEncryptUtils;

    //初始化
    public du() throws IOException {
        //创建毒进程,这里其实可以不用写的,我这里是随便写的,使用app本身的进程就可以绕过进程检测
        emulator = new AndroidARMEmulator("com.shizhuang.duapp");
        final 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(null);
        vm.setVerbose(true);
        vm.setJni(this);
//        vm = emulator.createDalvikVM(null);
        //加载so,使用armv8-64速度会快很多
        DalvikModule dm = vm.loadLibrary(new File("src/test/resources/xiaohongshu/libJNIEncrypt.so"), false);
        //调用jni
        dm.callJNI_OnLoad(emulator);
        module = dm.getModule();
        //Jni调用的类,加载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("123456");
        t.destroy();

    }

    private String encodeByte(String strs) {
        //调试
        // 这里还支持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;");
        System.out.println(ret);
        System.out.println("-----------------------");
        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');
            }
        }
        byte[] strs_byte = strs.getBytes();
        //获取encodeByte地址
        ret = TTEncryptUtils.callStaticJniMethod(emulator, "encodeByte([BLjava/lang/String;)Ljava/lang/String;", vm.addLocalObject(new ByteArray(strs_byte)),

                //传参,这里需要两个字符串,所以就传入两个参数
//                vm.addLocalObject(new StringObject(vm, strs)),
                vm.addLocalObject(new StringObject(vm, builder.toString()))

        );
        //ret 返回的是地址,
        hash = ret.intValue() & 0xffffffffL;
        //获得其值
        StringObject str = vm.getObject(hash);
        System.out.println(str);
        System.out.println("----------------------");
        System.out.println(str.getValue());
        return str.getValue();
    }
}

这个执行完之后在进行 md5 . 就 OK 了


文章作者: Andrew
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Andrew !
评论
 上一篇
收集的常用hook脚本 收集的常用hook脚本
本篇文章来源: https://note.youdao.com/ynoteshare1/index.html?id=7a1c9199ebb941eac77942a60f42ac70&type=note 收集的常用hook脚本 doc
2020-09-20 Andrew
下一篇 
apktool 反编译碰到的问题 apktool 反编译碰到的问题
使用 apktool 反编译 App 以及重新打包中遇到的问题及解决办法步骤反编译 app 时直接执行 apktool d demo.apk 这样就可以了。 然后重新打包的命令:apktool b demo 问题及解决重新打包时碰到的问题:
2020-04-26
  目录