[转载].NET商业软件源码保护
[轉(zhuǎn)載].NET商業(yè)軟件源碼保護(hù)
列舉工作以來遇到的各種類型的軟件所采用的代碼保護(hù)技術(shù),只講原理不涉及技術(shù)細(xì)節(jié)實(shí)現(xiàn),以避免產(chǎn)生法律問題。有些朋友說直接把代碼放在Github開源下載,開源可以促進(jìn)技術(shù)交流與進(jìn)步,然而值錢的代碼都積壓在硬盤里面,即使很爛的代碼都賣了很多錢,贏得了許多客戶與市場。珍惜愛護(hù)公司的代碼,他們都是寶貴的財(cái)富。
以下保護(hù)技術(shù)主要測重于脫機(jī)驗(yàn)證與保護(hù),不涉及聯(lián)網(wǎng)(連接到許可證服務(wù)器)驗(yàn)證。?
1、程序集混淆 Asembly obfuscate
CLR代碼的運(yùn)行是即時(shí)編譯執(zhí)行的,.NET編譯器只是將源代碼文件編譯成中間語言,中間語言包含豐富的元數(shù)據(jù)。使用.NET Reflector/ILSpy/JustCode這類的反編譯器幾乎可以還原整個(gè)源代碼,所以用.NET開發(fā)軟件第一個(gè)要做的任務(wù)是混淆編譯后的中間語言代碼。這也是我見得最多的.NET代碼保護(hù)技術(shù)。
?
2、寫注冊表 Registry
雖然.NET時(shí)代強(qiáng)調(diào)XCOPY部屬,但很多很程序依然依賴于注冊表來做保護(hù)技術(shù)的基礎(chǔ)。可以把自己想要隱藏的信息放到很深的注冊表鍵中。
一些程序會(huì)將注冊表鍵做一個(gè)字符串處理,比如將字符串改成16進(jìn)制值,或是做一個(gè)DES混淆處理,在不知道解密鍵(KEY)的情況下很難看出它的意思。
?
3、RSA 簽名? RSA Signature
RSA簽名技術(shù)可以生成二個(gè)密匙,私匙用于生成許可文件,公匙用于驗(yàn)證許可。
string?publicKey = "<BitStrength>1024</BitStrength><RSAKeyValue><Modulus>wDSWDT4ujpa+B7VkwdXGDvIEDc18O6qSnGtL38prVR18B7sjqbhR2Uq1C7hksADnF
DH+PAHv9BAWiqa1cWeaVgCwC2LNMClaJu4jZg0aFDIzhZUNHV56KS5aaVD+MHH+iEGmPok9XRz7Jd8hyjD38jHl439Uaf6oltxMRdKS5KU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
string?privateKey = "<BitStrength>1024</BitStrength><RSAKeyValue><Modulus>wDSWDT4ujpa+B7VkwdXGDvIEDc18O6qSnGtL38prVR18B7sjqbhR2Uq1C7hksADnFDH+PAHv9B
AWiqa1cWeaVgCwC2LNMClaJu4jZg0aFDIzhZUNHV56KS5aaVD+MHH+iEGmPok9XRz7Jd8hyjD38jHl439Uaf6oltxMRdKS5KU=</Modulus><Exponent>AQAB</Exponent><P>82nuszkXKLx
+NDtQLiruBlDGozAUaJ50PqHKq7jglLV740jz521+v2O6EVA+59gpGSwFrX6E7HnUrkKBQGbY/w==</P><Q>yiTO+1+xaNvmEcAyKdFboNRbP1/toUnakkREKyYCg/KLnjgpkb22gMtu
u5ocbfY2vIdyDZbYYeXmLYSJ9Io+Ww==</Q><DP>ds7Zx3iyKRv3rZ7Vv/MMQuDiU3yAOaA9tORbe/29AFiko4dUJT14hAo1I4Y7bgY/6R1nmAsM7i9486VaWQjaGQ==</DP><DQ>sRU
1zbiy7i1Vi09XopKpNmdR2F7tCVJti50KKtKNeZHNBbolkGslqgaM5wPGy/3ZTadKHuV6gaio0E8/m15P6Q==</DQ><InverseQ>YsZNcptrcalrlR5TS+rJ+m9G8+xUIJGGLSB3Czjw
q28rFgXa//avpx05E3FIN0tfAOKJhy84VKElqPNyQyacNA==</InverseQ><D>jaNy3Clxl6QgP3/90xWc0ZCpSh6eKT4GsnwjOrRpKh0DNJNEsaJhtpXmGs/0avsPToOUzVXEJP/iDKTTWtG
1GdkqZp+gaqKbp73RP21Nmd+lZ/S1WvmUTe3Ge5I5FP/7zf9KnTXBm1yLel/9N5UL6o5EncPNjqUt2+oKQ+q7vJU=</D></RSAKeyValue>";
因?yàn)樗匠字淮嬖谟谧约旱碾娔X中,不會(huì)發(fā)布到程序中,只要私匙不泄露出去,這種加密方法是相當(dāng)安全的。破解RSA簽名的唯一方法是替換公匙,用自己生成的私匙生成許可文件。
?
4、參數(shù)保護(hù) Parameter Protection
基于第3條RSA簽名技術(shù),簽名之后產(chǎn)生的字符串是只讀的,在它的基礎(chǔ)上我們可以增加許多控制點(diǎn),比如可使用的用戶數(shù),過期時(shí)間,最大賬套數(shù)等。
在我的Enterprise Solution開發(fā)框架中,提供基于第3條和第4條為原理的許可保護(hù)技術(shù)的例子,在一定程度上保護(hù)產(chǎn)品不被未授權(quán)用戶使用。
?
5、機(jī)器硬件識(shí)別 Hardware Recognition
為了控制軟件不會(huì)被客戶隨意拷貝分發(fā),一方面通過法律合同條文明確禁止,但通常這沒有什么卵用,另一方面則必須做硬件識(shí)別。在生成許可文件之前,要依賴于客戶的機(jī)器配置,將客戶的機(jī)器硬件信息完整的保存到許可文件中,運(yùn)行時(shí)逐條檢測,發(fā)現(xiàn)有不一致的地方立刻退出應(yīng)用程序。
.NET 提供了WMI接口用于讀取機(jī)器相關(guān)的信息,參數(shù)如下的代碼例子:
private static string GetDiskDriveSize() { return WmiHelper.GetWmiPropertyValue("Win32_DiskDrive", "Size"); } private static string GetDiskDriveTotalSectors() { return WmiHelper.GetWmiPropertyValue("Win32_DiskDrive", "TotalSectors"); } private static string GetDiskDriveTotalTracks() { return WmiHelper.GetWmiPropertyValue("Win32_BaseBoard", "Manufacturer"); }三個(gè)方法分別讀取硬盤大小,硬盤分區(qū),主板制造商,將這些信息組合起來放到一個(gè)字符串文件中,即是電腦的硬件信息,再對這個(gè)字符串做一個(gè)DES對稱加密或是RSA簽名處理,處理之后,客戶的硬件信息看起來是這樣的字符串。
lxocnnn7ofk2+Nheb7Qo+cBRDlCbVWHCfVSFG/XnyT3F7q/avyRL3Lj7gotPMtuo41A33AjSryt5a1ydvu7tTOnsOsizy8HJIrP13T5jHbgyHZgZaQk54eGLN3eft5zijKT3hyirZ5w2Mf6mWmv/9F
68jFxsnNh//OUUAVI3lx0=KMw2gRnZ8BqL4lNw4A5j+tuDlvbsj5gp3CGZNbAXlFlGW188uliAZexb6GhcvB0VSwTV37R6NUstT/VT5MJ7wyf/zyyHpa1uHGx4/UziLCAwawnap90BkQWlH1aVz
2lTX3I93iKKYOdAJF0y5TM9njlVvqToj2cBBWLUG+sYXxo=DUjIpSbrp5cl8L//WbIs7ErSX8RBTeVMFO7OCIYoTh7yogVzJNH3D3QZHYKnNfGmJDMSleJSgdLb0GdiWdEgiLTf0uv7lQsoA076
WM5VrtG7O/h0E3DvmisP7OkkuJIMEIpExaM+3GDlIHGvHYRK0nDfzBQM8AXM2k0ue8wj0xY=k5CRv+IkEdB6yZEy65iLXsU0lQT1FbHwSH7LawWBoOZHJt1TwIAajHuqH0AHAWZgRHYDbHCxnlJFv9t
OepsJdNGL6CvjUEnyuNA3RlhKNB6K51rOjIQ1ROKRiy9z+YsbHbJxdbsj3km/kITzfHvoDqQIg4zrTR0XfSn49j0rMkI=C4oBw14/k1OWPzMC1SUe+YxrJtyUqzL2k/cKz/feAhZ0DELbUiCUcbjhHg
+ryg+E7P5Bfy53n3kH5SBud4rVBpRUZGx4xZFPB8eXQ40SUCMxs74cbQRUPh7+zQo6qF/AtrQkXKbzoiZKHCz50n6h/afaa+jwuOplYUx191269w4=RGDYBw6j5VXJO7phILX1zLRcbO3+6SrBuCLEFwk
sitOk/z+OGtFEoIfHD5DZRp9t6GVYtpdI7jPVz7lTV4DL5xfCQ8woJjpqUdB++pYaIw3gx9EL6PD+ucRfLKtiNng6ujKe0r6A51y9eGJRic9p8uAPGSEj8OtNLmO0mVWcwhE=GJg9mdr/YdDMZCVe0WPb3
S8YGKfzdPYj3xJTQtRYdFLV9E6GHzQj8FFgIrxjdoD3n9FGthhF82MTpjS3kOdIyQEc7moienSbzqevcUPs4ZmDwmveH/F4DSynS7JAiPqCcnAj7N4EI/PkXZWAtdHSra2yWBkEBw5PlVhLTLbcLGE=FL
+JSw0yGUIpIZUgq8VRt27e5J+D0vRoEw9t5NKPROysnGw=YN1yhy2reEhQPs30aCnOpNDz2
He2E9re26QBwipNgivHM8Z/FcLk0hjALeiC8zY4Dcn+0PKag6DH7tmIBwTpBus2+ZqjLlgIx7uKMPB49+yPC5qOV8vsJGV/s81xVEA+prgNbh9Sa3TSsBV3qMSyZDEyvkHc+1QbBoLd/1h2WUI=p0/G
lIKMQ7XoRom9njDq5XPn3sj4V8P137v6eDDq7uTpRcTXD/qOWi/IZMcNX56LqVb1PJko0BCUYXa8h0zzEvsmTJNXUzggZlpkzk4EOzq4GekTwM6hXcn0Es/6iZ2J5Et1h5kSOOk1MLZS3cmUHeSRn0js
Ed0O/+L8+qBNpYapf6GL2iYf5j/Qfi+2djOwqCspHawZcBZ/e/WtK0b/0F4=lmHD5BVilXA7KIQk8yma7d4dP5mawdNhMEuYG68sN15SJOUMZlGiFT17rh0Y7Z
54itnjVmhaRVXBsc/LDKYPIwsD+TZBTGDbSOebmxvDe+Jdh6ZLsmGUIdREH4/L19y1713PyJ2r6HYi9v/8GobkWWg4chIKggBhSYUJFP8jj4Q=JHNsEDYacXEIwWhR
nDfiQoWZbrZjmCgF7lo9g4BCTYD0KbLLRKdrDERNPTQs+e3kLf0/fhc0x0BsE/yCuYcnj8rh9/iA08ZUxO+TZkz/p5rseWklWboc45o90q/ZXfuu5f+TCVPnfTXCxMjwdH3
F4I7EotPzweUS/P++YDvHHWA=d8l5s9fNa0fUX4eo9LoHVT4Wb8YbHKDvDW7o1P+wTDykIrOCLoCKklrSGdHjOi8EWw=LDrOGw3pq7rv4L7YoGLaZAmXfRdcw1wp2Zi/Hn2
這樣既避免了客戶隱私信息泄露,也可以解決當(dāng)前軟件氛圍環(huán)境下軟件分發(fā)的困擾。
?
6、序列號(hào)/注冊碼 Serial Key
相當(dāng)多的軟件還是采取這一傳統(tǒng)的序列號(hào)保護(hù)方法,比如Windows Server 2012的注冊碼:
NB4WH-BBBYV-3MPPC-9RCMV-46XCB
一組看似無序的數(shù)字與字母的組合,對軟件保護(hù)起了很重要的作用。如果是在軟件安裝時(shí)驗(yàn)證序列號(hào),則破解難度會(huì)更大。
序列上面的字母數(shù)字組合,可以包含很多信息,比如客戶名稱,過期時(shí)間,最大用戶數(shù)。將這樣的序列號(hào)分享給同行的其它客戶,一旦軟件公司追查起來很容易就能識(shí)別這個(gè)序列號(hào)是否合法。
在我的博客下載工具中用到的一個(gè)組件aspNetMHT,它就是采用這個(gè)方法來分發(fā)序列號(hào)的,序列號(hào)中包含過期時(shí)間。aspNetMHT的序列號(hào)看起來是這樣的:
SM48Z-FMXGZ-25P67-4ZJKF-GS211-AQYA4-7VHUX-KCF1C-RD4RC-RU7XS-XK8JY-6JT54-M9CX
?
7、強(qiáng)名稱 Strong Name
強(qiáng)名稱不是一種代碼保護(hù)技術(shù),而是程序集標(biāo)識(shí)技術(shù)。每個(gè)經(jīng)過strong name簽名后的程序集都是唯一的,在運(yùn)行時(shí)可以驗(yàn)證這個(gè)文件的簽名是否被改動(dòng)過。
驗(yàn)證強(qiáng)名稱的關(guān)鍵地方在于調(diào)用CLR中的基礎(chǔ)方法:
[DllImport("mscoree.dll", CharSet = CharSet.Unicode)] public static extern bool StrongNameSignatureVerificationEx(string wszFilePath, bool fForceVerification, ref bool pfWasVerified);所以開發(fā).NET程序,不僅僅要給程序簽名,還需要在運(yùn)行時(shí)驗(yàn)證所給的簽名是否被改動(dòng)過。
.NET CLR支持對程序集跳過強(qiáng)名稱驗(yàn)證,不過這樣做的風(fēng)險(xiǎn)太大,直接修改了CLR的行為,未見有很多實(shí)例。
8、內(nèi)存保護(hù) Memory? Protection
Delphi XE采取了這種方法,運(yùn)行時(shí)會(huì)生成一段驗(yàn)證代碼,驗(yàn)證結(jié)束后代碼銷毀,因?yàn)轵?yàn)證在內(nèi)存中進(jìn)行,不會(huì)在硬盤上留下痕跡,破解的難度相對困難了很多。
Win32支持動(dòng)態(tài)加載和卸載程序集,所以Win32 API中有接口LoadLibrary和UnloadLibrary供調(diào)用,可實(shí)現(xiàn)內(nèi)存保護(hù)。
.NET也支持動(dòng)態(tài)加載程序集,但不支持卸載(unload)程序集,程序集的卸載由CLR控制,這一點(diǎn)給破解內(nèi)存保護(hù)技術(shù)提供了方便。
在我的Enterprise Solution開發(fā)框架中,將第7條和第8條組合一下,簡單的解釋如下:創(chuàng)建一個(gè)類型定義文件,然后將這個(gè)文件用強(qiáng)名稱簽名,之后將這個(gè)簽名的程序集經(jīng)過混淆,字符串加密等處理,附加到啟動(dòng)程序的資源文件中去,運(yùn)行時(shí),我從資源文件中將此程序集解析釋放出來,同時(shí)強(qiáng)制驗(yàn)證程序集的強(qiáng)名稱,運(yùn)行類型定義文件中指定的驗(yàn)證方法,實(shí)現(xiàn)簡單的內(nèi)存保護(hù)技術(shù)。
破解這種保護(hù)需要知道簽名程序集的強(qiáng)名稱,字符串加密處理的全流程和相應(yīng)的鍵,給破解增加了不少難度。要驗(yàn)證什么和怎么驗(yàn)證都是在我設(shè)計(jì)的類型定義文件中指定的,啟動(dòng)程序只是一個(gè)殼,運(yùn)用反射調(diào)用要驗(yàn)證方法。而且這個(gè)經(jīng)過簽名后的程序集是附加到主程序中去的,要替換這個(gè)資源文件,也需要一些方法和技巧。
9、源代碼混淆 Source code obfuscate
經(jīng)過編譯混淆后的.NET程序集,在運(yùn)行時(shí)依舊可以被調(diào)試器附加調(diào)試。如果我能將源代碼中的敏感字符串替換成亂七八糟的字符串,減少明文的出現(xiàn),雖然降低了性能,但這樣可以增加安全性。比如,我運(yùn)行時(shí)檢測找不到許可文件時(shí),拋出以下異常:
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"license.lic"); if (!File.Exists(path)) throw new LicenseException("License file not found");經(jīng)過源代碼敏感字符串替換后的程序如下:
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"license.lic"); if (!File.Exists(path)) throw new LicenseException(B("/jNloqd4U59LBT64eX1hb9eO8kYDD7tD")); 經(jīng)過一個(gè)B方法的調(diào)用,無法看到異常的明文,增加了破解難度。如果代碼中這樣的B方法有很多,而且B方法的字符串處理方式各不相同,無疑提高了系統(tǒng)的安全性。現(xiàn)在市場上有很多JavaScript源代碼混淆工具,就是把JavaScript代碼的格式打亂,讓它不容易讀取。
C#源代碼也可以采用此方法,不過,讀強(qiáng)大的Visual Studio有文檔格式化功能(Edit-Advanced- Format Document ,Ctrl + E,D) ,瞬間變?yōu)榭勺x的格式。
10、本機(jī)代碼 Native Code
即將發(fā)布的Visual Studio 2015提供.NET Native功能,可將.NET代碼編譯為本機(jī)代碼。然而經(jīng)過近一年的等待,.NET Native目前也是僅僅限定于Windows應(yīng)用程序商店項(xiàng)目,真正的Windows Forms/WPF/ASP.NET要實(shí)現(xiàn)編譯為本機(jī)代碼可能不現(xiàn)實(shí)。
這種保護(hù)方法的核心是許可驗(yàn)證邏輯放在本機(jī)代碼中,直接編譯成機(jī)器碼。一般采用Visual C++/Delphi/VB6之類的工具,將重要的算法與驗(yàn)證編譯成機(jī)器碼,這樣會(huì)增加破解難度。本機(jī)代碼難于處理的一個(gè)方面是.NET Any CPU的問題。當(dāng)我們設(shè)定.NET編譯為Any CPU時(shí),CLLRU會(huì)依據(jù)程序運(yùn)行的平臺(tái)(x86,x64)編譯為本機(jī)代碼。
在x64的系統(tǒng)中加載32位的本機(jī)代碼,常常會(huì)拋出無效的程序集異常。破解這種保護(hù)的方法可直接修改.NET程序中的調(diào)用方法,可以忽略本機(jī)代碼的邏輯。
相對于前面的幾種技術(shù),這種保護(hù)技術(shù)破解難度更大,要懂的知識(shí)點(diǎn)也非常多。
博客轉(zhuǎn)自:JamesLi的《大型.NET商業(yè)軟件代碼保護(hù)技術(shù) 技術(shù)與實(shí)踐相結(jié)合保護(hù)辛苦創(chuàng)造的勞動(dòng)成果》 本文轉(zhuǎn)自SanMaoSpace博客園博客,原文鏈接:http://www.cnblogs.com/SanMaoSpace/p/4802797.html,如需轉(zhuǎn)載請自行聯(lián)系原作者總結(jié)
以上是生活随笔為你收集整理的[转载].NET商业软件源码保护的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广州的房价是我遥不可及的梦,今天就用Py
- 下一篇: asp.net mvc如何设置起始页