国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript混淆安全加固

gaara / 1873人閱讀

摘要:但事實(shí)上,即使不了解密碼學(xué),也應(yīng)知道是有意義的,因?yàn)榧用芮昂徒饷芎蟮沫h(huán)節(jié),是不受保護(hù)的。廢代碼注入插入一些永遠(yuǎn)不會發(fā)生的代碼,讓攻擊者在分析代碼的時候被這些無用的廢代碼混淆視聽,增加閱讀難度。

前言

在安全攻防戰(zhàn)場中,前端代碼都是公開的,那么對前端進(jìn)行加密有意義嗎?可能大部分人的回答是,毫無意義,不要自創(chuàng)加密算法,直接用HTTPS吧。但事實(shí)上,即使不了解密碼學(xué),也應(yīng)知道是有意義的,因?yàn)?b>加密前和解密后的環(huán)節(jié),是不受保護(hù)的。HTTPS只能保護(hù)傳輸層,此外別無用處。

而加密環(huán)節(jié)又分:

傳輸加密(對抗鏈路破解)

數(shù)據(jù)加密(對抗協(xié)議破解)

代碼加密(隱藏算法、反調(diào)試...)

本文主要列舉一些我見到的,我想到的一些加密方式,其實(shí)確切的說,應(yīng)該叫混淆,不應(yīng)該叫加密。

那么,代碼混淆的具體原理是什么?其實(shí)很簡單,就是去除代碼中盡可能多的有意義的信息,比如注釋、換行、空格、代碼負(fù)號、變量重命名、屬性重命名(允許的情況下)、無用代碼的移除等等。因?yàn)榇a是公開的,我們必須承認(rèn)沒有任何一種算法可以完全不被破解,所以,我們只能盡可能增加攻擊者閱讀代碼的成本。

原文地址

語法樹AST混淆

在保證代碼原本的功能性的情況下,我們可以對代碼的AST按需進(jìn)行變更,然后將變更后的AST在生成一份代碼進(jìn)行輸出,達(dá)到混淆的目的,我們最常用的uglify-js就是這樣對代碼進(jìn)行混淆的,當(dāng)然uglify-js的混淆只是主要進(jìn)行代碼壓縮,即我們下面講到的變量名混淆。

變量名混淆

將變量名混淆成閱讀比較難閱讀的字符,增加代碼閱讀難度,上面說的uglify-js進(jìn)行的混淆,就是把變量混淆成了短名(主要是為了進(jìn)行代碼壓縮),而現(xiàn)在大部分安全方向的混淆,都會將其混淆成類16進(jìn)制變量名,效果如下:

var test = "hello";

混淆后:

var _0x7deb = "hello";

注意事項(xiàng):

eval語法,eval函數(shù)中可能使用了原來的變量名,如果不對其進(jìn)行處理,可能會運(yùn)行報(bào)錯,如下:

var test = "hello";
eval("console.log(test)");

如果不對eval中的console.log(test)進(jìn)行關(guān)聯(lián)的混淆,則會報(bào)錯。不過,如果eval語法超出了靜態(tài)分析的范疇,比如:

var test = "hello";
var variableName = "test";
eval("console.log(" + variableName + ")");

這種咋辦呢,可能要進(jìn)行遍歷AST找到其運(yùn)行結(jié)果,然后在進(jìn)行混淆,不過貌似成本比較高。

全局變量的編碼,如果代碼是作為SDK進(jìn)行輸出的,我們需要保存全局變量名的不變,比如:

$變量是放在全局下的,混淆過后如下:

那么如果依賴這一段代碼的模塊,使用$("id")調(diào)用自然會報(bào)錯,因?yàn)檫@個全局變量已經(jīng)被混淆了。

常量提取

將JS中的常量提取到數(shù)組中,調(diào)用的時候用數(shù)組下標(biāo)的方式調(diào)用,這樣的話直接讀懂基本不可能了,要么反AST處理下,要么一步一步調(diào)試,工作量大增。

以上面的代碼為例:

var test = "hello";

混淆過后:

var _0x9d2b = ["hello"];

var _0xb7de = function (_0x4c7513) {
    var _0x96ade5 = _0x9d2b[_0x4c7513];
    return _0x96ade5;
};

var test = _0xb7de(0);

當(dāng)然,我們可以根據(jù)需求,將數(shù)組轉(zhuǎn)化為二位數(shù)組、三維數(shù)組等,只需要在需要用到的地方獲取就可以。

常量混淆

將常量進(jìn)行加密處理,上面的代碼中,雖然已經(jīng)是混淆過后的代碼了,但是hello字符串還是以明文的形式出現(xiàn)在代碼中,可以利用JS中16進(jìn)制編碼會直接解碼的特性將關(guān)鍵字的Unicode進(jìn)行了16進(jìn)制編碼。如下:

var test = "hello";

結(jié)合常量提取得到混淆結(jié)果:

var _0x9d2b = ["x68x65x6cx6cx6f"];

var _0xb7de = function (_0x4c7513) {
    _0x4c7513 = _0x4c7513 - 0x0;
    var _0x96ade5 = _0x9d2b[_0x4c7513];
    return _0x96ade5;
};

var test = _0xb7de("0x0");

當(dāng)然,除了JS特性自帶的Unicode自動解析以外,也可以自定義一些加解密算法,比如對常量進(jìn)行base64編碼,或者其他的什么rc4等等,只需要使用的時候解密就OK,比如上面的代碼用base64編碼后:

var _0x9d2b = ["aGVsbG8="]; // base64編碼后的字符串

var _0xaf421 = function (_0xab132) {
    // base64解碼函數(shù)
    var _0x75aed = function(_0x2cf82) {
        // TODO: 解碼
    };
    return _0x75aed(_0xab132);
}

var _0xb7de = function (_0x4c7513) {
    _0x4c7513 = _0x4c7513 - 0x0;
    var _0x96ade5 = _0xaf421(_0x9d2b[_0x4c7513]);
    return _0x96ade5;
};

var test = _0xb7de("0x0");
運(yùn)算混淆

將所有的邏輯運(yùn)算符、二元運(yùn)算符都變成函數(shù),目的也是增加代碼閱讀難度,讓其無法直接通過靜態(tài)分析得到結(jié)果。如下:

var i = 1 + 2;
var j = i * 2;
var k = j || i;

混淆后:

var _0x62fae = {
    _0xeca4f: function(_0x3c412, _0xae362) {
        return _0x3c412 + _0xae362;
    },
    _0xe82ae: function(_0x63aec, _0x678ec) {
        return _0x63aec * _0x678ec;
    },
    _0x2374a: function(_0x32487, _0x3a461) {
        return _0x32487 || _0x3a461;
    }
};

var i = _0x62fae._0e8ca4f(1, 2);
var j = _0x62fae._0xe82ae(i, 2);
var k = _0x62fae._0x2374a(i, j);

當(dāng)然除了邏輯運(yùn)算符和二元運(yùn)算符以外,還可以將函數(shù)調(diào)用、靜態(tài)字符串進(jìn)行類似的混淆,如下:

var fun1 = function(name) {
    console.log("hello, " + name);
};
var fun2 = function(name, age) {
    console.log(name + " is " + age + " years old");
}

var name = "xiao.ming";
fun1(name);
fun2(name, 8);
var _0x62fae = {
    _0xe82ae: function(_0x63aec, _0x678ec) {
        return _0x63aec(_0x678ec);
    },
    _0xeca4f: function(_0x92352, _0x3c412, _0xae362) {
        return _0x92352(_0x3c412, _0xae362)
    },
    _0x2374a: "xiao.ming",
    _0x5482a: "hello, ",
    _0x837ce: " is ",
    _0x3226e: " years old"
};

var fun1 = function(name) {
    console.log(_0x62fae._0x5482a + name);
};
var fun2 = function(name, age) {
    console.log(name + _0x62fae._0x837ce + age + _0x62fae._0x3226e);
}

var name = _0x62fae._0x2374a;
_0x62fae._0xe82ae(fun1, name);
_0x62fae._0xeca4f(fun2, name, 0x8);

上面的例子中,fun1和fun2內(nèi)的字符串相加也會被混淆走,靜態(tài)字符串也會被前面提到的字符串提取抽取到數(shù)組中(我就是懶,這部分代碼就不寫了)。

需要注意的是,我們每次遇到相同的運(yùn)算符,需不需要重新生成函數(shù)進(jìn)行替換,這就按個人需求了。

語法丑化

將我們常用的語法混淆成我們不常用的語法,前提是不改變代碼的功能。例如for換成do/while,如下:

for (i = 0; i < n; i++) { 
    // TODO: do something
}

var i = 0;
do {
    if (i >= n) break;
    
    // TODO: do something
    i++;
} while (true)
動態(tài)執(zhí)行

將靜態(tài)執(zhí)行代碼添加動態(tài)判斷,運(yùn)行時動態(tài)決定運(yùn)算符,干擾靜態(tài)分析。

如下:

var c = 1 + 2;

混淆過后:

function _0x513fa(_0x534f6, _0x85766) { return _0x534f6 + _0x85766; }
function _0x3f632(_0x534f6, _0x534f6) { return _0x534f6 - _0x534f6; }

// 動態(tài)判定函數(shù)
function _0x3fa24() {
    return true;
}

var c = _0x3fa24() ? _0x513fa(1, 2) : _0x3f632(1, 2);
流程混淆

對執(zhí)行流程進(jìn)行混淆,又稱控制流扁平化,為什么要做混淆執(zhí)行流程呢?因?yàn)樵诖a開發(fā)的過程中,為了使代碼邏輯清晰,便于維護(hù)和擴(kuò)展,會把代碼編寫的邏輯非常清晰。一段代碼從輸入,經(jīng)過各種if/else分支,順序執(zhí)行之后得到不同的結(jié)果,而我們需要將這些執(zhí)行流程和判定流程進(jìn)行混淆,讓攻擊者沒那么容易摸清楚我們的執(zhí)行邏輯。

控制流扁平化又分順序扁平化、條件扁平化,

順序扁平化

顧名思義,將按順序、自上而下執(zhí)行的代碼,分解成數(shù)個分支進(jìn)行執(zhí)行,如下代碼:

(function () {
    console.log(1);
    console.log(2);
    console.log(3);
    console.log(4);
    console.log(5);
})();

流程圖如下:

混淆過后代碼如下:

(function () {
    var flow = "3|4|0|1|2".split("|"), index = 0;
    while (!![]) {
        switch (flow[index++]) {
        case "0":
            console.log(3);
            continue;
        case "1":
            console.log(4);
            continue;
        case "2":
            console.log(5);
            continue;
        case "3":
            console.log(1);
            continue;
        case "4":
            console.log(2);
            continue;
        }
        break;
    }
}());

混淆過后的流程圖如下:

流程看起來了。

條件扁平化

條件扁平化的作用是把所有if/else分支的流程,全部扁平到一個流程中,在流程圖中擁有相同的入口和出口。

如下面的代碼:

function modexp(y, x, w, n) {
    var R, L;
    var k = 0;
    var s = 1;
    while(k < w) {
        if (x[k] == 1) {
            R = (s * y) % n;
        }
        else {
            R = s;
        }
        s = R * R % n;
        L = R;
        k++;
    }
    return L;
}

如上代碼,流程圖是這樣的

控制流扁平化后代碼如下:

function modexp(y, x, w, n) {
    var R, L, s, k;
    var next = 0;
    for(;;) {
        switch(next) {
        case 0: k = 0; s = 1; next = 1; break;
        case 1: if (k < w) next = 2; else next = 6; break;
        case 2: if (x[k] == 1) next = 3; else next = 4; break;
        case 3: R = (s * y) % n; next = 5; break;
        case 4: R = s; next = 5; break;
        case 5: s = R * R % n; L = R; k++; next = 1; break;
        case 6: return L;
        }
    }
}

混淆后的流程圖如下:

直觀的感覺就是代碼變了,所有的代碼都擠到了一層當(dāng)中,這樣做的好處在于在讓攻擊者無法直觀,或通過靜態(tài)分析的方法判斷哪些代碼先執(zhí)行哪些后執(zhí)行,必須要通過動態(tài)運(yùn)行才能記錄執(zhí)行順序,從而加重了分析的負(fù)擔(dān)。

需要注意的是,在我們的流程中,無論是順序流程還是條件流程,如果出現(xiàn)了塊作用域的變量聲明(const/let),那么上面的流程扁平化將會出現(xiàn)錯誤,因?yàn)閟witch/case內(nèi)部為塊作用域,表達(dá)式被分到case內(nèi)部之后,其他case無法取到const/let的變量聲明,自然會報(bào)錯。

不透明謂詞

上面的switch/case的判斷是通過數(shù)字(也就是謂詞)的形式判斷的,而且是透明的,可以看到的,為了更加的混淆視聽,可以將case判斷設(shè)定為表達(dá)式,讓其無法直接判斷,比如利用上面代碼,改為不透明謂詞:

function modexp(y, x, w, n) {
    var a = 0, b = 1, c = 2 * b + a;
    var R, L, s, k;
    var next = 0;
    for(;;) {
        switch(next) {
        case (a * b): k = 0; s = 1; next = 1; break;
        case (2 * a + b): if (k < w) next = 2; else next = 6; break;
        case (2 * b - a): if (x[k] == 1) next = 3; else next = 4; break;
        case (3 * a + b + c): R = (s * y) % n; next = 5; break;
        case (2 * b + c): R = s; next = 5; break;
        case (2 * c + b): s = R * R % n; L = R; k++; next = 1; break;
        case (4 * c - 2 * b): return L;
        }
    }
}

謂詞用a、b、c三個變量組成,甚至可以把這三個變量隱藏到全局中定義,或者隱藏在某個數(shù)組中,讓攻擊者不能那么輕易找到。

腳本加殼

將腳本進(jìn)行編碼,運(yùn)行時 解碼 再 eval 執(zhí)行如:

eval (…………………………..……………. ……………. !@#$%^&* ……………. .…………………………..……………. )

但是實(shí)際上這樣意義并不大,因?yàn)楣粽咧恍枰補(bǔ)lert或者console.log就原形畢露了

改進(jìn)方案:利用Function / (function(){}).constructor將代碼當(dāng)做字符串傳入,然后執(zhí)行,如下:

var code = "console.log("hellow")";
(new Function(code))();

如上代碼,可以對code進(jìn)行加密混淆,例如aaencode,原理也是如此,我們舉個例子

alert("Hello, JavaScript");

利用aaencode混淆過后,代碼如下:

?ω??= /`m′)? ~┻━┻   //*′?`*/ ["_"]; o=(???)  =_=3; c=(?Θ?) =(???)-(???); (?Д?) =(?Θ?)= (o^_^o)/ (o^_^o);(?Д?)={?Θ?: "_" ,?ω?? : ((?ω??==3) +"_") [?Θ?] ,???? :(?ω??+ "_")[o^_^o -(?Θ?)] ,?Д??:((???==3) +"_")[???] }; (?Д?) [?Θ?] =((?ω??==3) +"_") [c^_^o];(?Д?) ["c"] = ((?Д?)+"_") [ (???)+(???)-(?Θ?) ];(?Д?) ["o"] = ((?Д?)+"_") [?Θ?];(?o?)=(?Д?) ["c"]+(?Д?) ["o"]+(?ω?? +"_")[?Θ?]+ ((?ω??==3) +"_") [???] + ((?Д?) +"_") [(???)+(???)]+ ((???==3) +"_") [?Θ?]+((???==3) +"_") [(???) - (?Θ?)]+(?Д?) ["c"]+((?Д?)+"_") [(???)+(???)]+ (?Д?) ["o"]+((???==3) +"_") [?Θ?];(?Д?) ["_"] =(o^_^o) [?o?] [?o?];(?ε?)=((???==3) +"_") [?Θ?]+ (?Д?) .?Д??+((?Д?)+"_") [(???) + (???)]+((???==3) +"_") [o^_^o -?Θ?]+((???==3) +"_") [?Θ?]+ (?ω?? +"_") [?Θ?]; (???)+=(?Θ?); (?Д?)[?ε?]=""; (?Д?).?Θ??=(?Д?+ ???)[o^_^o -(?Θ?)];(o???o)=(?ω?? +"_")[c^_^o];(?Д?) [?o?]=""";(?Д?) ["_"] ( (?Д?) ["_"] (?ε?+(?Д?)[?o?]+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ ((???) + (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (???)+ (?Д?)[?ε?]+((???) + (?Θ?))+ (c^_^o)+ (?Д?)[?ε?]+(???)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ (?Θ?)+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ ((???) + (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ ((???) + (o^_^o))+ (?Д?)[?ε?]+((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(???)+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (?Θ?)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) - (?Θ?))+ (o^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (o^_^o)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (???)+ (?Д?)[?ε?]+(???)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+((???) + (?Θ?))+ (?Θ?)+ (?Д?)[?o?]) (?Θ?)) ("_");

這段代碼看起來很奇怪,不像是JavaScript代碼,但是實(shí)際上這段代碼是用一些看似表情的符號,聲明了一個16位的數(shù)組(用來表示16進(jìn)制位置),然后將code當(dāng)做字符串遍歷,把每個代碼符號通過string.charCodeAt取這個16位的數(shù)組下標(biāo),拼接成代碼。大概的意思就是把代碼當(dāng)做字符串,然后使用這些符號的拼接代替這一段代碼(可以看到代碼里有很多加號),最后,通過(new Function(code))("_")執(zhí)行。

仔細(xì)觀察上面這一段代碼,把代碼最后的("_")去掉,在運(yùn)行,你會直接看到源代碼,然后Function.constructor存在(?Д?)變量中,感興趣的同學(xué)可以自行查看。

除了aaencode,jjencode原理也是差不多,就不做解釋了,其他更霸氣的jsfuck,這些都是對代碼進(jìn)行加密的,這里就不詳細(xì)介紹了。

反調(diào)試

由于JavaScript自帶debugger語法,我們可以利用死循環(huán)性的debugger,當(dāng)頁面打開調(diào)試面板的時候,無限進(jìn)入調(diào)試狀態(tài)。

定時執(zhí)行

在代碼開始執(zhí)行的時候,使用setInterval定時觸發(fā)我們的反調(diào)試函數(shù)。

隨機(jī)執(zhí)行

在代碼生成階段,隨機(jī)在部分函數(shù)體中注入我們的反調(diào)試函數(shù),當(dāng)代碼執(zhí)行到特定邏輯的時候,如果調(diào)試面板在打開狀態(tài),則無限進(jìn)入調(diào)試狀態(tài)。

內(nèi)容監(jiān)測

由于我們的代碼可能已經(jīng)反調(diào)試了,攻擊者可以會將代碼拷貝到自己本地,然后修改,調(diào)試,執(zhí)行,這個時候就需要添加一些檢測進(jìn)行判定,如果不是正常的環(huán)境執(zhí)行,那讓代碼自行失敗。

代碼自檢

在代碼生成的時候,為函數(shù)生成一份Hash,在代碼執(zhí)行之前,通過函數(shù) toString 方法,檢測代碼是否被篡改

function module() {
    // 篡改校驗(yàn)
    if (Hash(module.toString()) != "JkYxnHlxHbqKowiuy") {
        // 代碼被篡改!
    }
}
環(huán)境自檢

檢查當(dāng)前腳本的執(zhí)行環(huán)境,例如當(dāng)前的URL是否在允許的白名單內(nèi)、當(dāng)前環(huán)境是否正常的瀏覽器。

如果為Nodejs環(huán)境,如果出現(xiàn)異常環(huán)境,甚至我們可以啟動木馬,長期跟蹤。

廢代碼注入

插入一些永遠(yuǎn)不會發(fā)生的代碼,讓攻擊者在分析代碼的時候被這些無用的廢代碼混淆視聽,增加閱讀難度。

廢邏輯注入

與廢代碼相對立的就是有用的代碼,這些有用的代碼代表著被執(zhí)行代碼的邏輯,這個時候我們可以收集這些邏輯,增加一段判定來決定執(zhí)行真邏輯還是假邏輯,如下:

(function(){
    if (true) {
        var foo = function () {
            console.log("abc");
        };
        var bar = function () {
            console.log("def");
        };
        var baz = function () {
            console.log("ghi");
        };
        var bark = function () {
            console.log("jkl");
        };
        var hawk = function () {
            console.log("mno");
        };
 
        foo();
        bar();
        baz();
        bark();
        hawk();
    }
})();

可以看到,所有的console.log都是我們的執(zhí)行邏輯,這個時候可以收集所有的console.log,然后制造假判定來執(zhí)行真邏輯代碼,收集邏輯注入后如下:

(function(){
    if (true) {
        var foo = function () {
            if ("aDas" === "aDas") {
                console.log("abc");
            } else {
                console.log("def");
            }
        };
        var bar = function () {
            if ("Mfoi" !== "daGs") {
                console.log("ghi");
            } else {
                console.log("def");
            }
        };
        var baz = function () {
            if ("yuHo" === "yuHo") {
                console.log("ghi");
            } else {
                console.log("abc");
            }
        };
        var bark = function () {
            if ("qu2o" === "qu2o") {
                console.log("jkl");
            } else {
                console.log("mno");
            }
        };
        var hawk = function () {
            if ("qCuo" !== "qcuo") {
                console.log("jkl");
            } else {
                console.log("mno");
            }
        };
 
        foo();
        bar();
        baz();
        bark();
        hawk();
    }
})();

判定邏輯中生成了一些字符串,在沒有使用字符串提取的情況下,這是可以通過代碼靜態(tài)分析來得到真實(shí)的執(zhí)行邏輯的,或者我們可以使用上文講到的動態(tài)執(zhí)行來決定執(zhí)行真邏輯,可以看一下使用字符串提取和變量名編碼后的效果,如下:

var _0x6f5a = [
    "abc",
    "def",
    "caela",
    "hmexe",
    "ghi",
    "aaeem",
    "maxex",
    "mno",
    "jkl",
    "ladel",
    "xchem",
    "axdci",
    "acaeh",
    "log"
];
(function (_0x22c909, _0x4b3429) {
    var _0x1d4bab = function (_0x2e4228) {
        while (--_0x2e4228) {
            _0x22c909["push"](_0x22c909["shift"]());
        }
    };
    _0x1d4bab(++_0x4b3429);
}(_0x6f5a, 0x13f));
var _0x2386 = function (_0x5db522, _0x143eaa) {
    _0x5db522 = _0x5db522 - 0x0;
    var _0x50b579 = _0x6f5a[_0x5db522];
    return _0x50b579;
};
(function () {
    if (!![]) {
        var _0x38d12d = function () {
            if (_0x2386("0x0") !== _0x2386("0x1")) {
                console[_0x2386("0x2")](_0x2386("0x3"));
            } else {
                console[_0x2386("0x2")](_0x2386("0x4"));
            }
        };
        var _0x128337 = function () {
            if (_0x2386("0x5") !== _0x2386("0x6")) {
                console[_0x2386("0x2")](_0x2386("0x4"));
            } else {
                console[_0x2386("0x2")](_0x2386("0x7"));
            }
        };
        var _0x55d92e = function () {
            if (_0x2386("0x8") !== _0x2386("0x8")) {
                console[_0x2386("0x2")](_0x2386("0x3"));
            } else {
                console[_0x2386("0x2")](_0x2386("0x7"));
            }
        };
        var _0x3402dc = function () {
            if (_0x2386("0x9") !== _0x2386("0x9")) {
                console[_0x2386("0x2")](_0x2386("0xa"));
            } else {
                console[_0x2386("0x2")](_0x2386("0xb"));
            }
        };
        var _0x28cfaa = function () {
            if (_0x2386("0xc") === _0x2386("0xd")) {
                console[_0x2386("0x2")](_0x2386("0xb"));
            } else {
                console[_0x2386("0x2")](_0x2386("0xa"));
            }
        };
        _0x38d12d();
        _0x128337();
        _0x55d92e();
        _0x3402dc();
        _0x28cfaa();
    }
}());
求值陷阱

除了注入執(zhí)行邏輯以外,還可以埋入一個隱蔽的陷阱,在一個永不到達(dá)無法靜態(tài)分析的分支里,引用該函數(shù),正常用戶不會執(zhí)行,而 AST 遍歷求值時,則會觸發(fā)陷阱!陷阱能干啥呢?

日志上報(bào),及時了解情況

在本地存儲隱寫特征,長期跟蹤

釋放CSRF漏洞,獲得破解者的詳細(xì)信息

開啟自殺程序(頁面崩潰、死循環(huán)、耗盡內(nèi)存等)

加殼干擾

在代碼用eval包裹,然后對eval參數(shù)進(jìn)行加密,并埋下陷阱,在解碼時插入無用代碼,干擾顯示,大量換行、注釋、字符串等大量特殊字符,導(dǎo)致顯示卡頓。

結(jié)束

大概我想到的混淆就包括這些,單個特性使用的話,混淆效果一般,各個特性組合起來用的話,最終效果很明顯,當(dāng)然這個看個人需求,畢竟混淆是個雙刃劍,在增加了閱讀難度的同時,也增大了腳本的體積,降低了代碼的運(yùn)行效率。

參考文獻(xiàn)

代碼混淆之道——控制流扁平與不透明謂詞理論篇

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/104545.html

相關(guān)文章

  • Android 應(yīng)用防止被二次打包指南

    摘要:接下來,我就來詳解一下如何防止被二次打包。開發(fā)階段移動應(yīng)用開發(fā)時接入安全組件,保護(hù)數(shù)據(jù)安全。 前言 Android APP二次打包則是盜版正規(guī)Android APP,破解后植入惡意代碼重新打包。不管從性能、用戶體驗(yàn)、外觀它都跟正規(guī)APP一模一樣但是背后它確悄悄運(yùn)行著可怕的程序,它會在不知不覺中浪費(fèi)手機(jī)電量、流量,惡意扣費(fèi)、偷窺隱私等等行為。 二次打包問題只是Android應(yīng)用安全風(fēng)險(xiǎn)中...

    PAMPANG 評論0 收藏0
  • Android 開發(fā)怎樣做代碼加密或混淆

    摘要:網(wǎng)易資深安全工程師鐘亞平在今年的安卓巴士全球開發(fā)者論壇上做了安卓逆向與保護(hù)的演講完整演講內(nèi)容請見這里一文了解安卓逆向分析與保護(hù)機(jī)制,其中就談到了關(guān)于代碼混淆的問題。就是一個混淆代碼的開源項(xiàng)目,能夠?qū)ψ止?jié)碼進(jìn)行混淆縮減體積優(yōu)化等處理。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)。 在大公司怎么做android代碼混淆的?發(fā)現(xiàn)他們的軟件用apktool反編譯居然沒看到classes....

    incredible 評論0 收藏0
  • Android防護(hù)掃盲篇

    摘要:為了防止這種現(xiàn)象,我們可以對字節(jié)碼進(jìn)行混淆。動態(tài)鏈接庫是目標(biāo)文件的集合,目標(biāo)文件在動態(tài)鏈接庫中的組織方式是按照特殊方式形成的。 一、已知防護(hù)策略 1.不可或缺的混淆 Java 是一種跨平臺、解釋型語言,Java 源代碼編譯成的class文件中有大量包含語義的變量名、方法名的信息,很容易被反編譯為Java 源代碼。為了防止這種現(xiàn)象,我們可以對Java字節(jié)碼進(jìn)行混淆。混淆不僅能將代碼中的類...

    CastlePeaK 評論0 收藏0

發(fā)表評論

0條評論

gaara

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<