某咖啡app加密参数分析进阶版

查看 146|回复 10
作者:darbra   

仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。

前言
  • app 某某咖啡
  • v4.4.0
  • 去年发了一篇 某咖啡app网络请求签名算法分析与解密,这次是进阶版。

    mitmproxy抓包


    0000.png (144.96 KB, 下载次数: 1)
    下载附件
    2022-1-14 13:27 上传

    java分析
    定位到CryptoHelper类的名为md5_crypt的native静态方法。


    0001.png (188.57 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:29 上传

    frida hook
    脚本如下所示
    function hook() {
        Java.perform(function() {
        var CryptoHelper = Java.use('com.l*****e.safeboxlib.CryptoHelper');
        CryptoHelper.md5_crypt.implementation = function (x, y) {
            console.log('md5_crypt_x', bytes2str(x));
            console.log('md5_crypt_y', y);
            var result = this.md5_crypt(x, y);
            console.warn('md5_crypt_ret', bytes2str(result));
            return result;
            };
      }
      }
    我们可以看到,hook的结果和抓包结果一致


    0003.png (59.01 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:29 上传

    so分析
    使用lasting-yang的脚本hook_RegisterNatives
    脚本地址:https://github.com/lasting-yang/frida_hook_libart


    0004.png (103.41 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:29 上传

    使用开源的cutter到so去一探究竟,我们搜索上图中的偏移0x1a981,来到android_native_md5函数。


    0005.png (301.75 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:29 上传

    经过一番分析,应该是md5加密完之后,还有一个bytesToInt的逻辑。


    0006.png (352.24 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:30 上传

    unidbg
    去年的文章里用frida就能搞定了,这次我们用lilac、qinless、qxp等大佬极力推荐的神器unidbg进行辅助分析。
    首先是搭建架子
    package com.*;
    import com.github.unidbg.AndroidEmulator;
    import com.github.unidbg.Module;
    import com.github.unidbg.debugger.Debugger;
    import com.github.unidbg.file.IOResolver;
    import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
    import com.github.unidbg.linux.android.AndroidResolver;
    import com.github.unidbg.linux.android.dvm.*;
    import com.github.unidbg.linux.android.dvm.array.ByteArray;
    import com.github.unidbg.linux.android.dvm.array.IntArray;
    import com.github.unidbg.linux.android.dvm.wrapper.DvmInteger;
    import com.github.unidbg.memory.Memory;
    import java.io.File;
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    public class Md5Crypt440 extends AbstractJni {
        private final AndroidEmulator emulator;
        private final Module module;
        private final VM vm;
        public String apkPath = "/Users/darbra/Downloads/apk/com.*/temp.apk";
        public String soPath2 = "/Users/darbra/Downloads/apk/com.*/lib/armeabi-v7a/libcryptoDD.so";
        Md5Crypt440() {
            emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.*").build();
            final Memory memory = emulator.getMemory();
            memory.setLibraryResolver(new AndroidResolver(23));
            vm = emulator.createDalvikVM(new File(apkPath));
            vm.setVerbose(true);
            vm.setJni(this);
            DalvikModule dm2 = vm.loadLibrary(new File(soPath2), true);
            dm2.callJNI_OnLoad(emulator);
            module = dm2.getModule();
        }
        public void call() {
            String methodId = "md5_crypt([BI)[B";
            DvmClass SigEntity = vm.resolveClass("com/luckincoffee/safeboxlib/CryptoHelper");
            String fakeInput1 = "cid=210101;q=j***=;uid=***";
            ByteArray inputByteArray1 = new ByteArray(vm, fakeInput1.getBytes(StandardCharsets.UTF_8));
            DvmObject ret = SigEntity.callStaticJniMethodObject(
                    emulator, methodId,
                    inputByteArray1,
                    1
            );
            byte [] strByte = (byte[]) ret.getValue();
            String strString = new String(strByte);
            System.out.println("callObject执行结果:"+ strString);
        }
        public static void main(String[] args) {
            Md5Crypt440 getSig = new Md5Crypt440();
            getSig.call();
            getSig.destroy();
        }
        private void destroy() {
            try {
                emulator.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    值得注意的是,这个app不用补任何环境,非常轻松地就运行出了结果。


    0007.png (279.95 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:30 上传

    结果和抓包、frida完全一致。
    我们在md5函数打个断点。
    public void HookByConsoleDebugger(){
        Debugger debugger = emulator.attach();
        debugger.addBreakPoint(module.base+0x13E3C);
    }


    0008.png (262.24 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:30 上传



    0009.png (259.75 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:30 上传

    输入mr0,我们可以看到第一个参数就是明文,但不够完整。


    00100.png (91.1 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:30 上传

    接着输入mr0 0x100,后面可以跟的是大小。我们欣喜地发现,之前的那坨明文后面加了个salt值,d**9


    0010.png (164.88 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:31 上传

    参数2,r1=0xef=239,我们去cyberchef看看这个明文长度是否为239


    0011.png (91.13 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:31 上传

    果不其然是的。
    接着输入mr2,查看第三个参数。


    0014.png (64.99 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:31 上传

    看情况参数3不出重大意外是buffer,所以我们需要hook它的返回值。在这里我们先记下r2的地址--->>> 0xbffff5d8。
    我们使用blr 命令用于在函数返回时设置一个一次性断点,然后c 运行函数,它在返回处断下来。
    接着输入刚刚记录下来的 m0xbffff5d8


    0023.png (740.18 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:31 上传

    我们去cyberchef进行验证,完全正确!


    0012.png (119.99 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:32 上传

    md5步骤解决了,接着查看bytesToInt。


    0015.png (102.41 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:32 上传

    我们在0x13924那里进行hook操作
    public void hookBytesToInt() {
            IHookZz hookZz = HookZz.getInstance(emulator);
            hookZz.wrap(module.base + 0x13924 + 1, new WrapCallback() {
                @Override
                public void preCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                    Inspector.inspect(ctx.getR0Pointer().getByteArray(0, 0x10), "参数1");
                    System.out.println("参数2->>" + ctx.getR1Int());
                };
                @Override
                public void postCall(Emulator emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
                    System.out.println("返回值->>" + ctx.getR0Int());
                }
            });
        }
    我们看一下输出结果了,四个输出值都能对应上最后的sign结果。


    0017.png (255.32 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:32 上传

    其中的正负号处理应该是对应的如下逻辑


    0018.png (33.35 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:32 上传

    我们写个小脚本还原下,与之前的抓包、frida、unidbg都一致,大功告成。


    0019.png (147.34 KB, 下载次数: 0)
    下载附件
    2022-1-14 13:33 上传

    在本人github.com/darbra/sign 有更多的一些思路交流,如果对老师们有所帮助,不甚欣喜。

    下载次数, 下载附件

  • darbra
    OP
      


    mmmaxxx2630 发表于 2022-1-14 15:48
    大佬用的工具,都木有见过啊。。。。。。。。。。。。。。

    unidbg不错的 很多大佬都在推荐
    darbra
    OP
      


    pxwhsh 发表于 2022-1-14 14:14
    very very good.  relax

    thank you very much indeed
    huozhuang12345   

    完全没看懂。。。。。
    SakeDawn   

    6666学习了
    pxwhsh   

    very very good.  relax
    不苦小和尚   

    md5加盐???
    朔月D   

    不敢说学习了,,看不懂啊。
    mmmaxxx2630   

    大佬用的工具,都木有见过啊。。。。。。。。。。。。。。
    elevo   

    我这思路有点没理清
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部