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

密码学学习记录 2 / 18

样本来自 Litt1eQ 大佬的公众号 Coder小Q

分析之前可以先使用 unidbg 跑一下,方便动态调试分析

样本逻辑比较简单,只有一个静态的 native 函数,打开 so 即可分析

分析总结:这个样本改的比较彻底,abcd 顺序颠倒,循环左移的位数、K表等

so 分析

分析 sub_990 函数

前面是数据填充,跟常量定义

在往下就是四轮循环,可以看到循环左移的位数也都被改变了

最后就是数据拼接了,核心逻辑就是上面的循环,也就是 transform 函数

python 还原

0x1 定义常量

  • 1、md 缓冲器(四个常量)

so 里的常量在这里,循序的可以通过名称来确定,v57 类型是 int64 咱们直接拆成两个就行了,高位在前,低位在后,最后结果就是

A = 0x10325476
B = 0xEFCDAB89
C = 0x67452301
D = 0x98BADCFE
  • 2、常数组 T(正弦函数表)

v11 是我们输入的数据 TK 也就是(正弦函数表,我这里改了名字的),一共有 64 个

T = [
    0x8A51407D, 0x6A88995D, 0xFD7025F4, 0xA7553036, 0x489E15C1, 0xF5CDB84B, 0xC0FFBCF6, 0x253F7D7E, 
    0xE93FD535, 0xD6CD6448, 0x01220AE4, 0xD806D023, 0xE84E6EA9, 0x230135D8, 0xC27AE834, 0xF5292BF4, 
    0x46711AC1, 0xA90A840A, 0xFD1BBEF0, 0x687810E5, 0x8C37FC1B, 0xFFFD6EC6, 0x8867BEAC, 0x6C96FED4, 
    0xFDBF77AC, 0xA59C8134, 0x4AC99BE5, 0xF66D568A, 0xBF80B2C1, 0x277D05E4, 0xEA2C8E1F, 0xD58FA982, 
    0x03661ADB, 0xD93BE6CA, 0xE7585F52, 0x20C23A76, 0xC3F22CE1, 0xF47FB4D2, 0x4442B612, 0xAABC73EB, 
    0xFCC24453, 0x66657006, 0x8E1BE7C3, 0xFFF5BB27, 0x867B8079, 0x6EA336BB, 0xFE09B282, 0xA3E07FDA, 
    0x4CF3A208, 0xF708037E, 0xBDFDD143, 0x29B9C389, 0xEB1494A7, 0xD44DA632, 0x05AA195E, 0xDA6CA20A, 
    0xE65DAC20, 0x1E8296E0, 0xC5658374, 0xF3D1564B, 0x4212F2E5, 0xAC6AF723, 0xFC63B7E7, 0x6450C165
]
  • 3、循环左移位数(我这里称之为 S)
s1 = [25, 20, 15, 10] * 4
s2 = [27, 23, 18, 12] * 4
s3 = [28, 21, 16, 9] * 4
s4 = [26, 22, 17, 11] * 4
S = s1 + s2 + s3 + s4

0x2 数据填充

  • 这个是标准的

0x3 四轮循环

  • 这个需要先确定 abcd 循序
a = FF(a, b, c, d, M[0], S[0], T[0])
d = FF(d, a, b, c, M[1], S[1], T[1])
c = FF(c, d, a, b, M[2], S[2], T[2])
b = FF(b, c, d, a, M[3], S[3], T[3])

这是标准的代码(博主测试过,这个样本不是标准的),那要咋确定呢,其实也简单

改了名称之后,整体逻辑都比较清晰了,所以直接 copy so 循序即可

c = b + ROR4(c + ((a & d) | (b & ~a)) + M[0] + T[0], S[0])
a = c + ROR4(a + ((b & d) | (c & ~d)) + M[1] + T[1], S[1])
d = a + ROR4(d + ((c & b) | (a & ~b)) + M[2] + T[2], S[2])
b = d + ROR4(b + ((a & c) | (d & ~c)) + M[3] + T[3], S[3])

最终循序也就是这样的

unidbg

  • 可以使用 unidbg 动态调试,或者 hook 验证代码逻辑是否正确,博主提供一段 hook 代码,大家自行体会
public void inlineHook() {
    // 第一轮 hook
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xA66)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第一轮循环 md5C R3 25: 0x" + Long.toHexString(ctx.getR3Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xA66, module.base + 0xA66, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xA7A)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第一轮循环 md5A R2 20: 0x" + Long.toHexString(ctx.getR2Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xA7A, module.base + 0xA7A, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xA90)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第一轮循环 md5D R1 15: 0x" + Long.toHexString(ctx.getR1Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xA90, module.base + 0xA90, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xAAC)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第一轮循环 md5B R0 10: 0x" + Long.toHexString(ctx.getR0Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xAAC, module.base + 0xAAC, null);

    // 第二轮 hook
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xAFA)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第二轮循环 md5C R3 27: 0x" + Long.toHexString(ctx.getR3Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xAFA, module.base + 0xAFA, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xB1A)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第二轮循环 md5A R2 23: 0x" + Long.toHexString(ctx.getR2Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xB1A, module.base + 0xB1A, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xB3A)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第二轮循环 md5D R1 18: 0x" + Long.toHexString(ctx.getR1Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xB3A, module.base + 0xB3A, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xB5A)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第二轮循环 md5B R0 12: 0x" + Long.toHexString(ctx.getR0Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xB5A, module.base + 0xB5A, null);

    // 第三轮 hook
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xBAE)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第三轮循环 md5C R3 28: 0x" + Long.toHexString(ctx.getR3Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xBAE, module.base + 0xBAE, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xBCE)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第三轮循环 md5A R2 21: 0x" + Long.toHexString(ctx.getR2Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xBCE, module.base + 0xBCE, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xBEA)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第三轮循环 md5D R1 16: 0x" + Long.toHexString(ctx.getR1Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xBEA, module.base + 0xBEA, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xBF6)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第三轮循环 md5B R0 9: 0x" + Long.toHexString(ctx.getR0Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xBF6, module.base + 0xBF6, null);

    // 第四轮 hook
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xC40)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第四轮循环 md5C R3 26: 0x" + Long.toHexString(ctx.getR3Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xC40, module.base + 0xC40, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xC58)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第四轮循环 md5A R2 22: 0x" + Long.toHexString(ctx.getR2Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xC58, module.base + 0xC58, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xC76)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第四轮循环 md5D R1 17: 0x" + Long.toHexString(ctx.getR1Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xC76, module.base + 0xC76, null);
    emulator.getBackend().hook_add_new(new CodeHook() {
        @Override
        public void hook(Backend backend, long address, int size, Object user) {
            if (address == (module.base + 0xC8E)) {
                Arm32RegisterContext ctx = emulator.getContext();
                System.out.println("第四轮循环 md5B R0 11: 0x" + Long.toHexString(ctx.getR0Long()));
            }
        }

        @Override
        public void onAttach(UnHook unHook) {

        }

        @Override
        public void detach() {

        }
    }, module.base + 0xC8E, module.base + 0xC8E, null);
}

最后

unidbg 输入 1638845144244 结果 F7CE6906C0E04E6CEE43DD38575D1D9F

使用 python 输入输出也都是相同的

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

发表评论

返回顶部