閑來無事研究一下酷狗緩存文件kgtemp的加密方式


此貼為本人原創,轉載請注明出處

前幾天更新了被打入冷宮很久的酷狗,等進入之后就感覺菊花一緊————試 聽 居 然 都 要 開 通 音 樂 包(高品和無損)才行了,WTF!

這意味着以前緩存的都聽不了了,本着好馬不吃回頭草的原則,不打算去降級了,下載PJ版的又擔心被植入惡意代碼,心好累╮(╯▽╰)╭

作為一個程序猿,豈能被你這小陰招就擊敗,定要給你點顏色看看!

探索

首先對比了一下緩存文件和下載好的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:\KuGou\Temp\236909b6016c6e98365e5225f488dd7a.kgtemp", FileMode.Open, FileAccess.Read))
            {
                var output = File.OpenWrite(@"d:\test.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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM