吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11010|回复: 78
收起左侧

[Android 原创] 某东到家 app so signkeyV1 参数分析

  [复制链接]
qinless 发表于 2021-11-12 14:14
本帖最后由 qinless 于 2021-11-12 18:49 编辑

前言

京东到家 app signKeyv1 参数分析,版本 8.14.0

charles 抓包

1636696957152-0.png

就是 djencrypt 这个参数,是一个加密串,分析一下

java 层分析

1636696957152-1.png

全局搜索定位到这个函数 base.net.volley.BaseStringRequest.getParams,跟进 DaojiaAesUtil.encrypt 看看

1636696957152-2.png

在跟进 AesCbcCrypto.encrypt 这个函数

1636696957152-3.png

里面写的还是比较清楚的,加密方式是 AES/CBC/PKCS5Padding 使用 cyberchef 解密试试

1636696957152-4.png

解密成功,主要是分析这个 signKeyV1 参数,看长度是 64,猜测是 sha256 加密,分析一下

1636696957152-5.png

全局搜索定位到这里,调用 k2 native 函数获取的,在 libjdpdj.so 文件里

1636696957152-6.png

打开 so 进入 JNI_OnLoad 函数,这里是动态注册的,点击 off_117004

1636696957152-7.png

这里看到,函数注册列表,点进 gk2 函数

1636696957152-8.png

前面是一些数据处理,下面有个 j_hmac_sha256 函数,可以确实是用的 hmac sha256 算法

1636696957152-9.png

这里的符号都没去掉,init update final 函数都能看到,这里应该是标准的算法,因为使用的是 openssl 库,先写个 frida hook 一下

frida hook

function hook() {
    var javaString = Java.use('java.lang.String');
    var zCls = Java.use('jd.net.z');

    zCls.k2.implementation = function (a) {
        console.log('zCls.k2.a: ', javaString.$new(a));

        var res = this.k2(a);
        console.log('zCls.k2.res: ', res);

        return res;
    }
}

这里 hook java k2 函数的输入输出


function hookSo1() {
    var hmac_sha256 = Module.findExportByName('libjdpdj.so', 'hmac_sha256')
    var HMAC_CTX_init = Module.findExportByName('libjdpdj.so', 'HMAC_CTX_init')
    var HMAC_Update = Module.findExportByName('libjdpdj.so', 'HMAC_Update')
    var HMAC_Init_ex = Module.findExportByName('libjdpdj.so', 'HMAC_Init_ex')

    Interceptor.attach(hmac_sha256, {
        onEnter: function (args) {
            console.log('hmac_sha256 参数 1: ', hexdump(args[0]));
            console.log('hmac_sha256 参数 2: ', hexdump(args[1]));
            console.log('hmac_sha256 参数 3: ', hexdump(args[2]));
            console.log('hmac_sha256 参数 4: ', hexdump(args[3]));
        },
        onLeave: function (retValue) {
        }
    })

    Interceptor.attach(HMAC_CTX_init, {
        onEnter: function (args) {
            console.log('HMAC_CTX_init 参数 1: ', hexdump(args[0]));
        },
        onLeave: function (retValue) {
        }
    })

    Interceptor.attach(HMAC_Update, {
        onEnter: function (args) {
            console.log('HMAC_Update 参数 1: ', hexdump(args[0]));
            console.log('HMAC_Update 参数 2: ', hexdump(args[1], {length: 1200}));
            console.log('HMAC_Update 参数 3: ', hexdump(args[2]));
        },
        onLeave: function (retValue) {
        }
    })

    Interceptor.attach(HMAC_Init_ex, {
        onEnter: function (args) {
            console.log('HMAC_Init_ex 参数 1: ', hexdump(args[0]));
            console.log('HMAC_Init_ex 参数 2: ', hexdump(args[1]));
            console.log('HMAC_Init_ex 参数 3: ', hexdump(args[2]));
            console.log('HMAC_Init_ex 参数 4: ', hexdump(args[3]));
            console.log('HMAC_Init_ex 参数 5: ', hexdump(args[4]));
        },
        onLeave: function (retValue) {
        }
    })
}

这里在 hook 一些 so 函数,hamc 会有个 key 一般在 init 的时候初始化

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

启动脚本 frida -UF -l hook.js | tee hook.log

1636696957152-10.png

k2 函数的输入是请求参数

1636696957152-11.png

HMAC_Init_ex so 函数的参数二,长度 32 猜测是 hamc key

1636696957152-12.png

HMAC_Update 函数是请求参数

1636696957152-13.png

最后的加密结果 ae07cde50402ef91660dea93dc196f7f82e7bc04322baf4022dc2879434f3fae 是这个,来验证一下

1636696957152-14.png

使用 cyberchef 加密,结果一样,正是 hmac sha256

Tips: 下面在使用 unidbg 跑起来,毕竟多掌握一些工具总有用处

unidbg

package com.xiayu.jingdongdaojia;

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

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

public class SignKeyV1Test extends AbstractJni {
    private final AndroidEmulator emulator;
    private final Module module;
    private final VM vm;

    public String apkPath = "apk path";
    public String soPath = "so path";

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

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

    public SignKeyV1Test() {
        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 = dm.getModule();
    }

    public void callGetSignKeyV1() {
        DvmClass zClass = vm.resolveClass("jd/net/z");

        DvmObject<?> strRc = zClass.callStaticJniMethodObject(
                emulator,
                "k2([B)Ljava/lang/String;",
                new ByteArray(vm, "参数".getBytes())
        );

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

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

        signKeyV1.callGetSignKeyV1();
        signKeyV1.destroy();
    }

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

代码写完跑起来

1636696957152-15.png

这报错了,缺少函数 jd/utils/StatisticsReportUtil->getSign()Ljava/lang/String; 调用的是京东到家 apkjava 代码

1636696957152-16.png

点进来看一下,打开逻辑是获取 apk 的签名之类的,这里的依赖比较多,不是很好补,一般签名啥的都是固定,直接 frida call 一下,获取返回值

function callGetSign() {
    var StatisticsReportUtil = Java.use('jd.utils.StatisticsReportUtil');

    var res = StatisticsReportUtil.getSign();
    console.log(res)
}

运行成功,获取返回值

1636696957152-17.png

unidbg 补一下,直接写死字符串

1636696957152-18.png

再次运行结果出来了,结果相同

Tips: 后面在打算学习学习 ida gdb 动态调试,暂时留空

IDA 动态调试

// TODO

GDB 动态调试

// TODO

免费评分

参与人数 17吾爱币 +18 热心值 +16 收起 理由
way226510 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
shili180 + 1 + 1 用心讨论,共获提升!
hjhj525 + 1 + 1 我很赞同!
wyf321 + 1 我很赞同!
neal5808 + 1 + 1 我很赞同!
tandz + 1 + 1 我很赞同!
NOVASECMOYU + 1 我很赞同!
dialga + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
pousse + 1 + 1 我很赞同!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
枼小天 + 3 + 1 厉害,先存着晚点看
-yuy- + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
llwen2 + 1 + 1 热心回复!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
shiina0831 + 1 + 1 谢谢@Thanks!
hxd97244 + 1 + 1 厉害,厉害,这工具有的都没见过
chengang5301 + 1 感谢您的宝贵建议,我们会努力争取做得更好!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

ccb0429 发表于 2021-11-12 20:04
看到一个也是原创的  图片都一模一样   如果是一个人 当我没说   支持分享
https://bbs.pediy.com/thread-270228.htm

点评

@qinless 看雪这个帖子是本人发的吗?  详情 回复 发表于 2021-11-17 15:47
 楼主| qinless 发表于 2021-11-14 11:00
 楼主| qinless 发表于 2021-11-17 16:53
 楼主| qinless 发表于 2021-11-12 22:59
Jack150 发表于 2021-11-12 21:55
能用 frida和 Unidbg 两个工具搞出来,厉害。。  如果可以出个能够更详细的分析so文件的就更好了。

目前本人还很菜,只能分析这种简单没啥对抗的 so,遇到有对抗的就歇菜了,大佬如果有兴趣可以看看个人博客,会定期分享一些学习成果,https://www.qinless.com
 楼主| qinless 发表于 2021-11-12 14:32
初次发帖,没注意图片顺序搞反了,管理组看到麻烦帮忙删了,稍后重新发帖
Jack150 发表于 2021-11-12 21:55
能用 frida和 Unidbg 两个工具搞出来,厉害。。  如果可以出个能够更详细的分析so文件的就更好了。
 楼主| qinless 发表于 2021-11-12 22:57
ccb0429 发表于 2021-11-12 20:04
看到一个也是原创的  图片都一模一样   如果是一个人 当我没说   支持分享
https://bbs.pediy.com/thread- ...

谢谢大佬支持
ysy2001 发表于 2021-11-13 07:47
只能膜拜大佬,谢谢。
dazhujianhui 发表于 2021-11-13 10:08
膜拜  真的是看不懂  
hxd97244 发表于 2021-11-13 10:26
ccb0429 发表于 2021-11-12 20:04
看到一个也是原创的  图片都一模一样   如果是一个人 当我没说   支持分享
https://bbs.pediy.com/thread- ...

害我专门跑去原贴看了下,确实一样。
shiina0831 发表于 2021-11-13 10:36
过来学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-4 22:10

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表