zoukankan      html  css  js  c++  java
  • dewuApp逆向

    第一步就是抓包

    根据抓到的包,可以看出需要破解的参数 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 了

    第四步:使用 python 调用 jar

  • 相关阅读:
    dajngo ORM查询中select_related的作用,博客主题的定制,从数据库中按照年月筛选时间
    Django数据查询中对字段进行排序
    Django验证码实现
    django登录注册验证之密码包含特殊字符,确认密码一致实现,Form验证
    django模板传入参数的处理方式与反向生成url
    在django中使用循环与条件语言
    django的模板的继承与导入
    sublime3故障收集emmet无法安装pyv8
    [SQL SERVER系列]之嵌套子查询和相关子查询
    [SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优
  • 原文地址:https://www.cnblogs.com/gqv2009/p/13208434.html
Copyright © 2011-2022 走看看