密码学学习记录|hash md5 算法练习样本二

密码学学习记录 3 / 18

前言

样本 app https://www.wandoujia.com/apps/280945 版本 15.25.1

分析总结:这个样本是标准的 md5 算法,但是因为对 md5 不太了解,导致还原了 so 算法之后才发现,如果大家时间充足的话,还是推荐还原一下 so md5 算法

charles 抓包

就是这个 nsign 参数

java 层的逻辑就不在分析了,后面直接分析 so

frida hook

function getMapData(mapSet) {
    try {
        var result = {};
        var key_set = mapSet.keySet();
        var it = key_set.iterator();
        while (it.hasNext()) {
            var key_str = it.next().toString();
            result[key_str] = mapSet.get(key_str).toString();
        }
        return result
    } catch (error) {
        return mapSet
    }
}

function getProcessId() {
    var androidProcess = Java.use('android.os.Process');
    return 'processId: ' + androidProcess.myTid() + ' - ';
}

function printLog() {
    var result = '';

    for (var i = 0; i < arguments.length; i++) {
        result += arguments[i] + ' ';
    }

    console.log(getProcessId(), result)
}

Java.perform(function () {
    var SignUtil = Java.use('com.anjuke.mobile.sign.SignUtil');

    SignUtil.getSign0.implementation = function (a, b, c, d, e) {
        printLog('SignUtil.getSign0.a: ', a);
        printLog('SignUtil.getSign0.b: ', b);
        printLog('SignUtil.getSign0.c: ', c);
        printLog('SignUtil.getSign0.c: ', JSON.stringify(getMapData(c)));
        printLog('SignUtil.getSign0.d: ', d);
        printLog('SignUtil.getSign0.e: ', e);

        var res = this.getSign0(a, b, c, d, e);
        printLog('SignUtil.getSign0.res: ', res);

        return res;
    }
})

先使用 frida hook 一下,看看函数的输入输出时候

这个 c 参数是个 mapbyte[] 的数据没打印出来,不过都在 url params 里,可以根据 key 查找

so 分析

打开 libsignutil.so 文件

搜索 java 关键词,分析 getSign0 函数

点进 j_get_sign 函数

这里的 qsort 看起来是排序函数,下面又拼接上了一个盐值,最后调用了 j_SIGNMD5 函数

这个函数就比较清晰了,前面定义了四个 md5 的常量,接着调用了 update 函数

这是调用 transform 函数逻辑

transform 函数里的一些常量看起来不是标准的(实际上是标准的,博主也很疑惑,有清楚的小伙伴还望指点一下)

unidbg

接着使用 unidbg 辅助分析 so,大家自行先跑起来

final Pointer[] md5updater0 = {null};
emulator.getBackend().hook_add_new(new CodeHook() {
    @Override
    public void hook(Backend backend, long address, int size, Object user) {
        if (address == (module.base + 0x11D4)) {
            Arm32RegisterContext ctx = emulator.getContext();

            md5updater0[0] = ctx.getR0Pointer();

            Inspector.inspect(md5updater0[0].getByteArray(0, ctx.getR2Int() + 10), " md5 update params r0 ");
            Inspector.inspect(ctx.getR1Pointer().getByteArray(0, ctx.getR2Int() + 10), " md5 update params r1 ");
            System.out.println("md5 update params r2 " + ctx.getR2Int());
        }
    }

    @Override
    public void onAttach(UnHook unHook) {
    }

    @Override
    public void detach() {
    }
}, module.base + 0x11D4, module.base + 0x11D4, null);

跑起来之后,先 hook md5 update 函数的参数(获取到输入之后,就可以开始还原算法了)

so md5 还原

md5 算法的还原步骤

  • 1、定义四个常量

  • 2、定义 T数组(正弦函数表)

  • 3、定义循环左移数(当然这个样本是循环右移)

  • 4、确定 a, b, c, d 顺序(这个样本是标准的,唯一的区别是 + - 符号,可以参照 so 算法看一下)

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

2 条评论

feng504x

同感, 之前b站 安全第四题也是 标准md5, 然而后边才发现~~~

回复

会爬山的小脑虎

@feng504x 确实 懵逼

回复

发表评论

返回顶部