app sign so 加密算法分析还原|简单分析

android 逆向 17 / 37

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

const 龙哥 = Function() {}

const a = 全能的傻宝,每天都会换一种姿势来分享各种骚操作,10月份开始分享密码学;
const b = 点击加入星球;
return "无敌的龙哥";

推荐阅读

unidbg hook inline hook 使用
unidbg console debugger 使用
so 分析过程在验阶段会使用 unidbg debugger hook 功能,不熟悉的可以阅读以上文章
JD app sign so 加密算法分析还原|so 算法分析
JD app sign so 加密算法分析还原|so sub_126AC 函数算法还原

前言

前面分析了搜狗搜索 app 的 so 加解密逻辑,这次就来分析下 某东 app 的,继续学习 so 分析
app 版本 最新版 10.2.0

0x1

先来抓个包

随便点个请求,查看参数,这里有三个是 so 加密返回的

0x2

反编译 apk 查看加密函数

前面 java 层的分析就不说了,最终是找到了这个类 com.jingdong.common.utilsBitmapkitUtils,调用 getSignFromJni native 函数获取加密参数,一共有六个参数,具体的加密逻辑在 BitmapkitUtils.so 文件里,frida hook 看一下

0x3

frida hook

function hook() {
    var BitmapkitUtils = Java.use('com.jingdong.common.utils.BitmapkitUtils');

    BitmapkitUtils.getSignFromJni.implementation = function (a, b, c, d, e, f) {
        console.log('b: ', b);
        console.log('c: ', c);
        console.log('d: ', d);
        console.log('e: ', e);
        console.log('f: ', f);

        var res = this.getSignFromJni(a, b, c, d, e, f);

        console.log('resf: ', res);

        return res;
    }
}

function main() {
    Java.perform(function () {
        hook();
    })
}

setImmediate(main);

代码写完执行 frida -U -f com.jingdong.app.mall -l hook.js --no-pause | tee hook.log 命令,查看 hook.log 文件

函数的输入输出很明显,加密结果也能跟请求包对应起来,下面使用 frida 主动调用看看

frida call

function callBitmapkitUtils() {
    var BitmapkitUtils = Java.use('com.jingdong.common.utils.BitmapkitUtils');

    var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
    var context = currentApplication.getApplicationContext();

    var b = 'clientImage';
    var c = '{"moduleParams":{"18":"1565611060638","19":"1565229712150","25":"1567478504636","27":"1602488415048","28":"1631069159956","30":"1567404005627","32":"1567997588476","34":"1593508185597","35":"1568708316462","37":"1630293538664","42":"1623741761542","44":"1569247647090","46":"1588839806224","47":"1571295610042","61":"1582091758495","70":"1585279774645","74":"1586781606615"}}';
    var d = 'd5a585639f505b18';
    var e = 'android';
    var f = '10.2.0';

    var res = BitmapkitUtils.getSignFromJni(context, b, c, d, e, f);
    console.log('res: ', res);
}

function main() {
    Java.perform(function () {
        callBitmapkitUtils();
    })
}

setImmediate(main);

执行 frida -UF -l call.js

查看输出每次调用都不一样,应该是跟时间戳有关系,看 sign 的结果应该是 md5 or hmac,后面既然需要用到 unidbg debugger 功能那就需要先使用 unidbg 跑起来

0x4

使用 unidbg 调用 getSignFromJni 函数
这里的 so 有个坑,会调用 check_status 函数,校验 apk 的签名,有两种方式可以选择
1、直接 so patch 不执行这个函数,参考我之前的文章: JD app sign 加密参数破解 - unidbg
2、直接去补 so 的 check_status 函数,因为我们后面要去分析 so 算法还原,所以本次就选择这种方式

package com.xiayu.jingdong;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
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.memory.Memory;

import java.io.File;
import java.io.IOException;

public class JingDong1020Test extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;

    public String apkPath = "apk 文件路径";
    public String soPath = "so 文件路径";

    private static LibraryResolver createLibraryResolver() {
        return new AndroidResolver(23);
    }

    private static AndroidEmulator createARMEmulator() {
        return AndroidEmulatorBuilder
                .for32Bit()
                .build();
    }

    public JingDong1020Test() {
        emulator = createARMEmulator();
        final Memory memory = emulator.getMemory();
        memory.setLibraryResolver(createLibraryResolver());
        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setVerbose(true);

        DalvikModule dm = vm.loadLibrary(new File(soPath), false);
        vm.setJni(this);

        dm.callJNI_OnLoad(emulator);
        Module module = dm.getModule();
    }

    public void callGetSignFromJni() {
        DvmClass bitMapKitUtils = vm.resolveClass("com/jingdong/common/utils/BitmapkitUtils");

        DvmObject<?> strRc = bitMapKitUtils.callStaticJniMethodObject(
                emulator,
                "getSignFromJni()(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
                vm.addLocalObject(null),
                vm.addLocalObject(new StringObject(vm, "clientImage")),
                vm.addLocalObject(new StringObject(vm, "{\"moduleParams\":{\"18\":\"1565611060638\",\"19\":\"1565229712150\",\"25\":\"1567478504636\",\"27\":\"1602488415048\",\"28\":\"1631069159956\",\"30\":\"1567404005627\",\"32\":\"1567997588476\",\"34\":\"1593508185597\",\"35\":\"1568708316462\",\"37\":\"1630293538664\",\"42\":\"1623741761542\",\"44\":\"1569247647090\",\"46\":\"1588839806224\",\"47\":\"1571295610042\",\"61\":\"1582091758495\",\"70\":\"1585279774645\",\"74\":\"1586781606615\"}}")),
                vm.addLocalObject(new StringObject(vm, "d5a585639f505b18")),
                vm.addLocalObject(new StringObject(vm, "android")),
                vm.addLocalObject(new StringObject(vm, "10.2.0"))
        );

        System.out.println("callGetSignFromJni: " + strRc.getValue());
    }

    public static void main(String[] args) throws IOException {
        JingDong1020Test jdSign = new JingDong1020Test();

        jdSign.callGetSignFromJni();
        jdSign.destroy();
    }

    private void destroy() throws IOException {
        emulator.close();
    }
}

全部代码,写完跑起来

环境问题补起来,返回 Application

返回 base.apk 的文件路径

这个是调用了自定义的 com/jingdong/common/utils/BitmapkitZip->unZip 函数,目前没啥好的办法,只有去把 java 复制过来使用,第一个参数是需要解压的 apk 路径,所以我们传递的是本地的 apk 路径

一个加密参数,调用的是 java 内置函数,直接补

这里需要返回一个对象数组

接着又补了一些环境

在运行,结果就出来了,每次运行的结果不一样,下面使用 python 请求测试一下,结果是否可用

0x5

使用 java server 框架启动服务,在使用 python 调用 java 接口获取 sign 参数,测试是否可用

代码写完,结果是可以用的

最后

某东 unidbg 例子就写完了,后面开始去分析 so 具体算法

8 条评论
本文作者:
本文链接: https://www.qinless.com/?p=576
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

8 条评论

查哪

BitmapkitZip 反编译代码可以发我下吗,我这都是不全的,q857216084

回复

会爬山的小脑虎

@查哪 怎么会不全呢,我也是直接复制的

回复

查哪

@会爬山的小脑虎 jadx或者dex后unZip是空的

会爬山的小脑虎

@查哪 加微信联系 2027762055

嗄嗄

BitmapkitZip函数jadx解析不全,怎么拿全的代码呢?是smali还原吗?

回复

会爬山的小脑虎

@嗄嗄 对 jadx jeb 反编译都有点问题,没法直接用的,我是用 mt管理器 反编译复制的

回复

D0D

你好 我在使用unidbg 调用函数的时候 一直出现Exception in thread "main" java.lang.IllegalStateException: Illegal JNI version: 0xffffffff 这个错误 我这里也去修改了so里面的东西

回复

沈听白

@D0D 你已经解决这个问题了吗

回复

发表评论

返回顶部