UC加密算法與解密
概述:
??? UC是一款比較有名的國產聊天軟件,早先由longmaster開發,現在已經被新浪收購。目前新浪Web語音聊天室也已經改裝為使用UC插件了。這樣一來新浪的Web聊天室看上去也很“安全”了。
?
??? 本文談談UC的文本加密方法,主要還是講分析方法要點和Blowfish的特征,因為結果本身并沒有什么好講的,還原實現直接看代碼就可以了。
?
?http://www.team509.com/download/ucsniffer.rar
?http://www.team509.com/download/ucsniffer.src.rar
?
??? 本文談談UC的文本加密方法,主要還是講分析方法要點和Blowfish的特征,因為結果本身并沒有什么好講的,還原實現直接看代碼就可以了。
?
?http://www.team509.com/download/ucsniffer.rar
?http://www.team509.com/download/ucsniffer.src.rar
正文:
??? 我注意到UC的時候它的版本是v2.40,那時UC的聊天數據就已經加密了,,一直到現在的UC2005(內部版本號好象是什么4.10.625)。另外軟件本身也加了殼,在這一點上,UC比QQ做的好那么一點。然而,它的聊天文本加密是一個典型的完全不顧及密碼學基本常識的蹩腳作品。我是說,它居然使用固定密鑰!!!實際上再好的公開算法,也經不住固定密鑰的糟蹋。真是可惜呀。
?
??? 關于Blowfish:Blowfish算法是密碼學牛人Bruce Schneier設計的算法,是一個64位分組,變長密鑰的分組密碼算法。據作者本人講,設計這個算法要達到四個目標:Fast,Compact, Simple和Variably Secure,想來應該是做到了。我不是十分清楚對該算法的分析現在達到了什么境界,不過本文目的不是去分析算法,而是針對特定的錯誤應用找出其中的漏洞。因此我們只要能辨認出這個算法就可以了。
?
??? 這個算法明顯的匯編特征是,需要維護一個不小的表,加密的輪函數需要不斷查表以進行運算。具體一點說是4個100h元的數組,每個元是一個32位整數。總計大小4*400h*4=1000h字節。另外附近還有一個18個元素的表,每個元素也是4字節。這些表的數值由加密密鑰初始化而得到,但是在以后的加密過程中這個表是只讀的,就是說其中的數據是不變的。表的使用方法是,把輸入的整數拆分成四個字節,分別作四次查表,得到的結果作加法和異或運算后得到最后的該輪運算的結果。如果你看到某加密算法的匯編代碼中有這樣特征的話,十有八九就是Blowfish了。
?
??? 分析UC的過程,這里以UC2.40為例。首先查殼,ASPack 2.11 -> Alexey Solodovnikov(后來變成了ASPack 2.12),脫殼過程就不贅述了,跟蹤也不難,稍微細心一點,我們應該很快就能找到對數據進行加密處理的地方。一層層鉆進call里面去后,我們可以看到下面這樣一段代碼:
?
??? 關于Blowfish:Blowfish算法是密碼學牛人Bruce Schneier設計的算法,是一個64位分組,變長密鑰的分組密碼算法。據作者本人講,設計這個算法要達到四個目標:Fast,Compact, Simple和Variably Secure,想來應該是做到了。我不是十分清楚對該算法的分析現在達到了什么境界,不過本文目的不是去分析算法,而是針對特定的錯誤應用找出其中的漏洞。因此我們只要能辨認出這個算法就可以了。
?
??? 這個算法明顯的匯編特征是,需要維護一個不小的表,加密的輪函數需要不斷查表以進行運算。具體一點說是4個100h元的數組,每個元是一個32位整數。總計大小4*400h*4=1000h字節。另外附近還有一個18個元素的表,每個元素也是4字節。這些表的數值由加密密鑰初始化而得到,但是在以后的加密過程中這個表是只讀的,就是說其中的數據是不變的。表的使用方法是,把輸入的整數拆分成四個字節,分別作四次查表,得到的結果作加法和異或運算后得到最后的該輪運算的結果。如果你看到某加密算法的匯編代碼中有這樣特征的話,十有八九就是Blowfish了。
?
??? 分析UC的過程,這里以UC2.40為例。首先查殼,ASPack 2.11 -> Alexey Solodovnikov(后來變成了ASPack 2.12),脫殼過程就不贅述了,跟蹤也不難,稍微細心一點,我們應該很快就能找到對數據進行加密處理的地方。一層層鉆進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個單字節
.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元的整數表,其實也就是Blowfish代碼中維護的P盒,18*4=72=48h,那么EDX+48h,EDX+448h,EDX+848h和EDX+C48h就是S盒了,每個大小400h。標注“這里”的這四句是四次查表運算,結果放在EAX里返回。完全和Blowfish的輪函數F相同,所以看到這里,基本可以確定算法就是Blowfish了。多次觀察加密過程,可以發現這個表里的數據總是不變的,說明UC的運行沒有任何密鑰協商過程,用的是固定密鑰。
?
??? Bruce原來的代碼(http://www.schneier.com/code/bfsh-sch.zip)中用P,S來命名,我覺得不大好,所以我改寫的時候稍微把名字加長了些。
?
??? 由于固定密鑰,為了代碼的簡便,我選擇了直接從內存里(7B0034)把這段生成好的1048h字節數據扒下來,寫在了我的解密代碼中,這也就是我的代碼中P_BOX和S_BOX的來歷。這樣做一個好處是省去了調用InitializeBlowfish函數的時間,另外也真正做到專碼專用了。只要UC一天不改,這代碼就一天有效,決不含糊。
?
??? 現在的UC還是一直就使用這樣的算法,至少兩年都沒改過了,而且還把新浪Web聊天室也如此包裝了一下。解密既然不難,接下來的事情其實就都沒有難度了,我隨便分析了一下,寫了個ucsniffer。
?
??? 關于UC的語音聊天沒有仔細研究,如果沒改動過的話,應該還是明碼,直接在線收聽或者錄下來慢慢聽都是可以實現的。
.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個單字節
.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元的整數表,其實也就是Blowfish代碼中維護的P盒,18*4=72=48h,那么EDX+48h,EDX+448h,EDX+848h和EDX+C48h就是S盒了,每個大小400h。標注“這里”的這四句是四次查表運算,結果放在EAX里返回。完全和Blowfish的輪函數F相同,所以看到這里,基本可以確定算法就是Blowfish了。多次觀察加密過程,可以發現這個表里的數據總是不變的,說明UC的運行沒有任何密鑰協商過程,用的是固定密鑰。
?
??? Bruce原來的代碼(http://www.schneier.com/code/bfsh-sch.zip)中用P,S來命名,我覺得不大好,所以我改寫的時候稍微把名字加長了些。
?
??? 由于固定密鑰,為了代碼的簡便,我選擇了直接從內存里(7B0034)把這段生成好的1048h字節數據扒下來,寫在了我的解密代碼中,這也就是我的代碼中P_BOX和S_BOX的來歷。這樣做一個好處是省去了調用InitializeBlowfish函數的時間,另外也真正做到專碼專用了。只要UC一天不改,這代碼就一天有效,決不含糊。
?
??? 現在的UC還是一直就使用這樣的算法,至少兩年都沒改過了,而且還把新浪Web聊天室也如此包裝了一下。解密既然不難,接下來的事情其實就都沒有難度了,我隨便分析了一下,寫了個ucsniffer。
?
??? 關于UC的語音聊天沒有仔細研究,如果沒改動過的話,應該還是明碼,直接在線收聽或者錄下來慢慢聽都是可以實現的。
結論:
??? 總地來說我覺得Blowfish算法本身應該還是不錯地,知道使用Blowfish也說明作者應該懂一些密碼安全知識,可惜最糟糕的事情莫過于此,固定的密鑰把所有本來應該有的安全性全部破壞掉了。