??? 我注意到UC的時候它的版本是v2.40,那時UC的聊天數(shù)據(jù)就已經(jīng)加密了,,一直到現(xiàn)在的UC2005(內(nèi)部版本號好象是什么4.10.625)。另外軟件本身也加了殼,在這一點上,UC比QQ做的好那么一點。然而,它的聊天文本加密是一個典型的完全不顧及密碼學(xué)基本常識的蹩腳作品。我是說,它居然使用固定密鑰!!!實際上再好的公開算法,也經(jīng)不住固定密鑰的糟蹋。真是可惜呀。
?
??? 關(guān)于Blowfish:Blowfish算法是密碼學(xué)牛人Bruce Schneier設(shè)計的算法,是一個64位分組,變長密鑰的分組密碼算法。據(jù)作者本人講,設(shè)計這個算法要達(dá)到四個目標(biāo):Fast,Compact, Simple和Variably Secure,想來應(yīng)該是做到了。我不是十分清楚對該算法的分析現(xiàn)在達(dá)到了什么境界,不過本文目的不是去分析算法,而是針對特定的錯誤應(yīng)用找出其中的漏洞。因此我們只要能辨認(rèn)出這個算法就可以了。
?
??? 這個算法明顯的匯編特征是,需要維護(hù)一個不小的表,加密的輪函數(shù)需要不斷查表以進(jìn)行運算。具體一點說是4個100h元的數(shù)組,每個元是一個32位整數(shù)。總計大小4*400h*4=1000h字節(jié)。另外附近還有一個18個元素的表,每個元素也是4字節(jié)。這些表的數(shù)值由加密密鑰初始化而得到,但是在以后的加密過程中這個表是只讀的,就是說其中的數(shù)據(jù)是不變的。表的使用方法是,把輸入的整數(shù)拆分成四個字節(jié),分別作四次查表,得到的結(jié)果作加法和異或運算后得到最后的該輪運算的結(jié)果。如果你看到某加密算法的匯編代碼中有這樣特征的話,十有八九就是Blowfish了。
?
??? 分析UC的過程,這里以UC2.40為例。首先查殼,ASPack 2.11 -> Alexey Solodovnikov(后來變成了ASPack 2.12),脫殼過程就不贅述了,跟蹤也不難,稍微細(xì)心一點,我們應(yīng)該很快就能找到對數(shù)據(jù)進(jìn)行加密處理的地方。一層層鉆進(jìn)call里面去后,我們可以看到下面這樣一段代碼:
.text:005F92D4 sub_5F92D4????? proc near?????????????? ; CODE XREF: sub_5F9330+23 p
.text:005F92D4???????????????????????????????????????? ; sub_5F9394+24 p
.text:005F92D4
.text:005F92D4 var_2?????????? = word ptr -2
.text:005F92D4 arg_0?????????? = dword ptr? 8
.text:005F92D4 arg_4?????????? = dword ptr? 0Ch
.text:005F92D4
.text:005F92D4???????????????? push??? ebp
.text:005F92D5???????????????? mov???? ebp, esp
.text:005F92D7???????????????? push??? ecx
.text:005F92D8???????????????? push??? ebx
.text:005F92D9???????????????? mov???? eax, [ebp+arg_4]
.text:005F92DC???????????????? mov???? edx, [ebp+arg_0]
.text:005F92DF???????????????? mov???? ecx, eax
.text:005F92E1???????????????? and???? cx, 0FFh
.text:005F92E6???????????????? mov???? [ebp+var_2], cx
.text:005F92EA???????????????? shr???? eax, 8
.text:005F92ED???????????????? mov???? ebx, eax
.text:005F92EF???????????????? and???? bx, 0FFh
.text:005F92F4???????????????? shr???? eax, 8
.text:005F92F7???????????????? mov???? ecx, eax
.text:005F92F9???????????????? and???? cx, 0FFh
.text:005F92FE???????????????? movzx?? ecx, cx
.text:005F9301???????????????? shr???? eax, 8
.text:005F9304???????????????? and???? ax, 0FFh ; 到這里之前把輸入拆成了4個單字節(jié)
.text:005F9308???????????????? movzx?? eax, ax
.text:005F930B???????????????? mov???? eax, [edx+eax*4+48h] ; 這里
.text:005F930F???????????????? add???? eax, [edx+ecx*4+448h] ; 這里
.text:005F9316???????????????? movzx?? ecx, bx
.text:005F9319???????????????? xor???? eax, [edx+ecx*4+848h] ; 這里
.text:005F9320???????????????? movzx?? ecx, [ebp+var_2]
.text:005F9324???????????????? add???? eax, [edx+ecx*4+0C48h] ; 這里
.text:005F932B???????????????? pop???? ebx
.text:005F932C???????????????? pop???? ecx
.text:005F932D???????????????? pop???? ebp
.text:005F932E???????????????? retn
.text:005F932E sub_5F92D4????? endp
?
?
??? 看到了嗎?EDX這個地方是一個18元的整數(shù)表,其實也就是Blowfish代碼中維護(hù)的P盒,18*4=72=48h,那么EDX+48h,EDX+448h,EDX+848h和EDX+C48h就是S盒了,每個大小400h。標(biāo)注“這里”的這四句是四次查表運算,結(jié)果放在EAX里返回。完全和Blowfish的輪函數(shù)F相同,所以看到這里,基本可以確定算法就是Blowfish了。多次觀察加密過程,可以發(fā)現(xiàn)這個表里的數(shù)據(jù)總是不變的,說明UC的運行沒有任何密鑰協(xié)商過程,用的是固定密鑰。
?
??? Bruce原來的代碼(
http://www.schneier.com/code/bfsh-sch.zip)中用P,S來命名,我覺得不大好,所以我改寫的時候稍微把名字加長了些。
?
??? 由于固定密鑰,為了代碼的簡便,我選擇了直接從內(nèi)存里(7B0034)把這段生成好的1048h字節(jié)數(shù)據(jù)扒下來,寫在了我的解密代碼中,這也就是我的代碼中P_BOX和S_BOX的來歷。這樣做一個好處是省去了調(diào)用InitializeBlowfish函數(shù)的時間,另外也真正做到專碼專用了。只要UC一天不改,這代碼就一天有效,決不含糊。
?
??? 現(xiàn)在的UC還是一直就使用這樣的算法,至少兩年都沒改過了,而且還把新浪Web聊天室也如此包裝了一下。解密既然不難,接下來的事情其實就都沒有難度了,我隨便分析了一下,寫了個ucsniffer。
?
??? 關(guān)于UC的語音聊天沒有仔細(xì)研究,如果沒改動過的話,應(yīng)該還是明碼,直接在線收聽或者錄下來慢慢聽都是可以實現(xiàn)的。