zoukankan      html  css  js  c++  java
  • 酷狗缓存文件kgtemp的加密方式

    [转自:http://www.cnblogs.com/KMBlog/p/6877752.html]

    首先对比了一下缓存文件和下载好的mp3文件,发现缓存文件多了1024个字节,而且对比了几个缓存文件,前1024个字节都一样,看来使了个障眼法,去掉这1024个字节应该就是原版的音频数据了。

    然后下图是加密前后的对比:

    加密前加密后

    会发现加密前的一堆0x55 加密后变成 0xA9 0xE9 0xDA 0x52循环了,说明是用了4字节的循环加密,然后切换成2进制研究

    加密前 0x55 0x55 0x55 0x55   01010101 01010101 01010101 01010101

    加密后 0xA9 0xE9 0xDA 0x52   10101001 11101001 11011010 01010010

    对称逐字节加密的运算也就循环移位或者异或固定的数或者取反,但上面的几组数循环移位和取反都不太像,就先假设是异或固定的数A B C D,接下来做填空题:

    0x55 0x55 0x55 0x55   01010101 01010101 01010101 01010101

    A       B      C      D        11111100 10111100 10001111 00000111

    0xA9 0xE9 0xDA 0x52   10101001 11101001 11011010 01010010

    得出:A B C D分别为0xFC 0xBC 0x8F 0x07 ,然后取开头的数据验证:

    加密前 0x49 0x44 0x33 0x03   01001001 01000100 00110011 00000011

    xor     0x3C 0xAC 0xEF 0x67   00111100 10101100 11101111 01100111

    加密后 0x75 0xE8 0xDC 0x64   01110101 11101000 11011100 01100100

    这次的A B C D分别为0x3C 0xAC 0xEF 0x67

    纳尼?不是固定的?WTF! 

    两组A B C D低4位的数字都是 C C F 7

    看来最终结果确实是xor计算来的,只是高4位的数值要复杂一些。

    根据0 xor X =X的性质,我找了一组全0的加密前后的对比,

    加密前 0x00 0x00 0x00 0x00   00000000 00000000 00000000 00000000

    加密后 0xAC 0xEC 0xDF 0x57   10101100 11101100 11011111 01010111

    那A B C D高4位就对应 0xA 0xE 0xD 0x5

    再用开头的数据验证:

    加密前 0x49 0x44 0x33 0x03   01001001 01000100 00110011 00000011

    xor     0xAC 0xEC 0xDF 0x57  10101100 11101100 11011111 01010111

    加密后 0xE5 0xA8 0xEC 0x54 11100101 10101000 11101100 01010100

    还是不对,而且发现一点:只要加密前的数的高4位=低4位,加密后的高4位都固定为0xA 0xE 0xD 0x5

    这不就是xor 中的4个数的高4位吗,由(0 xor X=X)和(X xor X=0)可知,高4位的算法应该是这样的:

    分别取输入数的高4位和低4位H,L, 然后取xor的高4位I 结果Y= H xor L xor I

    带入前面的3组数据验算,都对了^_^

    撸码

    既然加密算法已经猜出来了,就撸码验证一下,看解密后的文件的MD5与缓存文件名是否相等:

    class Program
        {
            static void Main(string[] args)
            {
    
                byte[] key={0xAC,0xEC,0xDF,0x57};
                using (var input = new FileStream(@"E:KuGouTemp236909b6016c6e98365e5225f488dd7a.kgtemp", FileMode.Open, FileAccess.Read))
                {
                    var output = File.OpenWrite(@"d:	est.mp3");//输出文件
                    input.Seek(1024, SeekOrigin.Begin);//跳过1024字节的包头
                    byte[] buffer = new byte[key.Length];
                    int length;
                    while((length=input.Read(buffer,0,buffer.Length))>0)
                    {
                        for(int i=0;i<length;i++)
                        {
                            var k = key[i];
                            var kh = k >> 4;
                            var kl = k & 0xf;
                            var b = buffer[i];
                            var low = b & 0xf ^ kl;//解密后的低4位
                            var high = (b >> 4) ^ kh ^ low & 0xf;//解密后的高4位
                            buffer[i] = (byte)(high << 4 | low);
                        }
                        output.Write(buffer, 0, length);
                    }
                    output.Close();
                }
                Console.WriteLine("按任意键退出...");
                Console.ReadKey();
            }
        }

    结果:输出文件的MD5与缓存文件名相同,大功告成

    总结

    固定要异或的key={0xAC,0xEC,0xDF,0x57}

    加密方式如下:

    1.设输入的数为x,输出结果为y,循环变量为i;

    2.分别取x的高4位和低4位h,l;  h=x >> 4 ; l=x & 0xf;

    3.分别取key[i]的高4位和低4位kh,kl;kh=key[i] >> 4;kl=key[i] & 0xf;

    4.y=h ^ l ^ kh;

    5.y=y<< 4 | (l ^ kl);

    解密方式如下:

    1.设输入的数为x,输出结果为y,循环变量为i;

    2.分别取x的高4位和低4位h,l;h=x >> 4 ; l=x & 0xf;

    3.分别取key[i]的高4位和低4位kh,kl;kh=key[i] >> 4;kl=key[i] & 0xf;

    4.y=l ^ kl;

    5.y=(h ^ kh ^ y)<<4 | y;

  • 相关阅读:
    vue 组件
    vue 中的computed和watch
    Vue 框架 笔记
    初次使用git配置以及git如何使用ssh密钥(将ssh密钥添加到github)
    JavaScript 执行机制
    Vue.js 动画
    封装nodeJS中 $on $emit $off 事件
    JS中的事件委托
    什么是“闭包”(closure)为什么要用它?
    js使用面向对象编写下拉菜单
  • 原文地址:https://www.cnblogs.com/kennyliu/p/7684498.html
Copyright © 2011-2022 走看看