文章來源:javascriptOnlineObfuscator">http://www.BizStruct.cn/JavascriptOnlineObfuscator
Javascript 代碼混淆的目的
Javascript 是一種解釋執行的腳本語言,主要應用於 Web 領域的客戶端的浏覽器中;由於 Javascript 解釋執行的特性,代碼必須明文下載到客戶端,並且可以很容易的進行調試,使得 Javascript 代碼的保護非常困難;
不同的人對 Javascript 代碼的保護有不同的看法;有的人辛苦努力的代碼,卻可以被競爭對手輕易獲得,他們就非常希望能有保護 Javascript 代碼的方案,但現有的方案可能無法滿足他們的要求;很多人認為 Javascript 語言很簡單,Javascript 代碼沒有保護的價值,可能是他們的代碼確實簡單,或者他們並不了解 Javascript 語言強大的功能;還有的人認為現在都開源了,還保護代碼干什麼,當然開源的人是值得敬佩的,但對別人的代碼的開源要求,卻不是合理的。
為了提高用戶的體驗,出現了 Web 2.0 技術,並隨著 Ajax 和富界面技術的發展,Javascript 在 Web 應用上的重要性越來越高,Javascript 代碼的復雜性、功能和技術含量也越來越高,對Javascript 代碼保護的需要也越來越迫切。
Javascript 在線混淆器的目的是為 Javascript 代碼保護的需求,提供一種全新的綜合解決方案,包括編碼規則和免費的在線混淆器。
混淆和加密的區別
很多人將這兩者混在一起討論,實際上兩者的目的有一定的區別,采取的手段也有很大的不同。加密主要是為了防止未經授權的使用,對這種情況即使破解了加密,也只能非法使用,並不一定能獲得軟件的代碼邏輯;但對於腳本來說,防止對代碼進行訪問的措施,也屬於加密,對這種情況,破解了加密,就獲得了代碼;而混淆是在無法阻止他人獲取代碼的情況下,采取的保護代碼的邏輯不被他人理解的措施;對於混淆的代碼,他人很難理解,無法進行修改和重新應用;
對於生成機器碼的語言,比如 C 語言,只需要考慮未經授權的訪問,幾乎不需考慮代碼的保護;因為對編譯後的軟件,只能反匯編為匯編語言代碼,幾乎無法分析出代碼的邏輯。
對於生成中間代碼的語言,比如 Java 和 C#,即需要考慮未經授權的訪問,又需考慮代碼的保護;;因為對編譯後的軟件,可以很容易的反編譯為較高級的語言,從而了解到代碼中的邏輯,並較容易的破解加密。而混淆後,即難於理解代碼的邏輯,也不易找到加密點所在。
對於腳本語言,比如 Javascript,只能混淆,難以加密;因為腳本都是明文存在的,很容易調試的,通過跟蹤可以較容易的破解上面兩種目的的加密。但是混淆後的代碼是難於理解代碼的邏輯的。
我們只涉及到對 Javascript 腳本進行混淆,而不涉及加密;對於涉及到 Javascript 的系統的加密,我們建議不要將加密點放在 Javascript 腳本內,而是放在服務端的編譯程序內,因為編譯程序的加密可以采用更多的保護方式,加密的強度也更高。
我們首先要分析 Javascript 語言和混淆相關的特點,和現有的混淆產品的不足,然後再提出我們對 Javascript 代碼混淆的解決方案,最後是我們的 Javascript 在線混淆器。
Javascript 語言和混淆相關的特性
Javascript 是一種解釋執行的腳本語言,相對編譯類型的語言有很多自身的特性,而其中一些特性會對代碼混淆帶來很大的困難。
無法定義類的屬性和方法的名稱是否需要被混淆
Javascript 是一種基於原型的語言,沒有嚴格的類型定義。在自定義的類中,對於需要外部訪問的屬性和方法,不能進行混淆;對於內部訪問的屬性和方法,需要進行混淆;但Javascript 語言本身,無法對屬性和方法進行這樣的區分。為此我們要尋找一種變通的機制來識別屬性和方法的名稱是否需要混淆。
存在大量的系統定義的核心的和客戶端的方法和屬性不能被混淆
Javascript 語言本身定義了大量的核心的類、方法和屬性;浏覽器中也定義了大量的客戶端的類、方法和屬性;這些類、方法和屬性都不能夠被混淆,然而這些類、方法和屬性的數量太大,無法通過枚舉來避免混淆;為此我們需要尋找一種方法來標識這些類、屬性和方法。
無法定義全局變量是否需要被混淆
全局變量是 window 對象的屬性,局部變量是函數對象的屬性;所有的局部變量都是可以和應該被混淆的,而全局變量有的需要混淆,有的不能混淆;但全局變量和局部變量的表現形式是一樣的,難以區分;而且全局變量本身更無法定義是否需要被混淆。為此我們要找到一種方法來區分不能混淆的全局變量,和需要混淆的全局變量及局部變量。
Javascript 語言的這些特點,都對代碼的混淆帶來了很大的困難,如果不解決這幾個問題,Javascript 代碼的混淆就缺少實用的價值。
現有 Javascript 混淆產品的問題
當我們需要混淆 Javascipt 代碼的時候,首先考察了市面上現有的產品,和一些論壇裡對混淆的思路,但這些產品和思路都不能滿足我們的要求。
有一個商品化的 Javascript 混淆產品,采用了和一種 C# 混淆工具相似的混淆方式,分析了代碼裡所有的標識符,對一些系統預設的標識符不混淆,對其他的進行混淆,同時提供用戶對標識符的混淆進行選擇和配置;這個產品的功能很多很復雜,但有一個很大的問題,就是預設的標識符有限,對於代碼中用到的大量的系統定義的屬性和方法,會進行混淆,為此需要自己手工配置,避免對這些屬性和方法的混淆,這對於大型的系統幾乎是一個不可能完成的任務。
有一些論壇裡也討論到混淆的思路,包括一些示例,這些思路更多的是改變標識符的表現形式,有的是用編碼字符串的關聯數組替換屬性,比如將 xx.dd 替換為 xx["\x64\x64"];更復雜的是把 "\x64\x64" 之類保存到字符串數組,然後調用字符串數組作為關聯數組的下標;這種思路可以避免上面的問題,但有一個更大的問題,就是混淆是可逆的,被混淆的標識符僅僅是被轉換成了16進制的形式,可以很容易的恢復。
正是現有產品的不足,促使我們不得不研究自己的解決方案。我們的解決方案也是經過了幾個版本,一開始的版本要復雜的多,花費了很大的工作量,但結果並不理想;幾經修改才找到現有的解決方案;雖然開始的大量工作,最後幾乎都廢棄了,但沒有前面的工作,也就沒有後面的結果;所以即使您可能會認為我們的方案簡單,那也只是我們努力的結果,而不是過程;而且簡單的東西,往往是有效的。
Javascript 代碼混淆綜合解決方案
通過前面對 Javascript 的特