摘 要:軟件安全是信息安全領域的重要內容,其中軟件保護是關乎知識產權的一項重要工作,市場上雖然有大量現成的方案可選用,如基于軟件的加密殼保護和基于硬件的加密鎖保護,但這些優秀的保護方案由于太流行,造成大家對其研究太透徹,反而容易被破解。所以有必要實現相關的保護方法。
關鍵詞:軟件保護;注冊碼生成器;破解;算法
軟件保護的目的是向正式注冊用戶提供完整的功能,所以軟件保護必然要包括驗證用戶合法性的環節,而這一環節通常采用注冊碼驗證的方式實現。
(1)使用者向軟件開發方發送用戶碼U,要求注冊。
(2)由軟件開發方發出經過運算得到注冊碼R=f(U)。
(3)用戶在軟件注冊界面輸入U和R。
(4)軟件通過檢驗函數F(U,R)來檢測用戶的合法性。
其中一些常用術語說明如下:
用戶碼U:用戶身份ID。
注冊碼R:用于驗證用戶是否合法。
注冊碼生成器:把R=f(u)中的f稱為注冊碼生成器算法,注冊生成器算法可以針對任何用戶碼計算出一一對應的注冊碼。
檢驗函數:把F(U,R)稱為檢驗函數,軟件使用檢驗函數檢驗注冊碼是否合法,也就是只有R=f(u)成立時,F(U,R)才是合法的。
算法求逆:把破解者通過檢驗函數F推導注冊碼生成器算法的過程稱為算法求逆。
1 堡壘戰術
人們早就在各個領域開始研究身份檢驗的問題了,并研究開發出了散列加密和非對稱加密等早已被人們認可的密碼學算法,但真正適用于軟件注冊這一場合的算法恐怕只有MD5和RSA算法了。
MD5算法通常不能直接用來對消息進行加密,因為這種算法沒有逆向算法,所以加密之后不能解密,這種加密是沒有實用意義的,MD5算法的用途在于數字簽名。例如張和李進行通信,張只將明文A加密為B傳送給李是不夠安全的,因為即使密文B的加密強度再高也只能防止在傳輸過程中被解密而泄露內容,卻不能防止破壞者直接篡改密文B。李收到B后解密得到A,也無法判斷A中內容的可靠性與安全性。所以張在發送B的同時通常會在A之后簽名,然后計算一個校驗碼C=MD5(A),將B、C一起發送給李,李收到B、C后,首先解密B得到A,然后同樣計算校驗碼C=MD5(A),若計算出的校驗碼與收到的校驗碼相同,則可判定A真實可靠。
同樣的原因導致不能把MD5算法直接用做注冊碼生成器,假如使用R=MD5(U)做注冊碼生成器,因為MD5本身沒有反函數,檢驗函數就必須包含注冊碼生成器。但是用以下辦法間接使用MD5算法就可以:
(1)設注冊碼生成器為R=f(U)。
(2)設MD5(a)=b。
(3)令檢驗函數F為:F(U,R)=MD5[f-1(R)-U+a]
顯然F的合法值應為b,只要U,R滿足R=f(U),F一定等于b。因為MD5沒有逆操作,破解者不能經由b知道f-1(R)-U+a應該等于a,也就不可能得到f-1的明確定義,更不會得到注冊碼生成器f。至于f-1(R)-U+a表達式中雖然含有a,但解密者無法判斷a和f-1的關系。
實際上利用MD5算法構造F可以有很多方法,讓企圖破解者根本看不出F和f、f-1的關系,就更不用說去找逆運算了。但MD5算法的弱點是,由于MD5沒有逆操作,所以a必須為常數,一旦破解者知道了一對可用的U、R,它們就可能追蹤到可用的a、b值,從而知道f-1,并由此推測出注冊碼生成器f。
相比于MD5,RSA算法在軟件保護中應用就要簡單的多了:
(1)軟件作者使用:R=Ud mod n作為注冊碼生成器。
(2)軟件使用:U=Re mod n作為檢驗函數。
由于算法的復雜性,破解者是不可能知道d,也就無法破解注冊碼生成器??梢哉f利用RSA算法保護軟件就是建造了一座堅固的堡壘,但是由于RSA算法是一種公開算法,所以利用RSA算法來進行軟件保護也存在著一些問題。
(1)大多數的使用者對RSA算法的細節并不了解,這就為因為錯誤使用RSA埋下了隱患。例如,在不同的軟件作品中,使用同樣的參數導致莫名的異常攻擊。
(2)有些函數本身的不完善性也會導致防線的崩潰,例如,在產生隨機數時,會有當初始條件相同時,產生完全相同的隨機數結果。破解者如果了解到這一點,就可以依據n值推斷原始數據產生過程,RSA的防線也就岌岌可危了。
(3)函數庫在產生隨機素數時,應當淘汰那些容易被猜到的素數,否則會導致RSA算法中存在若干由各種特殊素數構造成的“弱密鑰”,這樣帶來的后果就是當破解者稍有數論基礎,就很容易攻破RSA。
2 游擊戰術
軟件保護中的游擊戰術就是將檢驗函數F拆分成多個相異的Fi,然后將這些Fi的不規則的隨機分布到程序的各個位置上。
經過這樣的處理之后,通過任何一個Fi的驗證都只是合法注冊的必要非充分條件,而只有真正合法的注冊碼才能夠通過所有的Fi的驗證。解密者如果知道只找到Fi其中的一個部分,只要有任何一個Fi沒找到,它就不能了解F的全體細節,也就不能算法求逆。
可能你會有疑問,如何將F分解成相異的并且是必要非充分的的Fi?這就需要比較扎實的數學功底了。
(1)將R切分成多段Ri。
(2)構造不同的f算法,使得:Ri=fi(U)。
(3)令Fi=fi-1。
這種看似繁瑣的操作,是很有實際意義的。例如可以讓F1使用X算法,F2使用Y算法,F3使用Z算法,這里的X、Y、Z可以MD5、RSA等成熟算法,也可以是用戶自定義的算法。用戶注冊時程序只選擇其中一個Fi進行驗證,這里還要注意,注冊碼在傳輸過程中一定要使用自定義的文件格式進行封裝,通過F1的驗證即給用戶注冊成功的提示。但這時其實并沒有給用戶完整的軟件使用權限,因為程序中的F2和F3只有使用者執行特定的操作時才被調用,例如,在用戶使用某些高級功能的時候將封裝的注冊碼再次使用F2和F3驗證。如果發現任何一個Fi結果非法,就把軟件恢復為非法使用狀態。
對于軟件保護這種新興技術,其實應該多站在破解者的角度考慮,這樣才能合理利用已有的知識庫來解決不斷出現的新問題,沒有哪種解決方案是可以一成不變的解決過去與未來的所有問題。
參考文獻
[1]Eldad Eliam. Secret of Reverse Engineering[M].Wiley,2005.
[2]看雪學院.軟件加密技術內幕[M].北京:電子工業出版社,2004.
[3]段鋼.加密與解密[M].北京:電子工業出版社,2013.
[4]譚明金.黑客反匯編揭秘[M].北京:電子工業出版社,2010.
作者簡介:郁諾(1977-),男,上海崇明人,西安財經學院高職學院,工程師。