前文
因为目前市面上资料是较少的...
最近突然对js逆向有了一定兴趣
碰到涛也在油中
于是经过一段不可告人的事情后
打入了内部学习了一些奇奇怪怪的大人的知识
写下了这篇入门文章
可能存在事实性错误
可以在评论区支出
开始
因为https://www.jsjiami.com/生成的代码不好使
所以我换了一个
https://www.sojson.com/jsobfuscator.html
加密的代码也比较简单
let a=1;
alert(a);
最基础的配置我们研究一些东西
生成的代码为
/*
* 加密工具已经升级了一个版本,目前为 jsjiami.com.v5 ,主要加强了算法,以及防破解【绝对不可逆】配置,耶稣也无法100%还原,我说的。;
* 已经打算把这个工具基础功能一直免费下去。还希望支持我。
* 另外 jsjiami.com.v5 已经强制加入校验,注释可以去掉,但是 jsjiami.com.v5 不能去掉(如果你开通了VIP,可以手动去掉),其他都没有任何绑定。
* 誓死不会加入任何后门,jsjiami.com JS 加密的使命就是为了保护你们的Javascript 。
* 警告:如果您恶意去掉 jsjiami.com.v5 那么我们将不会保护您的JavaScript代码。请遵守规则
* 新版本: https://www.jsjiami.com/ 支持批量加密,支持大文件加密,拥有更多加密。 */
;var encode_version = 'jsjiami.com.v5', uumto = '__0xecbce', __0xecbce=['w7Q+w6jDqcKnMMOewpgF','TsOTIcKVw4IjwpsGc2NVQR/CtQ==','5YiH6ZmZ54uo5pyg5YyF772HfcOr5L+Z5a6R5p+y5byO56ms','w4I7Ohwo','dXkZw4kL','wrnClsKNIsKX','54if5p6c5Y6v772NCGDkv7rlr6zmnYXlvqPnq4nvvaPov4Hor6Xmla3mjIXmi6jkuaTnm7Dlt4zkv4o=','wpk8WMOuQA==','wqojw6I='];(function(_0x4a174f,_0x2b3ed7){var _0x51adc6=function(_0x4c4f72){while(--_0x4c4f72){_0x4a174f['push'](_0x4a174f['shift']());}};_0x51adc6(++_0x2b3ed7);}(__0xecbce,0x155));var _0x43f9=function(_0x15b28a,_0x370d4f){_0x15b28a=_0x15b28a-0x0;var _0x958f5c=__0xecbce[_0x15b28a];if(_0x43f9['initialized']===undefined){(function(){var _0x375bef=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x36add6='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x375bef['atob']||(_0x375bef['atob']=function(_0x2b8d70){var _0x786ab7=String(_0x2b8d70)['replace'](/=+$/,'');for(var _0x2efd19=0x0,_0x5032a4,_0x1a3fe4,_0x5cb9a4=0x0,_0x3d9d3c='';_0x1a3fe4=_0x786ab7['charAt'](_0x5cb9a4++);~_0x1a3fe4&&(_0x5032a4=_0x2efd19%0x4?_0x5032a4*0x40+_0x1a3fe4:_0x1a3fe4,_0x2efd19++%0x4)?_0x3d9d3c+=String['fromCharCode'](0xff&_0x5032a4>>(-0x2*_0x2efd19&0x6)):0x0){_0x1a3fe4=_0x36add6['indexOf'](_0x1a3fe4);}return _0x3d9d3c;});}());var _0x4d9f1d=function(_0x11262d,_0x148d0f){var _0x31b35b=[],_0x2d6c29=0x0,_0x24b4f5,_0x196a93='',_0x56258a='';_0x11262d=atob(_0x11262d);for(var _0x3d7663=0x0,_0x34f9e9=_0x11262d['length'];_0x3d7663<_0x34f9e9;_0x3d7663++){_0x56258a+='%'+('00'+_0x11262d['charCodeAt'](_0x3d7663)['toString'](0x10))['slice'](-0x2);}_0x11262d=decodeURIComponent(_0x56258a);for(var _0x48101c=0x0;_0x48101c<0x100;_0x48101c++){_0x31b35b[_0x48101c]=_0x48101c;}for(_0x48101c=0x0;_0x48101c<0x100;_0x48101c++){_0x2d6c29=(_0x2d6c29+_0x31b35b[_0x48101c]+_0x148d0f['charCodeAt'](_0x48101c%_0x148d0f['length']))%0x100;_0x24b4f5=_0x31b35b[_0x48101c];_0x31b35b[_0x48101c]=_0x31b35b[_0x2d6c29];_0x31b35b[_0x2d6c29]=_0x24b4f5;}_0x48101c=0x0;_0x2d6c29=0x0;for(var _0x206f10=0x0;_0x206f10<_0x11262d['length'];_0x206f10++){_0x48101c=(_0x48101c+0x1)%0x100;_0x2d6c29=(_0x2d6c29+_0x31b35b[_0x48101c])%0x100;_0x24b4f5=_0x31b35b[_0x48101c];_0x31b35b[_0x48101c]=_0x31b35b[_0x2d6c29];_0x31b35b[_0x2d6c29]=_0x24b4f5;_0x196a93+=String['fromCharCode'](_0x11262d['charCodeAt'](_0x206f10)^_0x31b35b[(_0x31b35b[_0x48101c]+_0x31b35b[_0x2d6c29])%0x100]);}return _0x196a93;};_0x43f9['rc4']=_0x4d9f1d;_0x43f9['data']={};_0x43f9['initialized']=!![];}var _0x106a87=_0x43f9['data'][_0x15b28a];if(_0x106a87===undefined){if(_0x43f9['once']===undefined){_0x43f9['once']=!![];}_0x958f5c=_0x43f9['rc4'](_0x958f5c,_0x370d4f);_0x43f9['data'][_0x15b28a]=_0x958f5c;}else{_0x958f5c=_0x106a87;}return _0x958f5c;};let a=0x1;alert(a);;(function(_0xc2361a,_0x49f6b2,_0x4c5d49){var _0x4bbdd6={'PTyWI':_0x43f9('0x0','SRfb'),'CFOau':function _0x2e9886(_0x27d2c4,_0x233ed3){return _0x27d2c4!==_0x233ed3;},'yGZoO':_0x43f9('0x1','(WPz'),'UQhqT':function _0xe650a3(_0x4590a1,_0x160226){return _0x4590a1===_0x160226;},'TtTMq':_0x43f9('0x2','yz7r'),'FQggo':function _0x47c22c(_0x2fe61e,_0x50381a){return _0x2fe61e+_0x50381a;},'FTCAn':_0x43f9('0x3','D!uM')};_0x4c5d49='al';try{_0x4c5d49+=_0x4bbdd6['PTyWI'];_0x49f6b2=encode_version;if(!(_0x4bbdd6['CFOau'](typeof _0x49f6b2,_0x4bbdd6[_0x43f9('0x4','C[1$')])&&_0x4bbdd6[_0x43f9('0x5','0IU[')](_0x49f6b2,_0x4bbdd6[_0x43f9('0x6','tMJO')]))){_0xc2361a[_0x4c5d49](_0x4bbdd6['FQggo']('删除',_0x43f9('0x7','27(^')));}}catch(_0x2d647c){_0xc2361a[_0x4c5d49](_0x4bbdd6[_0x43f9('0x8','#zxt')]);}}(window));;encode_version = 'jsjiami.com.v5';
我们格式化一下,跑一下发现可以正常运行
证明没有进行格式化攻击
先看第一段
var encode_version = "jsjiami.com.v5",
uumto = "__0xecbce",
__0xecbce = [
"w7Q+w6jDqcKnMMOewpgF",
"TsOTIcKVw4IjwpsGc2NVQR/CtQ==",
"5YiH6ZmZ54uo5pyg5YyF772HfcOr5L+Z5a6R5p+y5byO56ms",
"w4I7Ohwo",
"dXkZw4kL",
"wrnClsKNIsKX",
"54if5p6c5Y6v772NCGDkv7rlr6zmnYXlvqPnq4nvvaPov4Hor6Xmla3mjIXmi6jkuaTnm7Dlt4zkv4o=",
"wpk8WMOuQA==",
"wqojw6I=",
];
var encode_version = "jsjiami.com.v5",
声明了网站加密标识,禁止删除
uumto暂时不知道
__0xecbce 是对字符串加密形成的数组,把代码里的字符串全部提到数组里了
我们称之为【数组混淆】
(function (_0x4a174f, _0x2b3ed7) {
var _0x51adc6 = function (_0x4c4f72) {
while (--_0x4c4f72) {
_0x4a174f["push"](_0x4a174f["shift"]());
}
};
_0x51adc6(++_0x2b3ed7);
})(__0xecbce, 0x155);
这里是一个数组乱序混淆,因为数组混淆很容易被抓到规律
所以在 创建后,进行一个乱序,我们称之为【乱序混淆】
我们可以调试看一下
这是没执行的时候
这是执行一次的时候
可以看到就是将第一项放到最后一位,重复++0x155次,也就是342次
当执行到342次后
打乱成了这样
然后声明了一个_0x43f9的函数
执行到了a=1,alert...加密个鬼啦!
接下来走到了自执行代码
我大概贴一下,我们继续往后分析
(function (_0xc2361a, _0x49f6b2, _0x4c5d49) {
var _0x4bbdd6 = {
PTyWI: _0x43f9("0x0", "SRfb"),
CFOau: function _0x2e9886(_0x27d2c4, _0x233ed3) {
return _0x27d2c4 !== _0x233ed3;
},
yGZoO: _0x43f9("0x1", "(WPz"),
UQhqT: function _0xe650a3(_0x4590a1, _0x160226) {
return _0x4590a1 === _0x160226;
},
TtTMq: _0x43f9("0x2", "yz7r"),
FQggo: function _0x47c22c(_0x2fe61e, _0x50381a) {
return _0x2fe61e + _0x50381a;
},
FTCAn: _0x43f9("0x3", "D!uM"),
};
_0x4c5d49 = "al";
try {
_0x4c5d49 += _0x4bbdd6["PTyWI"];
_0x49f6b2 = encode_version;
if (
!(
_0x4bbdd6["CFOau"](
typeof _0x49f6b2,
_0x4bbdd6[_0x43f9("0x4", "C[1$")]
) &&
_0x4bbdd6[_0x43f9("0x5", "0IU[")](
_0x49f6b2,
_0x4bbdd6[_0x43f9("0x6", "tMJO")]
)
)
) {
_0xc2361a[_0x4c5d49](_0x4bbdd6["FQggo"]("删除", _0x43f9("0x7", "27(^")));
}
} catch (_0x2d647c) {
_0xc2361a[_0x4c5d49](_0x4bbdd6[_0x43f9("0x8", "#zxt")]);
}
})(window);
有三个变量,但是实际只传入了一个变量
另外两个很有可能是在源代码叫var a=1之类的
在混淆之后变量提升到顶部的入参,来混淆视线,我们称之为【变量提升混淆】
然后这里声明了一个对象,并且调用了_0x43f9,证明了0x43f9是一个解密函数
我们跟进去看看
传入了两个参数
首先将字符串-0,形成数字
var _0x958f5c = __0xecbce[_0x15b28a];
然后找到对应的字符串
判断这个函数有没有初始化过,我们第一次运行很显然没有
_0x43f9["initialized"] === undefined
所以直接执行一段自执行函数,代码我们上面贴了,我就不重复了
获取对应的window值(浏览器情况下)
var _0x375bef =
typeof window !== "undefined"
? window
: typeof process === "object" &&
typeof require === "function" &&
typeof global === "object"
? global
: this;
然后对window的atob进行了劫持
_0x375bef["atob"] ||
(_0x375bef["atob"] = function (_0x2b8d70)
又声明了一个_0x4d9f1d 函数,干啥不知道
_0x43f9["rc4"] = _0x4d9f1d;将上面那个函数赋值给解密函数,叫rc4,应该也是个什么解密
_0x43f9["data"] = {};应该是一个数字缓存
_0x43f9["initialized"] = !![];表示初始化成功
var _0x4d9f1d = function (_0x11262d, _0x148d0f)
_0x43f9["rc4"] = _0x4d9f1d;
_0x43f9["data"] = {};
_0x43f9["initialized"] = !![];
判断是否命中缓存,我们这里肯定没有命中
没有命中就判断once是否执行过一次了,没执行过就设置once为真
if (_0x106a87 === undefined) {
if (_0x43f9["once"] === undefined) {
_0x43f9["once"] = !![];
}
_0x958f5c = _0x43f9["rc4"](_0x958f5c, _0x370d4f);
_0x43f9["data"][_0x15b28a] = _0x958f5c;
} else {
_0x958f5c = _0x106a87;
}
设置后传入
_0x958f5c = _0x43f9["rc4"](_0x958f5c, _0x370d4f);
传入我们数组混淆里的内容,以及一个最初传入的内容
结语
下篇继续...太长了