天天看點

混淆加密後的JS代碼能還原嗎?

作者:JShaman

JS代碼混淆加密後,能被逆向破解、還原為原始代碼嗎?

嚴謹地說:真不能,最最最起碼是絕不可能完全還原。

JS代碼混淆加密,有多種技術手段,大體上可分為:編碼、加密算法、代碼變形、邏輯順序變化。

不否認,其中,某些是可以逆向的,例如字元編碼:字元串内容進行Unicode編碼、16進制編碼、Base64編碼後,是可以反向還原的。

例程:

console.log("hi");           

使用JShaman對上面一句代碼中的字元進行編碼,編碼後得到的新代碼:

console['\x6c\x6f\x67']("\u0068\u0069");           

其中log三個字母變成了\x6c\x6f\x67,這是十六進制化了,hi變成了\u0068\u0069,這是進行了unicode化。

這類編碼确實是可以還原的,如:

\x6c\x6f\x67的解碼方式:

"\x6c\x6f\x67".replace(/\\x(\w{2})/g,function(x){ return String.fromCharCode(parseInt(x,16)) });           

\u0068\u0069的解碼方式:

"\u0068\u0069".replace(/\\/g,"%");           

此時的階段性觀點:不否認某些是可以還原的,但是如前面所述,混淆加密手段有多種,現實中,正常對JS代碼加密時,不可能隻使用簡單的編碼,而還會啟用衆多其它混淆加密選項。

注:如果非要隻用幾個簡單的編碼,來證明加密後可逆。對于此種了解,不做辯解。

而更多混淆加密方法,是絕不可能破解或逆向的,比如:

var name = "Tom";
var age = "18";           

這兩行代碼中,定義了兩個變量,從名稱即可知道,一個是名字,另一個是年齡。

同樣用JShaman加密後,得到:

var _ = "Tom";
var _2 = "18";           

兩個有意義的變量名,變成了無意義的下劃線。

試想:如果隻是拿到加密後的代碼,如何能知道原來是變量名是什麼?

能破解成為原始代碼嗎?真的,目前,地球人的科技做不到。

又比如下面3行代碼:

var num1 = 3;
var num2 = 1+2;
var num3=function(s,h){return s^h;}(738158,738157);           

加密後得到:

var num1=function(s,h){return s^h;}(874506,874505);
var num2=function(s,h){return s+h;}(722724^722725,768350^768348);
var num3=function(s,h){return s^h;}(738158,738157);           

這是對數值進行了變形,加密後的代碼邏輯很簡單,似乎最終都可以認為指派是3,例如:

var num1 = 3;
var num2 = 3;
var num3 = 3;           

但,這僅僅是推測,這種暴力的還原,已然破壞了原始代碼,即:破解錯了!

或許有人說:跟原始代碼值差不多。好像是的,但邏輯已經破壞。

而且,這是用簡單的代碼舉例,現實中的代碼不能這麼簡單,且不論代碼量級,這種用力過度的還原,已經破壞了原有的代碼含義。

再比如:

同樣是上例中的3行代碼,在加密時使用“僵屍代碼植入”後,可以成為:

var _0x;
var num1 = function (s, h) { return s ^ h;}(467688, 467691);
_0x = 972677 ^ 972685;
var _0x2;
var num2 = function (s, h) { return s + h;}(754013 ^ 754012, 887759 ^ 887757);
_0x2 = "cpde";
var _0x3 = function (s, h) { return s + h;}(807363 ^ 807370, 383146 ^ 383147);
var num3 = function (s, h) { return s ^ h;}(738158, 738157);
_0x3 = 738774 ^ 738774;           

注:為分辨原始3個變量,未對變量名變形。

也就是,代碼中随機插入了無用的“僵屍代碼”,而且這些代碼可能包含變量、函數、邏輯,還可能有指派、有引用。

真講:無法差別哪個是原來的變量、哪個是新增出的僵屍變量。

不可能破解

不多綴述,以上幾例不可逆操作,已經說明:使用某些技術方案後,加密出的JS代碼是不可能還原為原始代碼的,更别說有些人希望破解得到“100%原始代碼”。

此外,JS代碼保護還有很多加密選項,例如AST化、虛拟機保護、控制流收縮等等,綜合使用起來,會進一步提升加密保護強度,破解并得到原始代碼這個需要,會變的愈發困難。

時間代價

從另一個角度講:JS代碼混淆加密的目的,是為了防止破解。保護強度越高,破解難度越大,所需要消耗的時間越久,當消耗時長超過一定值,比如開發一個功能需要30天,而破解則需要40天,則破解的代價已變的不可接受,如此便等同于防止破解。

法律層面

做為補充,這裡再加一些文字,淺談破解的法律風險,破解者可能面臨的後果。

進行JS代碼破解、解密,涉嫌觸犯以下多條法律條款,若被起訴将面臨刑事責任:

根據刑法第286條破壞計算機資訊系統罪,可處五年以下有期徒刑或者拘役;後果特别嚴重的,處五年以上有期徒刑。

注:不公開、不傳播、不對第三方造成損害情形除外。

提供收費JS破解者,除了觸犯刑法第286條,同時還犯侵犯著作權罪:

根據刑法第217條侵犯著作權罪,可處三年以下有期徒刑,特别嚴重情節的,處三年以上十年以下有期徒刑。

有種情況:破解者不直接提供破解,而是開發破解工具、或将破解過程寫成文章釋出,此行為視為傳授破解方法,犯傳授犯罪方法。

根據刑法第295條傳授犯罪方法罪,可處五年以下有期徒刑,情節特别嚴重的,處十年以上有期徒刑或者無期徒刑。

也就是說,進行JS代碼破解、逆向,是種犯罪行為,真正有技術、有能力、有正規收入來源的技術人員,相信不會輕易進行觸犯法律的嘗試。也就意味着對JS代碼進行加密後,會間接得到法律層面的安全保障。

綜合

綜上所述,JS代碼加密後,極大的提高了代碼安全性,進行破解需要耗費大量時間,而且無法逆向得到原始代碼,還會使破解者會面臨違法犯罪風險。

是以,對JS代碼進行混淆加密,是保護代碼、保護版權、保護産品的有效方法。