此貼為本人原創,轉載請註明出處 序 前幾天更新了被打入冷宮很久的酷狗,等進入之後就感覺菊花一緊————試 聽 居 然 都 要 開 通 音 樂 包(高品和無損)才行了,WTF! 這意味著以前緩存的都聽不了了,本著好馬不吃回頭草的原則,不打算去降級了,下載PJ版的又擔心被植入惡意代碼,心好累╮(╯▽╰) ...
此貼為本人原創,轉載請註明出處
序
前幾天更新了被打入冷宮很久的酷狗,等進入之後就感覺菊花一緊————試 聽 居 然 都 要 開 通 音 樂 包(高品和無損)才行了,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;