Javascript代碼混淆綜合解決方案-Javascript在線混淆器
Javascript 代碼混淆的目的
Javascript 是一種解釋執(zhí)行的腳本語(yǔ)言,主要應(yīng)用于 Web 領(lǐng)域的客戶端的瀏覽器中;由于 Javascript 解釋執(zhí)行的特性,代碼必須明文下載到客戶端,并且可以很容易的進(jìn)行調(diào)試,使得 Javascript 代碼的保護(hù)非常困難;
不同的人對(duì) Javascript 代碼的保護(hù)有不同的看法;有的人辛苦努力的代碼,卻可以被競(jìng)爭(zhēng)對(duì)手輕易獲得,他們就非常希望能有保護(hù) Javascript 代碼的方案,但現(xiàn)有的方案可能無(wú)法滿足他們的要求;很多人認(rèn)為 Javascript 語(yǔ)言很簡(jiǎn)單,Javascript 代碼沒(méi)有保護(hù)的價(jià)值,可能是他們的代碼確實(shí)簡(jiǎn)單,或者他們并不了解 Javascript 語(yǔ)言強(qiáng)大的功能;還有的人認(rèn)為現(xiàn)在都開(kāi)源了,還保護(hù)代碼干什么,當(dāng)然開(kāi)源的人是值得敬佩的,但對(duì)別人的代碼的開(kāi)源要求,卻不是合理的。
為了提高用戶的體驗(yàn),出現(xiàn)了 Web 2.0 技術(shù),并隨著 AJAX 和富界面技術(shù)的發(fā)展,Javascript 在 Web 應(yīng)用上的重要性越來(lái)越高,Javascript 代碼的復(fù)雜性、功能和技術(shù)含量也越來(lái)越高,對(duì)Javascript 代碼保護(hù)的需要也越來(lái)越迫切。
Javascript 在線混淆器的目的是為 Javascript 代碼保護(hù)的需求,提供一種全新的綜合解決方案,包括編碼規(guī)則和免費(fèi)的在線混淆器。
混淆和加密的區(qū)別
很多人將這兩者混在一起討論,實(shí)際上兩者的目的有一定的區(qū)別,采取的手段也有很大的不同。加密主要是為了防止未經(jīng)授權(quán)的使用,對(duì)這種情況即使破解了加密,也只能非法使用,并不一定能獲得軟件的代碼邏輯;但對(duì)于腳本來(lái)說(shuō),防止對(duì)代碼進(jìn)行訪問(wèn)的措施,也屬于加密,對(duì)這種情況,破解了加密,就獲得了代碼;而混淆是在無(wú)法阻止他人獲取代碼的情況下,采取的保護(hù)代碼的邏輯不被他人理解的措施;對(duì)于混淆的代碼,他人很難理解,無(wú)法進(jìn)行修改和重新應(yīng)用;
對(duì)于生成機(jī)器碼的語(yǔ)言,比如 C 語(yǔ)言,只需要考慮未經(jīng)授權(quán)的訪問(wèn),幾乎不需考慮代碼的保護(hù);因?yàn)閷?duì)編譯后的軟件,只能反匯編為匯編語(yǔ)言代碼,幾乎無(wú)法分析出代碼的邏輯。
對(duì)于生成中間代碼的語(yǔ)言,比如 Java 和 C#,即需要考慮未經(jīng)授權(quán)的訪問(wèn),又需考慮代碼的保護(hù);;因?yàn)閷?duì)編譯后的軟件,可以很容易的反編譯為較高級(jí)的語(yǔ)言,從而了解到代碼中的邏輯,并較容易的破解加密。而混淆后,即難于理解代碼的邏輯,也不易找到加密點(diǎn)所在。
對(duì)于腳本語(yǔ)言,比如 Javascript,只能混淆,難以加密;因?yàn)槟_本都是明文存在的,很容易調(diào)試的,通過(guò)跟蹤可以較容易的破解上面兩種目的的加密。但是混淆后的代碼是難于理解代碼的邏輯的。
我們只涉及到對(duì) Javascript 腳本進(jìn)行混淆,而不涉及加密;對(duì)于涉及到 Javascript 的系統(tǒng)的加密,我們建議不要將加密點(diǎn)放在 Javascript 腳本內(nèi),而是放在服務(wù)端的編譯程序內(nèi),因?yàn)榫幾g程序的加密可以采用更多的保護(hù)方式,加密的強(qiáng)度也更高。
我們首先要分析 Javascript 語(yǔ)言和混淆相關(guān)的特點(diǎn),和現(xiàn)有的混淆產(chǎn)品的不足,然后再提出我們對(duì) Javascript 代碼混淆的解決方案,最后是我們的 Javascript 在線混淆器。
Javascript 語(yǔ)言和混淆相關(guān)的特性
Javascript 是一種解釋執(zhí)行的腳本語(yǔ)言,相對(duì)編譯類(lèi)型的語(yǔ)言有很多自身的特性,而其中一些特性會(huì)對(duì)代碼混淆帶來(lái)很大的困難。
無(wú)法定義類(lèi)的屬性和方法的名稱(chēng)是否需要被混淆
Javascript 是一種基于原型的語(yǔ)言,沒(méi)有嚴(yán)格的類(lèi)型定義。在自定義的類(lèi)中,對(duì)于需要外部訪問(wèn)的屬性和方法,不能進(jìn)行混淆;對(duì)于內(nèi)部訪問(wèn)的屬性和方法,需要進(jìn)行混淆;但Javascript 語(yǔ)言本身,無(wú)法對(duì)屬性和方法進(jìn)行這樣的區(qū)分。為此我們要尋找一種變通的機(jī)制來(lái)識(shí)別屬性和方法的名稱(chēng)是否需要混淆。
存在大量的系統(tǒng)定義的核心的和客戶端的方法和屬性不能被混淆
Javascript 語(yǔ)言本身定義了大量的核心的類(lèi)、方法和屬性;瀏覽器中也定義了大量的客戶端的類(lèi)、方法和屬性;這些類(lèi)、方法和屬性都不能夠被混淆,然而這些類(lèi)、方法和屬性的數(shù)量太大,無(wú)法通過(guò)枚舉來(lái)避免混淆;為此我們需要尋找一種方法來(lái)標(biāo)識(shí)這些類(lèi)、屬性和方法。
無(wú)法定義全局變量是否需要被混淆
全局變量是 window 對(duì)象的屬性,局部變量是函數(shù)對(duì)象的屬性;所有的局部變量都是可以和應(yīng)該被混淆的,而全局變量有的需要混淆,有的不能混淆;但全局變量和局部變量的表現(xiàn)形式是一樣的,難以區(qū)分;而且全局變量本身更無(wú)法定義是否需要被混淆。為此我們要找到一種方法來(lái)區(qū)分不能混淆的全局變量,和需要混淆的全局變量及局部變量。
Javascript 語(yǔ)言的這些特點(diǎn),都對(duì)代碼的混淆帶來(lái)了很大的困難,如果不解決這幾個(gè)問(wèn)題,Javascript 代碼的混淆就缺少實(shí)用的價(jià)值。
現(xiàn)有 Javascript 混淆產(chǎn)品的問(wèn)題
當(dāng)我們需要混淆 Javascipt 代碼的時(shí)候,首先考察了市面上現(xiàn)有的產(chǎn)品,和一些論壇里對(duì)混淆的思路,但這些產(chǎn)品和思路都不能滿足我們的要求。
有一個(gè)商品化的 Javascript 混淆產(chǎn)品,采用了和一種 C# 混淆工具相似的混淆方式,分析了代碼里所有的標(biāo)識(shí)符,對(duì)一些系統(tǒng)預(yù)設(shè)的標(biāo)識(shí)符不混淆,對(duì)其他的進(jìn)行混淆,同時(shí)提供用戶對(duì)標(biāo)識(shí)符的混淆進(jìn)行選擇和配置;這個(gè)產(chǎn)品的功能很多很復(fù)雜,但有一個(gè)很大的問(wèn)題,就是預(yù)設(shè)的標(biāo)識(shí)符有限,對(duì)于代碼中用到的大量的系統(tǒng)定義的屬性和方法,會(huì)進(jìn)行混淆,為此需要自己手工配置,避免對(duì)這些屬性和方法的混淆,這對(duì)于大型的系統(tǒng)幾乎是一個(gè)不可能完成的任務(wù)。
有一些論壇里也討論到混淆的思路,包括一些示例,這些思路更多的是改變標(biāo)識(shí)符的表現(xiàn)形式,有的是用編碼字符串的關(guān)聯(lián)數(shù)組替換屬性,比如將 xx.dd 替換為 xx["\x64\x64"];更復(fù)雜的是把 "\x64\x64" 之類(lèi)保存到字符串?dāng)?shù)組,然后調(diào)用字符串?dāng)?shù)組作為關(guān)聯(lián)數(shù)組的下標(biāo);這種思路可以避免上面的問(wèn)題,但有一個(gè)更大的問(wèn)題,就是混淆是可逆的,被混淆的標(biāo)識(shí)符僅僅是被轉(zhuǎn)換成了16進(jìn)制的形式,可以很容易的恢復(fù)。
正是現(xiàn)有產(chǎn)品的不足,促使我們不得不研究自己的解決方案。我們的解決方案也是經(jīng)過(guò)了幾個(gè)版本,一開(kāi)始的版本要復(fù)雜的多,花費(fèi)了很大的工作量,但結(jié)果并不理想;幾經(jīng)修改才找到現(xiàn)有的解決方案;雖然開(kāi)始的大量工作,最后幾乎都廢棄了,但沒(méi)有前面的工作,也就沒(méi)有后面的結(jié)果;所以即使您可能會(huì)認(rèn)為我們的方案簡(jiǎn)單,那也只是我們努力的結(jié)果,而不是過(guò)程;而且簡(jiǎn)單的東西,往往是有效的。
Javascript 代碼混淆綜合解決方案
通過(guò)前面對(duì) Javascript 的特性和相關(guān)混淆產(chǎn)品的分析,使我們認(rèn)識(shí)到如果僅僅是在混淆器上下功夫是不夠的;因?yàn)?Javascript 語(yǔ)言本身對(duì)混淆的功能有很大的限制,無(wú)法解決。為此我們?cè)O(shè)計(jì)了一個(gè)綜合的解決方案,就是 Javascript 在線混淆器規(guī)則,只要是按照規(guī)則編寫(xiě)的 Javascipt 代碼,都能使用 Javascript 在線混淆器混淆進(jìn)行混淆。
Javascript 在線混淆器的規(guī)則并不復(fù)雜,但能夠解決 Javascript 語(yǔ)言本身的特性和其他混淆產(chǎn)品遇到的問(wèn)題。
規(guī)則一、所有用 window 約束的類(lèi)、變量和函數(shù)都不混淆,其他的類(lèi)、變量和函數(shù)都混淆。
全局的類(lèi)、變量和函數(shù)本身都是 window 的屬性,用不用 window 約束,從邏輯的角度是一樣的。但我們可以借用 window 的約束來(lái)區(qū)分對(duì)全局的類(lèi)、變量和函數(shù)是否需要進(jìn)行混淆。
用 window 的約束必須是前后一致的,不但包括類(lèi)、變量和函數(shù)的定義,也包括類(lèi)、變量和函數(shù)的調(diào)用。
局部的類(lèi)、變量和函數(shù),因?yàn)闆](méi)有 window 約束,所以都是混淆的。
類(lèi)型 | 混淆 | 不混淆 |
類(lèi)定義 | function Class1(){...} | window.Class1 = function(){...} |
函數(shù)定義 | function Method1(){...} | window.Method1 = function(){...} |
變量定義 | var Param1 = 1; | window.Param1 = 1; |
生成類(lèi)的實(shí)例 | var object1 = new Class1(); | var object1 = new window.Class1(); |
函數(shù)調(diào)用 | Method1(); | window.Method1() |
變量引用 | var newParam = Param1; | var newParam = window.Param1; |
規(guī)則二、所有以小寫(xiě)字符開(kāi)頭的屬性和方法都不混淆,以其他字母開(kāi)頭的屬性和方法都混淆,用 window 約束的屬性和方法應(yīng)用規(guī)則一。
JavaScript 核心和客戶端中有大量的系統(tǒng)定義的方法和屬性不能被混淆,而這些方法和屬性絕大多數(shù)都是以小寫(xiě)字母開(kāi)始的,本規(guī)則保證了系統(tǒng)定義的方法和屬性不被混淆。在 Javascript 客戶端中僅有極少數(shù)的系統(tǒng)定義的以大寫(xiě)字符起始的方法和屬性,對(duì)于這種情況,可以采用關(guān)聯(lián)數(shù)組的方式避免被混淆,比如 object1["Method1"]();此方法也適用于第三方控件中可能會(huì)有的以大寫(xiě)字符起始的方法和屬性的情況。
此規(guī)則也使我們可以在自定義的類(lèi)中標(biāo)識(shí)方法和屬性是否被混淆,對(duì)于需要外部調(diào)用不能混淆的方法和屬性,采用小寫(xiě)字母起始,對(duì)于內(nèi)部的方法和屬性,采用其他字母起始。
類(lèi)型 | 混淆 | 不混淆 |
類(lèi)方法定義 | Class1.Method1 = function(){...} | Class1.method1 = function(){...} Class1["Method1"] = function(){...} |
對(duì)象方法定義 | Class1.prototype.Method1 = function(){...} | Class1.prototype.method1 = function(){...} Class1.prototype["Method1"] = function(){...} |
類(lèi)屬性定義 | Class1.Prop1 = 1; | Class1.prop1 = 1; Class1["Prop1"] = 1; |
對(duì)象屬性定義 | object1.Prop1 = 1; | object1.prop1 = 1; object1["Prop1"] = 1; |
類(lèi)方法調(diào)用 | Class1.Method1(); | Class1.method1 (); Class1["Method1"](); |
對(duì)象方法調(diào)用 | object1.Method1(); | object1.method1 (); object1["Method1"](); |
Javascript 在線混淆器的核心規(guī)則就是以上兩點(diǎn),另外還有幾點(diǎn)說(shuō)明。
標(biāo)識(shí)符的混淆采用 Hash 算法,不可逆
Hash 算法是不可逆的,所以不能根據(jù)混淆后的標(biāo)識(shí)符,來(lái)直接推出混淆前的標(biāo)識(shí)符;但 Hash 算法依賴于 .Net 系統(tǒng)的實(shí)現(xiàn),大多數(shù)的時(shí)候,.Net 的 Hash 算法是不變的,就是同一個(gè)標(biāo)識(shí)符的混淆結(jié)果是一樣的;如果能夠枚舉足夠多的標(biāo)識(shí)符,仍然可能根據(jù)相同的混淆結(jié)果,知道混淆前的標(biāo)識(shí)符。
如何調(diào)用混淆后的類(lèi)、方法和屬性
對(duì)于混淆代碼的內(nèi)部調(diào)用,只要采用相同的規(guī)則,要么都混淆,要么都不混淆,就能正確的調(diào)用。
對(duì)于混淆代碼的外部調(diào)用,可以有兩種方式,一種是不混淆,代碼內(nèi)部采用不混淆的規(guī)則,外部采用不混淆的可理解的標(biāo)識(shí)符調(diào)用;另一種是混淆,代碼內(nèi)部采用混淆的規(guī)則,外部也采用混淆后的不可理解的標(biāo)識(shí)符調(diào)用,但此方式依賴于 .Net Hash 算法的實(shí)現(xiàn),在不同版本的 .Net 實(shí)現(xiàn)中的 Hash 算法有可能不同,以至混淆后的標(biāo)識(shí)符不一致,從而導(dǎo)致重新混淆后,需要替換原來(lái)混淆的標(biāo)識(shí)符。
為何有“清除空格,保留分號(hào)后的回車(chē)”的選項(xiàng)
Javascript 語(yǔ)法要求全局函數(shù)的結(jié)尾必須有分號(hào)或回車(chē),如果遺漏了分號(hào),而又清除了所有的回車(chē),總是提示第一行缺少分號(hào),無(wú)法定位錯(cuò)誤所在;采用本選項(xiàng)可以有助于尋找缺少的分號(hào)的位置。
以下 Javascript 語(yǔ)言的保留字不混淆
break, case, catch, continue, debugger, default, delete, do, else, false, finally, for, function, if, in, instanceof, new, null, return, switch, this, throw, true, try, typeof, var, while, with
混淆器預(yù)定義了一些 window 的屬性和方法
Javascript 核心類(lèi)和函數(shù)是不能被混淆的,他們實(shí)質(zhì)上都是 window 的屬性和方法,按照規(guī)則應(yīng)該用 window 約束,以避免被混淆;但對(duì)于 Object、Array、Date、ActiveXObject 等核心類(lèi),混淆器已經(jīng)預(yù)定義不會(huì)混淆,不需要再用 window 約束。對(duì)于 alert 等 window 常用的方法和 document 等 window 常用的客戶端屬性,也有預(yù)定義。其他需要預(yù)定義的類(lèi)和方法,我們會(huì)逐步添加;沒(méi)有預(yù)定義的全局類(lèi)和函數(shù),如果不能混淆,必須用 window 約束。
以下全局的類(lèi)、變量和方法不混淆
ActiveXObject, alert, Array, Boolean, Date , document, Math, Number, Object, RegExp, String, window
Javascript 在線混淆器
請(qǐng)?jiān)L問(wèn) http://www.BizStruct.cn/JavascriptOnlineObfuscator/JavascriptOnlineObfuscator.aspx 。
相關(guān)文章
JavaScript利用Immerjs實(shí)現(xiàn)不可變數(shù)據(jù)
Immerjs?是一個(gè)用于管理?JavaScript?不可變數(shù)據(jù)結(jié)構(gòu)的庫(kù),它可以幫助我們更輕松地處理狀態(tài)的變化,并減少冗余代碼。本文就來(lái)帶大家揭秘如何利用Immerjs實(shí)現(xiàn)不可變數(shù)據(jù),感興趣的可以了解一下2023-04-04關(guān)于微信中a鏈接無(wú)法跳轉(zhuǎn)問(wèn)題
微信頁(yè)面開(kāi)發(fā)時(shí),各個(gè)主頁(yè)之間的跳轉(zhuǎn),完全是通過(guò)a鏈接進(jìn)行的,但是來(lái)回跳轉(zhuǎn)幾次,再次從其他主頁(yè)面跳回首頁(yè)的時(shí)候,微信頭部出現(xiàn)了跳轉(zhuǎn)加載進(jìn)度條,但是就是不跳轉(zhuǎn),也沒(méi)有任何反應(yīng),怎么回事呢?下面小編給大家解答下2016-08-08JavaScript canvas動(dòng)畫(huà)實(shí)現(xiàn)時(shí)鐘效果
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas動(dòng)畫(huà)實(shí)現(xiàn)時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02深入理解requestAnimationFrame的動(dòng)畫(huà)循環(huán)
這篇文章先給大家介紹了什么是requestAnimationFrame,而后才深入講述關(guān)于requestAnimationFrame的動(dòng)畫(huà)循環(huán),文章介紹的非常詳細(xì),相信對(duì)大家學(xué)習(xí)requestAnimationFrame具有一定的參考借鑒價(jià)值,有需要的朋友下面來(lái)一起看看吧。2016-09-09簡(jiǎn)單實(shí)例處理url特殊符號(hào)&處理(2種方法)
url里的參數(shù)內(nèi)容包含&符合,我有兩種方法解決一是:在頁(yè)面用JS轉(zhuǎn)碼;二是:在后端處理,另外還有網(wǎng)絡(luò)分享的一些方法,感興趣的朋友可以參考下哈2013-04-04js+CSS實(shí)現(xiàn)彈出居中背景半透明div層的方法
這篇文章主要介紹了js+CSS實(shí)現(xiàn)彈出居中背景半透明div層的方法,涉及javascript操作彈出div層的操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-02-02JavaScript動(dòng)態(tài)檢驗(yàn)密碼強(qiáng)度的實(shí)現(xiàn)方法
平時(shí)我們會(huì)在某些網(wǎng)站的注冊(cè)頁(yè)面或者更改密碼的頁(yè)面發(fā)現(xiàn)當(dāng)我們輸入密碼時(shí),會(huì)有一個(gè)類(lèi)似于進(jìn)度條的長(zhǎng)條進(jìn)行提示用戶輸入的密碼強(qiáng)度。那么這種效果怎么實(shí)現(xiàn)的呢?下面小編給大家介紹下js動(dòng)態(tài)檢驗(yàn)密碼強(qiáng)度的實(shí)現(xiàn)方法,一起看看吧2016-11-11解決layui彈出層layer的area過(guò)大被遮擋的問(wèn)題
今天小編就為大家分享一篇解決layui彈出層layer的area過(guò)大被遮擋的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09