MENU

某JS加密逆向还原简单分析

September 15, 2020 • Read: 8584 • Code,教程

加密前源码

var a={},b={}; 

(function(w, d) { 

 w.info = "这是一个一系列js操作。"; 

 d.adinfo = "站长接高级 “JS加密” 和 “JS解密” ,保卫你的 js。"; 

 d.warning = "如果您的JS里嵌套了PHP,JSP标签,等等其他非JavaScript的代码,请提取出来再加密。这个工具不能加密php、jsp等模版内容"; 

 d.intro = "本工具由 www.jsjiami.com 提供接口。"; 

加密后源码

/*
 * 加密工具已经升级了一个版本,目前为 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', silni = '',  _0x20f1=['5aeP5p2T5oCq55mrwr0Z6YSM5baA5aaX5Lmbw4ANwqXvv5Iuwpkh5qKK56+Y77yQ566756+65YS45LmV6Z2bYDrDssK0c8ORbcOifEbnmKTkuJXnoKPvvrzor6DmjJrljpblhITmnJ/lhoLliIvlrprjg5Tovrvku5fltJ3lh7TkuqjogJLliYzlrZHDmTLCm+ODq1TChjrnrZTmq5nniYblhp3lrYE=','KMKoT8K7','w5nCnjrCoMO6','w67DkRnChXc=','AC1Gw4pYHEQ=','F8KyU8KCHQ==','woxicMOWw4I=','w6XDgcKZw6Mh','HEEw','CMO1CzbClMKHQQ5Zw7nCnwc0wqA=','wqUWNQ==','I1XDuA==','56iA6ZSt5o2m6amz57qsOuKCkMOZUuWKiuWtjuKBssKW5ZCAwp/ig6U8wq3op6jlrozigLHCpe+8puS8veWOl+S8gOebicKuasOw44Kn','5aWn5p6Q5oKs55igw6cC6Ye15bWn5aSl5LmqEcKcwrDvva0WQFTmo7bnr7fvvbrnr4jnroTlha3kuZDpnrDCoMKod8KdRGs8w4rCu8Of55qN5LmI56CU772Y6K2x5o+K5Yyn5YSM5p2G5Yay5Yqq5a2f44OD6L6O5Lqm5bay5Yad5Lui6IKs5Yqo5ay0w53ClVrjgIsfw6kU56+s5qua54mK5YSB5a2L','LsKHw6fCosKA','ch90wo9nwr57woUs','AsKRw4g9Dw==','w5/DlnnDizM=','wobCsFXDv8KE','54q85p+H5Y+477yAIcKC5L6l5ayg5p2j5by756qy772M6LyV6K6i5pea5o6O5oqJ5Luo55qx5bWS5L6a','PQd6LQ==','ZhV5woRnwrg=','w73ClUrDqcKx','w7jDpznCmlzDscOt','w5UXXsKzw7U=','JQhZwq3DgA==','56mt6Zei5o226amL57uybeKDmmh75Yqq5a2k4oOwY+WQvWHig5jCgsKm6KaU5a6c4oG8w73vv4vkvpnljr/kvarnmrI2w4Yh44G9'];(function(_0x273a54,_0x5628d8){var _0x542da4=function(_0x14d3ca){while(--_0x14d3ca){_0x273a54['push'](_0x273a54['shift']());}};_0x542da4(++_0x5628d8);}(_0x20f1,0xa1));var _0xd671=function(_0x1e0d70,_0x16dbe4){_0x1e0d70=_0x1e0d70-0x0;var _0x38dc25=_0x20f1[_0x1e0d70];if(_0xd671['initialized']===undefined){(function(){var _0xd2dbbd=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x251e01='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0xd2dbbd['atob']||(_0xd2dbbd['atob']=function(_0x21c814){var _0x24f5d5=String(_0x21c814)['replace'](/=+$/,'');for(var _0x34984d=0x0,_0x232c4d,_0x3a854e,_0x54d8d0=0x0,_0x2c3883='';_0x3a854e=_0x24f5d5['charAt'](_0x54d8d0++);~_0x3a854e&&(_0x232c4d=_0x34984d%0x4?_0x232c4d*0x40+_0x3a854e:_0x3a854e,_0x34984d++%0x4)?_0x2c3883+=String['fromCharCode'](0xff&_0x232c4d>>(-0x2*_0x34984d&0x6)):0x0){_0x3a854e=_0x251e01['indexOf'](_0x3a854e);}return _0x2c3883;});}());var _0x3aebff=function(_0xcdbb0c,_0x1decee){var _0x2b353f=[],_0x4851bb=0x0,_0x3ac2e1,_0x193195='',_0x481096='';_0xcdbb0c=atob(_0xcdbb0c);for(var _0x46a9c8=0x0,_0x1aafad=_0xcdbb0c['length'];_0x46a9c8<_0x1aafad;_0x46a9c8++){_0x481096+='%'+('00'+_0xcdbb0c['charCodeAt'](_0x46a9c8)['toString'](0x10))['slice'](-0x2);}_0xcdbb0c=decodeURIComponent(_0x481096);for(var _0x5a580a=0x0;_0x5a580a<0x100;_0x5a580a++){_0x2b353f[_0x5a580a]=_0x5a580a;}for(_0x5a580a=0x0;_0x5a580a<0x100;_0x5a580a++){_0x4851bb=(_0x4851bb+_0x2b353f[_0x5a580a]+_0x1decee['charCodeAt'](_0x5a580a%_0x1decee['length']))%0x100;_0x3ac2e1=_0x2b353f[_0x5a580a];_0x2b353f[_0x5a580a]=_0x2b353f[_0x4851bb];_0x2b353f[_0x4851bb]=_0x3ac2e1;}_0x5a580a=0x0;_0x4851bb=0x0;for(var _0x274b49=0x0;_0x274b49<_0xcdbb0c['length'];_0x274b49++){_0x5a580a=(_0x5a580a+0x1)%0x100;_0x4851bb=(_0x4851bb+_0x2b353f[_0x5a580a])%0x100;_0x3ac2e1=_0x2b353f[_0x5a580a];_0x2b353f[_0x5a580a]=_0x2b353f[_0x4851bb];_0x2b353f[_0x4851bb]=_0x3ac2e1;_0x193195+=String['fromCharCode'](_0xcdbb0c['charCodeAt'](_0x274b49)^_0x2b353f[(_0x2b353f[_0x5a580a]+_0x2b353f[_0x4851bb])%0x100]);}return _0x193195;};_0xd671['rc4']=_0x3aebff;_0xd671['data']={};_0xd671['initialized']=!![];}var _0x2863fa=_0xd671['data'][_0x1e0d70];if(_0x2863fa===undefined){if(_0xd671['once']===undefined){_0xd671['once']=!![];}_0x38dc25=_0xd671['rc4'](_0x38dc25,_0x16dbe4);_0xd671['data'][_0x1e0d70]=_0x38dc25;}else{_0x38dc25=_0x2863fa;}return _0x38dc25;};var a={},b={};(function(_0x13396a,_0x398dc6){var _0x1f8b1d={'EvoNd':'这是一个一系列js操作。','aWRqB':_0xd671('0x0','L(!['),'VtzVO':_0xd671('0x1','^iJ['),'RHwpZ':'本工具由\x20www.jsjiami.com\x20提供接口。'};_0x13396a[_0xd671('0x2','C4o#')]=_0x1f8b1d[_0xd671('0x3','0W]!')];_0x398dc6['adinfo']=_0x1f8b1d[_0xd671('0x4','$#vZ')];_0x398dc6[_0xd671('0x5','Jea^')]=_0x1f8b1d[_0xd671('0x6','C4o#')];_0x398dc6[_0xd671('0x7',[email protected]')]=_0x1f8b1d[_0xd671('0x8','fHUP')];}(a,b));;(function(_0x5d37d2,_0x978629,_0x3bdc6b){var _0x4c95c9={'oPPdo':_0xd671('0x9','9Leb'),'cHeMw':function _0xd3acad(_0x36d993,_0x2288a0){return _0x36d993!==_0x2288a0;},'jHrrU':function _0x124de9(_0x339e10,_0x365e71){return _0x339e10===_0x365e71;},'TPiKn':_0xd671('0xa','BW$%'),'HcuYX':function _0x1325c2(_0x4380c0,_0x13bd29){return _0x4380c0!==_0x13bd29;},'yoBrk':_0xd671('0xb','Jo2m'),'FprmZ':_0xd671('0xc','WJmd'),'DucYL':function _0x3b92b7(_0x3f97e9,_0x48a6ed){return _0x3f97e9+_0x48a6ed;},'CIDrA':'这是一个一系列js操作。','SuaWD':_0xd671('0xd','RzU^'),'gISKs':_0xd671('0xe',[email protected]'),'lfYwj':'删除版本号,js会定期弹窗'};_0x3bdc6b='al';try{_0x3bdc6b+=_0x4c95c9['oPPdo'];_0x978629=encode_version;if(!(_0x4c95c9[_0xd671('0xf','^iJ[')](typeof _0x978629,_0xd671('0x10','rTUP'))&&_0x4c95c9['jHrrU'](_0x978629,_0x4c95c9[_0xd671('0x11',[email protected]')]))){if(_0x4c95c9[_0xd671('0x12','fwyI')](_0x4c95c9['yoBrk'],_0x4c95c9['FprmZ'])){_0x5d37d2[_0x3bdc6b](_0x4c95c9[_0xd671('0x13','4Vgu')]('删除',_0xd671('0x14','a*3N')));}else{_0x5d37d2[_0xd671('0x15','*9!e')]=_0x4c95c9['CIDrA'];d[_0xd671('0x16','rTUP')]=_0x4c95c9[_0xd671('0x17','akCG')];d[_0xd671('0x18','$#vZ')]=_0x4c95c9['gISKs'];d[_0xd671('0x19','zX03')]='本工具由\x20www.jsjiami.com\x20提供接口。';}}}catch(_0x4cb95a){_0x5d37d2[_0x3bdc6b](_0x4c95c9[_0xd671('0x1a','I9uc')]);}}(window));;encode_version = 'jsjiami.com.v5';

逆向还原过程

解密第一步,先对代码简单梳理,便于阅读
https://tool.lu/js 在这里选择解密

经过分析,可以将代码分成三大段,第一大段为一个大数组,然后经过紧跟的一个立即执行函数,将这段数组进行一定方式的重新排列,如下图:
20200915164829.jpg

我们可以利用浏览器的控制台,并加一行代码,然后打印一下这个数组,检测一下
20200915165201.jpg

因此可以不用管它,能运行就行。接下来看第二大段,为一个解密函数,主要用于将一些诸如 _0xd671('0x0', 'L(![') 这种的,解密成关键字,这个解密函数类似如下:
20200915165356.jpg

最后的第三大段,即为被加密的主要函数。可以看到其中大量调用了解密函数,并且定义了一些关键字如 EvoNd 等,因此使代码混淆。那么我们调用解密函数,使之还原,就能让代码清晰一些了
20200915165631.jpg

主要思路:

用Python读取原来代码的js文件,然后正则匹配,凡是用到解密函数的地方,直接调用解密函数将其替换,最后重新写入一个新的js文件中。具体操作如下:
 先将第一、二大段修改后的代码,另外复制到一个新的js文件中,并构造一个change函数,函数如图所示:
20200915170154.jpg

然后用Python读取调用,将修改后的代码写入到src.js中。写法可以参照如下:

import re, execjs

def change(s):
    value = s.group('value')
    return ctx.call("change", value)

# decode.js 是第一、二段加构造一个change函数的代码
with open("decode.js", "r", encoding="utf-8") as fb:
    ctx = execjs.compile(fb.read())

# code.js是原代码
with open("code.js", "r") as f:
    word = f.read()

# 下面的_0xd671根据原来的代码进行修改
pattern = re.compile(r"(?P<value>_0xd671\('.*?', '.*?'\))", re.S)
word = re.sub(pattern, change, word)

with open("src.js", "w", encoding="utf-8") as f:
    f.write(word)
    print("替换成功")

代码运行环境 Python3.7.5

替换完成以后,第一、二大段一般就没用了,可以直接删除。替换后的核心代码,见下图。可以看到其中定义了一个对象,然后定义了几个关键字属性,下方又会调用该属性。
20200915171149.jpg
这时候读这段代码,已经没什么难度了,如果还想清晰点,可以继续替换,将那些关键字代表的属性替换就好了,如下
20200915171608.jpg

到处,代码这样已经全部还原完毕,至于变量名称,这些是不可能还原了的

Archives QR Code
QR Code for this page
Tipping QR Code