JavaScript混淆加密
混淆之后的代码功能不变,但是在逆向的时候不是一定得还原代码,要是补环境之后能运行也可以,要是想知道业务逻辑怎么实现的,要去还原
十六进制与Unicode字符串
1 | Date.prototype.format = function(formatStr) { |
访问属性的方法,str['replace']
或者str.replace
,对于前者,字符串replace
是可以加密的
而且,这里Date()
是window的内置对象,所以new Date()
也就是new window.Date()
,或者new window['Date']()
十六进制字符串可以表示正常的字符串,比如'yyyy-MM-dd'
,十六进制字符串表示就是'\x79\x79\x79\x79\x2d\x4d\x4d\x2d\x64\x64'
也就是把字符转成ASCII码,然后再转成十六进制,y的ASCII码是121,也就是0x79
十六进制转换
1 | function hexEnc(code) { |
unicode编码和十六进制类似
1 | function unicodeEnc(str) { |
ASCII码混淆
字符转ASCII码,charCodeAt
方法
ASCII码还原字符串,String.fromCharCode(120)
,可以接受数组String.fromCharCode(120,105)
字符串转ASCII码
1 | function stringToByte(str) { |
那么str = str.replace(/MM/, (this.getMonth() + 1) > 9 ? (this.getMonth() + 1).toString() : '0' + (this.getMonth() + 1));
转换成ASCII码就是
1 | 115,116,114,32,61,32,115,116,114,46,114,101,112,108,97,99,101,40,47,77,77,47,44,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,32,62,32,57,32,63,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,46,116,111,83,116,114,105,110,103,40,41,32,58,32,39,48,39,32,43,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,41,59 |
但是这样是字符串,不能直接当成代码用,要用eval
去执行
也就是
1 | eval(String.fromCharCode(115,116,114,32,61,32,115,116,114,46,114,101,112,108,97,99,101,40,47,77,77,47,44,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,32,62,32,57,32,63,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,46,116,111,83,116,114,105,110,103,40,41,32,58,32,39,48,39,32,43,32,40,116,104,105,115,46,103,101,116,77,111,110,116,104,40,41,32,43,32,49,41,41,59)) |
字符串常量加密
不是所有的字符串常量都能加密
数值常量加密
算法的初始化常量进行加密,比如可以两个值异或得到需要的值
数组混淆和乱序
可以把需要的字符串和数值和函数都放到一个数组中,然后对数组进行加密
乱序,就是把数组的元素顺序打乱,在调用数组之前还原正常的数组元素顺序
花指令
花指令,就是混淆视听的没有意义的代码
函数可以无限套娃,越写越膨胀
JSFuck
就是用六个字符去表示js代码
有网站可以解密,如果网站解密不了,再去分步分析,分析的方法是按照括号为组去执行,看执行的结果,然后去把代码用解出来的明文结果替换
流程平坦化
一般的代码是从上往下执行,在上面的代码就是先执行
用条件语句可以让代码按索引去执行,case块的索引可以是字符也可以是数字,字符还可以放到数组中去
逗号表达式混淆
1 | function t(){ |
上面的代码最终返回的是f,逗号前面的代码会被执行,但是最终只返回f
同样,var a = ( a = 1000, a += 2000);
,最终a等于3000
逗号表达式里还能加一些垃圾代码,只计算不赋值的
函数调用可以加逗号表达式,不影响函数调用,比如
1 | (1 + 1 + 1 + 1 + 'thisisatest',sub)(a,b) |
同理,对象访问属性也可以用逗号表达式,如obj.name
,可以混淆成(bbb = (1 + 1 + 1 + 'test', obj)).name
eval加密
eval会把传入的字符串参数当成代码去运行,字符串可以加密,下面的function
是解密函数
1 | eval(function (p, a, c, k, e, r) { |
可以直接把这里eval
改成console.log
去输出就得到解密之后的代码
格式化检测
代码格式化检测是一种防止代码被格式化或美化的技术。
许多网站的加密/反爬/反调试代码会使用混淆、压缩让代码变得难以阅读,而开发者在调试时可能会使用格式化工具让代码变得易读。
网站可以通过检测代码是否被格式化来识别调试行为,并进行反调试或反分析。
JavaScript 的 Function.prototype.toString()
方法会返回函数的源码
如果代码被格式化,返回的字符串会有换行、空格增加,可以通过计算字符串长度发现代码是否被格式化。
1 | (function () { |
isFormatted.toString()
返回 isFormatted
函数的源码,如果源码的长度超过100(说明代码有换行或空格被美化了),就判定代码被格式化,并进行反调试(死循环等)。
Function混淆
1 | function test(a,b) { |