js混淆有两种:
•变量•代码执行流程混淆代码的执行流程一般通过控制流混淆来实现,下面主要介绍一下常见的变量混淆方式。
基本混淆方法
将值放到新的变量中,再通过 window 来取:
也可以结合 base64 编码,即(btoa,atob)
先通过 atob(ry4n3[0]),即 YWJj 的 base64decode,解码得到 abc,再用 window[abc]来获取变量 abc 的值——"test" 也可以利用 eval 方法,例如 eval("function xx(){return 12} xx()")
,结合上 base64:
如果是利用 eval 进行混淆,可以直接在 eval 处下断点,跟进虚拟机即可看到明文:
js 默认支持 unicode 编码,因此可以支持生僻语言等等,AA 加密和 JJ 加密就是利用了这一点。
AA 加密
AA 加密和 JJ 加密都可以通过 sojson 网站进行。
sojson:JS加密,JS 安全加密, AAencode 加密 —在线加密 (sojson.com)[1]
以 console.log(1)为例,加密后的代码如图所示,执行后成功打印出 1.
JJ 加密
JJ 加密与 AA 加密类似,都是利用 js 支持 unicode 编码,并且都是通过 eval+Function 的方式进行,下面尝试对 JJ 加密进行调试。
同样以 console.log(1)为例:
首先这里可以直接运行出值。 最后一行代码为:
sojson.$(sojson.$(sojson.$$ +"""+ sojson.$$__ + sojson._$ +"\"+ sojson.__$ + sojson.$_$ + sojson.$$_ +"\"+ sojson.__$ + sojson.$$_ + sojson._$$ + sojson._$ +(![]+"")[sojson._$_]+ sojson.$$$_ +"."+(![]+"")[sojson._$_]+ sojson._$ +"\"+ sojson.__$ + sojson.$__ + sojson.$$$ +"("+ sojson.__$ +")"+""")())(sojson ={
___:++sojson,
$$$$:(![]+"")[sojson]
});
这里执行了一个方法,肯定是在该方法运行之后,才完成了字符串的拼接以及整体代码的运行。
很明显这里是一个 Function,尝试改写 Function:
Function = function(){debugger;}这里加上一个 debugger,类似于 hook 的形式,打上断点并运行,但是没有断住。
看看上一行代码:
sojson 是一个 object,其实也就是 OBJECT[0].constructor.constructor,执行后就是 Function:
由于是直接从原型链取的,因此无法通过改写来 debug。
可以直接改写 sojson. $ ,(注意,先在 28 行打断点,执行,断住时,改写为 sojson.$=function(){debugger;}),此时能够直接进到虚拟机里,即 sojson.$ = function(){debugger;}
通过 arguments 打印出此时的所有参数,可以看到 "return"co156163ole.lo147(1)""
这段内容还是经过简单的加密处理的,直接通过控制台还原一下:
最终结果即为 console.log(1)
jsfuck
javascript 是一种灵活的动态语言,其允许使用多种语法结构和运算符来实现具体逻辑,并且允许进行各种类型的数据转换,jsfuck 就是利用了这些特性,结合位运算操作实现的一种加密方式。
还是以 console.log(1)为例,同样可以直接运行,因为他没有改变代码的语法和形式等等,只是进行了混淆操作:
jsfuck 混淆之后的代码要进行调试较为麻烦,可以通过下面的代码来实现快速解密:
Function.prototype.__defineGetter__('constructor',function(){
returnfunction(...args){
console.log('code:',...args);
returnFunction(...args);
};
});
这里定义了一个 getter 方法,该方法会在访问对象的 constructor 属性时被调用。在这个 getter 方法中,它重新定义了 constructor 属性,使得在访问 constructor 属性时,会执行一个自定义的函数。
该函数会接收传入的参数即...args ,然后打印出参数 args ,最后返回一个新的 Function 对象,该对象与原始的 Function 构造函数的行为相同。 JSFuck 加密后的代码执行时,通常会创建一个 Function 对象,然后对他进行调用。通过重定义 constructor 属性,并在访问时输出参数,我们可以获取到加密后的代码内容,并且还可以将其作为参数传递给新的 Function 对象,从而执行原始代码。
例如,对下面代码进行 jsfuck 混淆:
var test="123"
console.log(test)
可以看到很多 escape 和 location,最终跳到了原始的明文代码,并且输出了结果 123.
References
[1]
JS加密,JS 安全加密, AAencode 加密 —在线加密 (sojson.com): https://www.sojson.com/aaencode.html
原文始发于微信公众号(Crush Sec):js 逆向系列04-常见混淆原理
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论