NET軟件加殼技術設計論文

時間:2022-09-17 05:55:00

導語:NET軟件加殼技術設計論文一文來源于網友上傳,不代表本站觀點,若需要原創文章可咨詢客服老師,歡迎參考。

NET軟件加殼技術設計論文

摘要介紹了軟件加殼技術的基本知識,給出了.net環境下桌面軟件的一種新的加殼技術,闡述了在這種技術下,軟件與用戶注冊流程與實現的有關技術,最后,給出了加殼了的.NET軟件運行時,脫殼的關鍵技術與實現的部分代碼。

關鍵詞加殼;脫殼;DLL;DES;NET;MSIL

1引言

為了保護自己的軟件的技術內核不被他人輕易盜用,軟件開發人員使用了各種加密技術來保障軟件的版權不被侵犯,殼便是我們常用的一種軟件保護手段。對于Win32中軟件加殼技術已經有非常成熟的商業產品,然而,對于.NET環境下軟件,由于.NET程序的編譯結果不是機器語言代碼,而是一種MSIL中間代碼,因此不能使用傳統的加殼技術。目前,專門對.NET軟件實施加殼的商業軟件主要有MaxtoCode,另外,SafeNet公司也推出了其軟件保護產品圣天狗最新的外殼工具,滿足了軟件開發商的一大愿望。圣天狗外殼加密工具可以自動完成對可執行文件的加密過程,從而讓開發商快速方便地完成軟件加密和授權管理的工作。

本文介紹了.NET環境下一種簡單的軟件加殼技術,該技術使用了數字簽名、MSIL代碼混淆、加密等技術,可達到高強度的軟件保護。與MaxtoCode相比,這種技術的優點是:可以防止軟件非法拷貝,針對計算機硬件“指紋”授權(指紋:即硬件信息中終身不變的識別號,如CPU和硬盤的序列號等,下同),對于網絡版,可以防止非本服務器的客戶端訪問服務。

2認識“殼”

殼是對加密軟件的一個形象的比喻,顧名思義,殼是軟件外部的一件“外衣”,是軟件的保護屏障。有了它,惡意攻擊者就無法在對軟件反匯編后,直接找到軟件的核心代碼。

殼是一段程序,它先于程序運行,殼在運行后就獲得了該軟件控制權,利用其保護功能對軟件進行安全保護。

殼的工作原理大致是:先運行殼程序,殼將加密的主程序(主程序即原來的待加殼的程序,下同)代碼解密到內存中,運行其中相應功能,并將程序的控制權交還給主程序。

本文中研究的加殼技術正是基于這種原理,只是殼也是用.NET編寫的,加密與解密密鑰與用戶的機器硬件指紋有關,而不是固定的密鑰,所以可以防止軟件非法拷貝,達到更高的保護強度。

3本加殼技術的原理

先將原來的主程序編譯成DLL,再編寫一個殼程序,編譯成EXE,并將程序的運行入口(即main函數)移到殼中來,由殼開始執行整個程序。首先,可以用自編的加密工具,在軟件前將所有DLL文件分別進行加密(輸入特定的密鑰),在殼加載DLL時臨時將其解密到內存中,并加載運行。由于解密DLL的結果只存在于內存,所以攻擊者無法獲得解密后的DLL,除非他能找到DLL的解密密鑰。同時,為了避免攻擊者分析外殼程序的邏輯,從中尋找解密密鑰,還可以將殼編譯成EXE文件后,再用第三方軟件進行混淆(如:XenoCode)或加密(如:MaxtoCode),這樣攻擊者將無法了解DLL加密的算法及處理邏輯。從而,更有效地保護主程序DLL。加殼與脫殼的原理如圖1所示。

圖1NET軟件加密型加殼的原理

4軟件與用戶注冊流程

為了推廣軟件,開發商一般會將軟件的試用版放在網上,讓用戶自由下載試用,用戶基本滿意后再注冊正式版。

軟件與用戶注冊的流程如圖2所示。

5軟件與用戶注冊的實現

5.1注冊申請

為了達到軟件防拷貝的功能,開發商必須為不同的用戶制作不同的安裝文件,一套程序只能在一臺機器上運行。為此,開發商在制作安裝文件時,必須取得軟件將要運行的目標機器的指紋和用戶的單位名稱,對于有應用程序服務器的網絡版軟件,只需要取得應用服務器的指紋。指紋數據可以由用戶使用特定的程序取得,并通過短信或郵件的方式告知開發商。

指紋的提取有兩種方法:其一,通過軟件的試用版。試用版中設計申請注冊的模塊,用戶通過此模塊提取本機的指紋數據。軟件的試用版文件的制作不是針對目標機器的指紋制作的,可以在任何機器上運行。為了防止Cracker找到DLL的解密密鑰后,將試用版破解。通??梢詫υ囉冒孳浖O置功能限制(如:去掉部分關鍵代碼),這樣即使試用版被破解,也無法投入正式的應用。

方法二:使用專用于注冊申請的程序。對于網絡版的應用服務程序,如果沒有用戶界面,或無須試用的用戶,只能使用由開發商提供的專用注冊程序來提取機器指紋。

5.2計算注冊碼

這種加殼技術本來可以省去輸入注冊碼手工注冊這個過程,因為每一個的版本只能在指定的機器上運行,但為了定制用戶單位信息以及對用戶數進行限制,還是要有注冊過程的。注冊碼是由用戶單位、機器指紋及用戶數限制等信息經過加密處理后得到的,處理可以用自制的注冊碼計算工具來實現。

5.3加密DLL文件

本加殼技術的核心之一是加密DLL文件,加密過程可以用自制的加密工具完成。加密算法可以選擇.NET框架中提供任何加密算法或者自行設計加密算法。算法可以不用公開的算法,因為加密解密都是在自己的程序中進行。因此,此方案的安全性完全可以由開發商自己保證,而不依賴于第三方。

5.4制作安裝盤

制作之前,只需用專為此用戶加密的DLL文件及授權文件等替換安裝工程中相應的文件,再生成安裝盤。安裝盤中可以單獨存放一份加密DLL文件和授權文件,以備客戶升級正式版時用戶直接拷貝。

一般而言,安裝文件中不能直接包含注冊碼或授權文件的,但在這種技術下,可以將授權文件打包到安裝盤中,因為,即使安裝文件被復制,也無法在非授權的機器上運行。

5.5正式版安裝

對于沒有安裝過試用版的機器,可以直接使用安裝盤安裝正式版。對安裝過試用版的機器,可以用安裝盤中的正式版文件替換相應文件即可變成正式版。

5.6用戶注冊

調用正式版中“幫助”à“關于”à“注冊”功能,輸入注冊碼或選擇授權文件進行注冊。由于安裝文件中包含授權文件,也可以在正式版首次運行時,通過授權文件自動注冊,免去了手工注冊的過程。

6程序運行時脫殼的實現

脫殼實際上是將加密的程序代碼解密并加載到內存程序區,脫殼需要特定的解密密鑰或特定的解密算法。對于較簡單的程序,如果只有一兩個DLL,可以由殼程序進行一次性脫殼,全部放在內存中,這沒有什么技術上的難度,只是內存消耗較多。對于有多個DLL的程序,DLL不一定都要使用,有時可能只用其中部分,所以沒有必要一次脫殼,全部占據在內存中,可以根據需要來脫殼。脫殼涉及到DLL解密、DLL調用請求的捕獲等技術。

6.1DLL的解密

一般的加殼技術使用與用戶無關的密鑰,密鑰是固定中殼代碼中的,所以脫殼可以在任何一臺機器上實現,無法實現軟件防拷貝。而在本方案中,DLL加密密鑰與用戶計算機硬件指紋相關,當然解密密鑰也不是殼代碼中固定的,而需要臨時從目標計算機上提取指紋生成密鑰,才能解密,所以脫殼只能在授權的計算機上進行,從而可以很好地防止軟件的非法拷貝。

解密密鑰的是由硬件指紋生成的,指紋的提取與申請注冊時提取指紋的算法相同,并且,指紋通過相同的保密算法轉換后生成加密解密密鑰。因此,指紋的提取算法存在于殼和專用的注冊申請程序以軟件的試用版中,為了防止這些算法的破解,需要使用第三方工具(如:XenoCode,MaxtoCode)對這些程序的MSIL代碼進行混淆或加密。對于網絡版軟件,解密密鑰最好是由殼臨時從應用程序服務器獲??;但為了簡單起見,也可以將解密密鑰存入授權文件中,授權文件經加密后隨客戶端軟件一起安裝,脫殼時從授權文件中提取解密密鑰。

DLL的解密只能在內存中進行,不能生成臨時文件,避免Cracker截獲解密后的DLL。這就要用到文件流與加密流的技術,脫殼的部分代碼如下:

publicstaticAssemblyasmload(stringasmName)

{Assemblyasmsvr=null;

FileStreamfsr=null;

byte[]byVec=newbyte[16],byKey=newbyte[32];

//asmName待加載的程序集名,由參數帶入

stringtoLoad=AppDomain.CurrentDomain.BaseDirectory+asmName+"e.dll";

if(!File.Exists(toLoad))returnnull;

fsr=newFileStream(toLoad,FileMode.Open,FileAccess.Read);

byte[]rawAssembly=newbyte[fsr.Length];

//提取機器指紋并生成DES加密密鑰與初向量

createDesKeyVec(refbyVec,refbyKey);

SymmetricAlgorithmdes=SymmetricAlgorithm.Create();

CryptoStreamencStream=newCryptoStream(fsr,des.CreateDecryptor(byKey,byVec),CryptoStreamMode.Read);

//讀取并解密到到緩沖區

encStream.Read(rawAssembly,0,(int)fsr.Length);

encStream.Close();

fsr.Close();

asmsvr=AppDomain.CurrentDomain.Load(rawAssembly);

}

6.2DLL調用請求的捕獲

根據需要來脫殼也就是當程序集被調用時,臨時脫殼并加載,程序集一旦加載,以后需要調用其中的功能時就可以直接從內存中運行,這就既避免了內存的浪費又不會影響程序運行速度。關鍵是程序集的調用不一定從殼中調用,可以從任何一個已經運行的程序集中調用,怎么才能截獲程序集的調用請求呢?

首先要了解應用程序域,它由AppDomain對象來表示,為執行托管代碼提供隔離、卸載和安全邊界。多個應用程序域可以在一個進程中運行;但是,在應用程序域和線程之間沒有一對一的關聯。多個線程可以屬于一個應用程序域,盡管給定的線程并不局限于一個應用程序域,但在任何給定時間,線程都在一個應用程序域中執行。每當程序運行時,便會自動創建應用程序域。AppDomain實例用于加載和執行程序集(Assembly),AppDomain類實現一組事件,這些事件使應用程序可以在加載程序集、卸載應用程序域或引發未處理的異常時進行響應。本方案中就是通過事件AssemblyResolve來捕獲程序集調用請求的。

實現方法是:首先,在殼的main()函數中注冊事件AssemblyResolve的響應代碼,形如:

AppDomain.CurrentDomain.AssemblyResolve+=new

ResolveEventHandler(CurrentDomain_AssemblyResolve);

然后,再編寫一段事件響應代碼,來實現程序集脫殼與加載。這樣,在調用任何程序集時,就可以直接調用了,因為程序集的脫殼會自動進行。下面是事件響應的部分代碼:

///<returns>返回找到的或臨時加載的程序集</returns>

privatestaticAssemblyCurrentDomain_AssemblyResolve(objectsender,ResolveEventArgsargs)

{

Assemblyret=null;

try{

AppDomaindm=(AppDomain)sender;

stringdllName=args.Name.Split('''','''')[0];

//用xx開頭的文件表示加密過和DLL,區別于其它的DLL

if(dllName.StartsWith("xx")&&!dllName.EndsWith("resources"))

ret=asmload(dllName);

}

catch(Exceptionae)

{MessageBox.Show("加載數據集"+args.Name+"時出錯");}

returnret;

}

7總結

以上軟件保護方案的安全性能由DES算法(若采用)和機器指紋的安全性決定。DES算法的安全主要決定于對密鑰保護。另外,由于密鑰來自于機器指紋,而指紋數據來自于機器硬件信息,雖然,取指紋的算法要隨軟件外殼程序一起,但從指紋到密鑰要經過自己設計的保密算法來轉換,且保密算法不公開,所以算法本身是安全的。因此,密鑰的安全還取決于指紋提取算法的安全性和指紋轉密鑰的算法安全性,而它們的安全性又取決于第三方加密或混淆的強度了,這是本方案所無法控制的,這也許就是此方案安全性最薄弱的環節。

對于用商業加殼軟件的攻擊較多,所以一旦商業加殼技術被破解,用它加密過的軟件便沒有安全了。但對于自編的加殼技術,加密技術可以自行設計(保密),并且可以隨時調整,而且,用戶數不多,因此,攻擊者比較少,用這種技術加密的軟件安全性也就相對更好。使用本文中的加殼技術,可以更有效地抵抗拷貝、反編譯、分發序列號、注冊機各種常用的軟件破解方法。然而,這種自編加殼技術雖然安全,但軟件分發起來卻十分復雜,這也是此方案的美中不足之處。

參考文獻

[1]&WindowsApplicationDebug[M].Beijing:TsinghuaUniversityPress,2004.6:50

[2]彭明柳.徹底研究[M].北京:中國鐵道出版社,2003.2:13

[3]EthanMilleretal.StrongSecurityforDisbributedFileSystems[C].InProcof2001IEEEinternationalConferenceonPerformace,Computingandcommunications,2001:34~40

[4]劉曉華.精通.NET核心技術——原理與構架[M].北京:電子工業出版社,2002.8:183~231

[5]RichterJ.ProgrammingApplicationsForMicrosoftWindows[M].MicrosoftPress,2000