NET軟件加殼技術(shù)設(shè)計(jì)論文
時(shí)間:2022-09-17 05:55:00
導(dǎo)語:NET軟件加殼技術(shù)設(shè)計(jì)論文一文來源于網(wǎng)友上傳,不代表本站觀點(diǎn),若需要原創(chuàng)文章可咨詢客服老師,歡迎參考。
摘要介紹了軟件加殼技術(shù)的基本知識(shí),給出了.net環(huán)境下桌面軟件的一種新的加殼技術(shù),闡述了在這種技術(shù)下,軟件與用戶注冊(cè)流程與實(shí)現(xiàn)的有關(guān)技術(shù),最后,給出了加殼了的.NET軟件運(yùn)行時(shí),脫殼的關(guān)鍵技術(shù)與實(shí)現(xiàn)的部分代碼。
關(guān)鍵詞加殼;脫殼;DLL;DES;NET;MSIL
1引言
為了保護(hù)自己的軟件的技術(shù)內(nèi)核不被他人輕易盜用,軟件開發(fā)人員使用了各種加密技術(shù)來保障軟件的版權(quán)不被侵犯,殼便是我們常用的一種軟件保護(hù)手段。對(duì)于Win32中軟件加殼技術(shù)已經(jīng)有非常成熟的商業(yè)產(chǎn)品,然而,對(duì)于.NET環(huán)境下軟件,由于.NET程序的編譯結(jié)果不是機(jī)器語言代碼,而是一種MSIL中間代碼,因此不能使用傳統(tǒng)的加殼技術(shù)。目前,專門對(duì).NET軟件實(shí)施加殼的商業(yè)軟件主要有MaxtoCode,另外,SafeNet公司也推出了其軟件保護(hù)產(chǎn)品圣天狗最新的外殼工具,滿足了軟件開發(fā)商的一大愿望。圣天狗外殼加密工具可以自動(dòng)完成對(duì)可執(zhí)行文件的加密過程,從而讓開發(fā)商快速方便地完成軟件加密和授權(quán)管理的工作。
本文介紹了.NET環(huán)境下一種簡(jiǎn)單的軟件加殼技術(shù),該技術(shù)使用了數(shù)字簽名、MSIL代碼混淆、加密等技術(shù),可達(dá)到高強(qiáng)度的軟件保護(hù)。與MaxtoCode相比,這種技術(shù)的優(yōu)點(diǎn)是:可以防止軟件非法拷貝,針對(duì)計(jì)算機(jī)硬件“指紋”授權(quán)(指紋:即硬件信息中終身不變的識(shí)別號(hào),如CPU和硬盤的序列號(hào)等,下同),對(duì)于網(wǎng)絡(luò)版,可以防止非本服務(wù)器的客戶端訪問服務(wù)。
2認(rèn)識(shí)“殼”
殼是對(duì)加密軟件的一個(gè)形象的比喻,顧名思義,殼是軟件外部的一件“外衣”,是軟件的保護(hù)屏障。有了它,惡意攻擊者就無法在對(duì)軟件反匯編后,直接找到軟件的核心代碼。
殼是一段程序,它先于程序運(yùn)行,殼在運(yùn)行后就獲得了該軟件控制權(quán),利用其保護(hù)功能對(duì)軟件進(jìn)行安全保護(hù)。
殼的工作原理大致是:先運(yùn)行殼程序,殼將加密的主程序(主程序即原來的待加殼的程序,下同)代碼解密到內(nèi)存中,運(yùn)行其中相應(yīng)功能,并將程序的控制權(quán)交還給主程序。
本文中研究的加殼技術(shù)正是基于這種原理,只是殼也是用.NET編寫的,加密與解密密鑰與用戶的機(jī)器硬件指紋有關(guān),而不是固定的密鑰,所以可以防止軟件非法拷貝,達(dá)到更高的保護(hù)強(qiáng)度。
3本加殼技術(shù)的原理
先將原來的主程序編譯成DLL,再編寫一個(gè)殼程序,編譯成EXE,并將程序的運(yùn)行入口(即main函數(shù))移到殼中來,由殼開始執(zhí)行整個(gè)程序。首先,可以用自編的加密工具,在軟件前將所有DLL文件分別進(jìn)行加密(輸入特定的密鑰),在殼加載DLL時(shí)臨時(shí)將其解密到內(nèi)存中,并加載運(yùn)行。由于解密DLL的結(jié)果只存在于內(nèi)存,所以攻擊者無法獲得解密后的DLL,除非他能找到DLL的解密密鑰。同時(shí),為了避免攻擊者分析外殼程序的邏輯,從中尋找解密密鑰,還可以將殼編譯成EXE文件后,再用第三方軟件進(jìn)行混淆(如:XenoCode)或加密(如:MaxtoCode),這樣攻擊者將無法了解DLL加密的算法及處理邏輯。從而,更有效地保護(hù)主程序DLL。加殼與脫殼的原理如圖1所示。
圖1NET軟件加密型加殼的原理
4軟件與用戶注冊(cè)流程
為了推廣軟件,開發(fā)商一般會(huì)將軟件的試用版放在網(wǎng)上,讓用戶自由下載試用,用戶基本滿意后再注冊(cè)正式版。
軟件與用戶注冊(cè)的流程如圖2所示。
5軟件與用戶注冊(cè)的實(shí)現(xiàn)
5.1注冊(cè)申請(qǐng)
為了達(dá)到軟件防拷貝的功能,開發(fā)商必須為不同的用戶制作不同的安裝文件,一套程序只能在一臺(tái)機(jī)器上運(yùn)行。為此,開發(fā)商在制作安裝文件時(shí),必須取得軟件將要運(yùn)行的目標(biāo)機(jī)器的指紋和用戶的單位名稱,對(duì)于有應(yīng)用程序服務(wù)器的網(wǎng)絡(luò)版軟件,只需要取得應(yīng)用服務(wù)器的指紋。指紋數(shù)據(jù)可以由用戶使用特定的程序取得,并通過短信或郵件的方式告知開發(fā)商。
指紋的提取有兩種方法:其一,通過軟件的試用版。試用版中設(shè)計(jì)申請(qǐng)注冊(cè)的模塊,用戶通過此模塊提取本機(jī)的指紋數(shù)據(jù)。軟件的試用版文件的制作不是針對(duì)目標(biāo)機(jī)器的指紋制作的,可以在任何機(jī)器上運(yùn)行。為了防止Cracker找到DLL的解密密鑰后,將試用版破解。通??梢詫?duì)試用版軟件設(shè)置功能限制(如:去掉部分關(guān)鍵代碼),這樣即使試用版被破解,也無法投入正式的應(yīng)用。
方法二:使用專用于注冊(cè)申請(qǐng)的程序。對(duì)于網(wǎng)絡(luò)版的應(yīng)用服務(wù)程序,如果沒有用戶界面,或無須試用的用戶,只能使用由開發(fā)商提供的專用注冊(cè)程序來提取機(jī)器指紋。
5.2計(jì)算注冊(cè)碼
這種加殼技術(shù)本來可以省去輸入注冊(cè)碼手工注冊(cè)這個(gè)過程,因?yàn)槊恳粋€(gè)的版本只能在指定的機(jī)器上運(yùn)行,但為了定制用戶單位信息以及對(duì)用戶數(shù)進(jìn)行限制,還是要有注冊(cè)過程的。注冊(cè)碼是由用戶單位、機(jī)器指紋及用戶數(shù)限制等信息經(jīng)過加密處理后得到的,處理可以用自制的注冊(cè)碼計(jì)算工具來實(shí)現(xiàn)。
5.3加密DLL文件
本加殼技術(shù)的核心之一是加密DLL文件,加密過程可以用自制的加密工具完成。加密算法可以選擇.NET框架中提供任何加密算法或者自行設(shè)計(jì)加密算法。算法可以不用公開的算法,因?yàn)榧用芙饷芏际窃谧约旱某绦蛑羞M(jìn)行。因此,此方案的安全性完全可以由開發(fā)商自己保證,而不依賴于第三方。
5.4制作安裝盤
制作之前,只需用專為此用戶加密的DLL文件及授權(quán)文件等替換安裝工程中相應(yīng)的文件,再生成安裝盤。安裝盤中可以單獨(dú)存放一份加密DLL文件和授權(quán)文件,以備客戶升級(jí)正式版時(shí)用戶直接拷貝。
一般而言,安裝文件中不能直接包含注冊(cè)碼或授權(quán)文件的,但在這種技術(shù)下,可以將授權(quán)文件打包到安裝盤中,因?yàn)?,即使安裝文件被復(fù)制,也無法在非授權(quán)的機(jī)器上運(yùn)行。
5.5正式版安裝
對(duì)于沒有安裝過試用版的機(jī)器,可以直接使用安裝盤安裝正式版。對(duì)安裝過試用版的機(jī)器,可以用安裝盤中的正式版文件替換相應(yīng)文件即可變成正式版。
5.6用戶注冊(cè)
調(diào)用正式版中“幫助”à“關(guān)于”à“注冊(cè)”功能,輸入注冊(cè)碼或選擇授權(quán)文件進(jìn)行注冊(cè)。由于安裝文件中包含授權(quán)文件,也可以在正式版首次運(yùn)行時(shí),通過授權(quán)文件自動(dòng)注冊(cè),免去了手工注冊(cè)的過程。
6程序運(yùn)行時(shí)脫殼的實(shí)現(xiàn)
脫殼實(shí)際上是將加密的程序代碼解密并加載到內(nèi)存程序區(qū),脫殼需要特定的解密密鑰或特定的解密算法。對(duì)于較簡(jiǎn)單的程序,如果只有一兩個(gè)DLL,可以由殼程序進(jìn)行一次性脫殼,全部放在內(nèi)存中,這沒有什么技術(shù)上的難度,只是內(nèi)存消耗較多。對(duì)于有多個(gè)DLL的程序,DLL不一定都要使用,有時(shí)可能只用其中部分,所以沒有必要一次脫殼,全部占據(jù)在內(nèi)存中,可以根據(jù)需要來脫殼。脫殼涉及到DLL解密、DLL調(diào)用請(qǐng)求的捕獲等技術(shù)。
6.1DLL的解密
一般的加殼技術(shù)使用與用戶無關(guān)的密鑰,密鑰是固定中殼代碼中的,所以脫殼可以在任何一臺(tái)機(jī)器上實(shí)現(xiàn),無法實(shí)現(xiàn)軟件防拷貝。而在本方案中,DLL加密密鑰與用戶計(jì)算機(jī)硬件指紋相關(guān),當(dāng)然解密密鑰也不是殼代碼中固定的,而需要臨時(shí)從目標(biāo)計(jì)算機(jī)上提取指紋生成密鑰,才能解密,所以脫殼只能在授權(quán)的計(jì)算機(jī)上進(jìn)行,從而可以很好地防止軟件的非法拷貝。
解密密鑰的是由硬件指紋生成的,指紋的提取與申請(qǐng)注冊(cè)時(shí)提取指紋的算法相同,并且,指紋通過相同的保密算法轉(zhuǎn)換后生成加密解密密鑰。因此,指紋的提取算法存在于殼和專用的注冊(cè)申請(qǐng)程序以軟件的試用版中,為了防止這些算法的破解,需要使用第三方工具(如:XenoCode,MaxtoCode)對(duì)這些程序的MSIL代碼進(jìn)行混淆或加密。對(duì)于網(wǎng)絡(luò)版軟件,解密密鑰最好是由殼臨時(shí)從應(yīng)用程序服務(wù)器獲取;但為了簡(jiǎn)單起見,也可以將解密密鑰存入授權(quán)文件中,授權(quán)文件經(jīng)加密后隨客戶端軟件一起安裝,脫殼時(shí)從授權(quán)文件中提取解密密鑰。
DLL的解密只能在內(nèi)存中進(jìn)行,不能生成臨時(shí)文件,避免Cracker截獲解密后的DLL。這就要用到文件流與加密流的技術(shù),脫殼的部分代碼如下:
publicstaticAssemblyasmload(stringasmName)
{Assemblyasmsvr=null;
FileStreamfsr=null;
byte[]byVec=newbyte[16],byKey=newbyte[32];
//asmName待加載的程序集名,由參數(shù)帶入
stringtoLoad=AppDomain.CurrentDomain.BaseDirectory+asmName+"e.dll";
if(!File.Exists(toLoad))returnnull;
fsr=newFileStream(toLoad,F(xiàn)ileMode.Open,F(xiàn)ileAccess.Read);
byte[]rawAssembly=newbyte[fsr.Length];
//提取機(jī)器指紋并生成DES加密密鑰與初向量
createDesKeyVec(refbyVec,refbyKey);
SymmetricAlgorithmdes=SymmetricAlgorithm.Create();
CryptoStreamencStream=newCryptoStream(fsr,des.CreateDecryptor(byKey,byVec),CryptoStreamMode.Read);
//讀取并解密到到緩沖區(qū)
encStream.Read(rawAssembly,0,(int)fsr.Length);
encStream.Close();
fsr.Close();
asmsvr=AppDomain.CurrentDomain.Load(rawAssembly);
}
6.2DLL調(diào)用請(qǐng)求的捕獲
根據(jù)需要來脫殼也就是當(dāng)程序集被調(diào)用時(shí),臨時(shí)脫殼并加載,程序集一旦加載,以后需要調(diào)用其中的功能時(shí)就可以直接從內(nèi)存中運(yùn)行,這就既避免了內(nèi)存的浪費(fèi)又不會(huì)影響程序運(yùn)行速度。關(guān)鍵是程序集的調(diào)用不一定從殼中調(diào)用,可以從任何一個(gè)已經(jīng)運(yùn)行的程序集中調(diào)用,怎么才能截獲程序集的調(diào)用請(qǐng)求呢?
首先要了解應(yīng)用程序域,它由AppDomain對(duì)象來表示,為執(zhí)行托管代碼提供隔離、卸載和安全邊界。多個(gè)應(yīng)用程序域可以在一個(gè)進(jìn)程中運(yùn)行;但是,在應(yīng)用程序域和線程之間沒有一對(duì)一的關(guān)聯(lián)。多個(gè)線程可以屬于一個(gè)應(yīng)用程序域,盡管給定的線程并不局限于一個(gè)應(yīng)用程序域,但在任何給定時(shí)間,線程都在一個(gè)應(yīng)用程序域中執(zhí)行。每當(dāng)程序運(yùn)行時(shí),便會(huì)自動(dòng)創(chuàng)建應(yīng)用程序域。AppDomain實(shí)例用于加載和執(zhí)行程序集(Assembly),AppDomain類實(shí)現(xiàn)一組事件,這些事件使應(yīng)用程序可以在加載程序集、卸載應(yīng)用程序域或引發(fā)未處理的異常時(shí)進(jìn)行響應(yīng)。本方案中就是通過事件AssemblyResolve來捕獲程序集調(diào)用請(qǐng)求的。
實(shí)現(xiàn)方法是:首先,在殼的main()函數(shù)中注冊(cè)事件AssemblyResolve的響應(yīng)代碼,形如:
AppDomain.CurrentDomain.AssemblyResolve+=new
ResolveEventHandler(CurrentDomain_AssemblyResolve);
然后,再編寫一段事件響應(yīng)代碼,來實(shí)現(xiàn)程序集脫殼與加載。這樣,在調(diào)用任何程序集時(shí),就可以直接調(diào)用了,因?yàn)槌绦蚣拿摎?huì)自動(dòng)進(jìn)行。下面是事件響應(yīng)的部分代碼:
///<returns>返回找到的或臨時(shí)加載的程序集</returns>
privatestaticAssemblyCurrentDomain_AssemblyResolve(objectsender,ResolveEventArgsargs)
{
Assemblyret=null;
try{
AppDomaindm=(AppDomain)sender;
stringdllName=args.Name.Split('''','''')[0];
//用xx開頭的文件表示加密過和DLL,區(qū)別于其它的DLL
if(dllName.StartsWith("xx")&&!dllName.EndsWith("resources"))
ret=asmload(dllName);
}
catch(Exceptionae)
{MessageBox.Show("加載數(shù)據(jù)集"+args.Name+"時(shí)出錯(cuò)");}
returnret;
}
7總結(jié)
以上軟件保護(hù)方案的安全性能由DES算法(若采用)和機(jī)器指紋的安全性決定。DES算法的安全主要決定于對(duì)密鑰保護(hù)。另外,由于密鑰來自于機(jī)器指紋,而指紋數(shù)據(jù)來自于機(jī)器硬件信息,雖然,取指紋的算法要隨軟件外殼程序一起,但從指紋到密鑰要經(jīng)過自己設(shè)計(jì)的保密算法來轉(zhuǎn)換,且保密算法不公開,所以算法本身是安全的。因此,密鑰的安全還取決于指紋提取算法的安全性和指紋轉(zhuǎn)密鑰的算法安全性,而它們的安全性又取決于第三方加密或混淆的強(qiáng)度了,這是本方案所無法控制的,這也許就是此方案安全性最薄弱的環(huán)節(jié)。
對(duì)于用商業(yè)加殼軟件的攻擊較多,所以一旦商業(yè)加殼技術(shù)被破解,用它加密過的軟件便沒有安全了。但對(duì)于自編的加殼技術(shù),加密技術(shù)可以自行設(shè)計(jì)(保密),并且可以隨時(shí)調(diào)整,而且,用戶數(shù)不多,因此,攻擊者比較少,用這種技術(shù)加密的軟件安全性也就相對(duì)更好。使用本文中的加殼技術(shù),可以更有效地抵抗拷貝、反編譯、分發(fā)序列號(hào)、注冊(cè)機(jī)各種常用的軟件破解方法。然而,這種自編加殼技術(shù)雖然安全,但軟件分發(fā)起來卻十分復(fù)雜,這也是此方案的美中不足之處。
參考文獻(xiàn)
[1]&WindowsApplicationDebug[M].Beijing:TsinghuaUniversityPress,2004.6:50
[2]彭明柳.徹底研究[M].北京:中國鐵道出版社,2003.2:13
[3]EthanMilleretal.StrongSecurityforDisbributedFileSystems[C].InProcof2001IEEEinternationalConferenceonPerformace,Computingandcommunications,2001:34~40
[4]劉曉華.精通.NET核心技術(shù)——原理與構(gòu)架[M].北京:電子工業(yè)出版社,2002.8:183~231
[5]RichterJ.ProgrammingApplicationsForMicrosoftWindows[M].MicrosoftPress,2000