• android逆向奇技淫巧二十八:x音MD5使用分析


    1、MD5是业界非常成熟的hash算法了,原理不再赘述,这里介绍一下可以魔改的地方!

          

       (1)MD5默认输出是128bit,怎么改变这个长度了?MD5的结果是由4个32bit的ABCD组成的,原始取值如下:

    unsigned int A = 0x67452301; 
    unsigned int B = 0xEFCDAB89; 
    unsigned int C = 0x98BADCFE; 
    unsigned int D = 0x10325476;

      大家有没有发现啥规律了?16进制数从0开始分别是0123456789abcdef,直接按照4byte的长度截取使用了(注意MD5用的是小端,顺序刚好是反过来的),这不也是很明显的特征数么?所以这里完全可以换成其他没规律的数字;如果要想改变结果的长度,分别改变ABCD长度就行了;由此同样要改变明文Mi的分组长度和Ki的长度

            (2)上图只有Mi是明文,F和Ki出现的目的就是为了尽可能混淆或扩散明文和hash值,让明文和hash值之间找不到任何规律!所以F函数和Ki也是可以魔改的!原F函数如下:

    round 1: F(x,y,z) = (x & y) | (~x & z) //X为真就是Y;X为假就是Z
    round 2: G(x,y,z) = (x & z) | (y & ~z) :
    round 3: H(x,y,z) = x ^ y ^ z
    round 4: I(x,y,z) = y ^ ( x | ~z)

         完全可以替换成其他的函数,也可以调换顺序!同理,Ki原始值的计算方式是2^32 * |sin i |,而后取其整数部分, 原始的取值如下:

    const unsigned int k[] = {
          0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
          0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
          0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
          0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
          0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
          0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
          0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
          0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};

      这么多固定值的数,不是很容易被找到么?所以这里的三角函数sin完全可以换成cos、tg、ctg等其他函数。经过这些魔改后,特征数完全改变,想要查找就不那么容易了!

      2、之前用findcrypt在x音的libmetasec.so中找到了base64的码表,进而找到了X-Tyhon、X-Ladon、X-Argus生成代码的附近,但是还有X-Gorgon了,看着很像MD5类的算法,但是一直没找到,今天换个新插件试试:signsrch!居然找到了部分特征数,结果如下:

            

      (1)先看第一个,使用的地方在偏移0x6A5D4这里,来到代码这里后直接F5看看,还真有新发现:

              

       这不就是MD5的ABCD四个数么?继续进入里面的函数,在0x69D9C函数里面开始大量计算hash值了, 这里明显用到K表: 

                

      注意,原始值是10进制表示的,按H后转成16进制,但是F5识别成了补码,需要在数字上点击右键->invert sign才能看到正确的数字

            

       继续往下扒,在0x6A4F4偏移处开始用0x80填充了,如下:

            

       3、至此,可以明确x音肯定用了MD5算法,具体传入了哪些参数了?这个只能动态调试看看了! MD5的ABCD四个数都放栈上了,并且函数传入的是一串疑似URL内容的字符串!

             

       经过一系列骚操作后,栈上的ABCD变成这样了:这个结果后续会被用于X-Gorgon的构造(当然肯定不是简单粗暴地直接拿过来用)!

            

       同样的代码位置,还处理过这类“密文”数据:

        

       处理完的结果还是放栈上原ABCD的位置:

            

       其他遇到过计算MD5的字符串:

             

       这里把cronet、quic协议的版本都拿来求hash值了:

        

       堆内存居然偶遇了X-Gorgon,难道是malloc申请的内存使用后忘记free了?

            

       这里的1128后续会被用来生成X-Ladon字段:

           

     总结:

    1、算法模块特征: 

    • 进行大量的循环运算
    • 依赖运算相关的汇编指令,诸如XOR、AND、OR、NOT等(70%)
    • 加解密中信息熵的变化

    2、MD5的ABCD、K表内部的数据都是明文存储,很容易被找到,为啥对这些数据加密?为啥不通过某些公式计算出来,而是直接放明文了?我个人猜测:这类使用频率非常高的hash算法,如果把ABCD或K表加密,或用公式现场计算,效率肯定受影响,会降低用户体验的!其他某些地方加了OLLVM和VMP,已经导致client端计算效率降低了,如果再在这里加固,效率怕是直接跌倒地板,用户都跑光了,要安全有啥用了?

    3、MD5除了F函数,在和明文运算的时候为啥不用异或了? 

      (1)如果用异或,需要IV或key,接收端验证的时候也要这个,该怎么得到这两个了?除非提前通过其他方式获取,比如DH算法交换双方的公钥后生成key,然后HMAC算法使用key和明文一起生成hash值,所以HMAC的本质相当于用key加盐了!

           (2)异或有个特性,满足“交换律”:如果A^B=C,那么A^C=B或则B^C=A;一旦key泄漏,结合得到的hash值,可能反推出明文,就不安全了!

    参考:

    1、https://cloud.tencent.com/developer/article/1806329   MD5 C源码

  • 相关阅读:
    OpenJudge 2764 数根 C++
    OpenJudge / Poj 1835 宇航员 C++
    elasticsearch系统性能调优总结
    ES基本查询总结
    Vim最全快捷键键位图
    Idea常用插件整合
    微信小程序开发资源汇总
    Java JNI调用本地动态库使用详解
    java开发调试定位分析工具大全
    Redux-saga使用教程详解
  • 原文地址:https://www.cnblogs.com/theseventhson/p/16278741.html
Copyright © 2020-2023  润新知