
简单的JS编码
更新: 2025/2/24 字数: 0 字 时长: 0 分钟
JS 编码就是将 JS 代码按照某种规律进行编码,编码后的 JS 完全不具备可读性,但是我们可以通过浏览器中的 Console
很简单的进行还原,也可以通过专门的网站进行还原。
JS_Fuck编码
简单介绍
JSFuck 编码:就是将正常的 JS 代码编码成的只有 !、[]、+
的字符串编码进行加密。
JS_Fuck 解码网站:http://codertab.com/JsUnFuck
![] = false(布尔false)
!+[] = true(布尔true)
!+[]+[] = 'true'(布尔true变为字符串'true')
!+[]+!+[] = 2(true用作运算时等于1)
[!+[]+!+[]] = [2](变成一个数组里只有2)
[!+[]+!+[]]+[!+[]+!+[]] = '22'(两个数组[2]相加等于字符串22)
!+[]+[][!+[]+!+[]] = 'u'(取字符串'true'下标为2的字符)
(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]] = 'alert(1)'
例如,下图中的代码就是JSFuck代码:
我们打开解码网站,将代码粘贴进去,解码后的结果为:false
编码后的代码放在控制台中执行,可能有如下四种情况:
- 控制台执行报错,且非
unsafe
错误:点击报错信息即可还原代码; - 控制台执行不报错,删除一些语法(以括号为主),强制令其报错;
- 控制台报
unsafe
错误:自己写个 html 运行,然后删除语法令其报错即可还原; - 仅仅混淆部分数字的情况,一般情况下,上面的说法就失效了,只能一段一段的敲入
console
中或者采取网上一键解混淆。
题目实践
题目难度:非常简单
访问题目获取题目信息,并找到数据来源接口:
向后翻了 2 页,发现请求中的 POST 参数每次都会发生变化,其中 page
参数是页码,uc
参数是加密参数 :
选择 Initiator
选项卡,点击请求回调栈中的 call
跳转到发送该请求的位置:
跳转后,发现了想要的参数信息。从图中可以看到 window.a
是一个需要传参的函数,但在下面的 POST 传递的参数中 window.a
是一个加密字符串,说明该变量在代码过程当中被重新赋值了,而中间代码就只剩下 [](![]+[])...
这段了,根据内容判断该段代码是经过JS_Fuck编码后的代码:
我们将这段代码拷贝下来,在Console栏中运行,发现报错了,并提示了错误位置:
我们点击错误位置,追进去后就是还原后的 JS 代码了。发现 window.a
被重新赋值了:
aaencode编码
简单介绍
aaencode 编码:将正常的 JS 代码编码为好玩的特殊网络表情符号,如: ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚)
这样的表情文字。
aaencode 解码网站:https://www.qtool.net/decode
我们打开解码网站,将 aaencode 代码代码粘贴进去,解码后的结果为:window.o = 1;
题目实践
题目难度:非常简单
访问题目,一来就首先遇到 debugger,我们在左边侧栏右键选择 Never pause here
永远不停留这里:
注意外面定时器 setInterval(function(){}
和里面 debugger 都要打上断点,在右侧 Breakpoint 显示有两个断点,效果如下:
理解题目要求,找到数据接口:
往后翻动两页,观察请求头,发现每次请求 safe
参数都会有所变化:
选择 Initiator
选项卡,点击请求回调栈中的 call
跳转到发送该请求的位置:
跳转后,发现了想要的参数信息。在我们打断点的位置上面两行,有一个 request.setRequestHeader
设置请求头的操作,参数名称是 safe
,值是 token
,但我们全局搜索发现整个页面 token
只有一个,那么很有可能 token
产生于中间那一串表情字符的 aaencode 代码当中了:
为了验证我们猜想,在 201 行、202 行打上断点,并在控制台分别打印 token 的值,发现两次打印 token 的值都不一样,说明 aaencode 代码对 token 进行了赋值操作:
我们将这段代码拷贝下来,在 Console 栏中运行并没有报错,返回了一个undefined,说明代码是很可能是一个没有设置返回值的自执行函数:
在上图中末尾有一个独立的 ('_')
符号,我们删掉它再次打印,就会发现函数的内容:
双击输出的函数内容就会跳转到一个临时的 VM 文件里面,其内容就是完整的函数内容,逻辑也很简单就是围绕 a
这个有关时间戳的变量进行编码加密,我们在不熟悉的方法前面打上断点,继续运行:
所有不熟悉的方法都指向了 mian.js
这个文件:
进入这个 mian.js
文件,发现内容也是被 ob 混淆了的,但无论怎么混淆,它终究是可以运行的:
接下来,就是将 VM 文件里面的函数内容和被混淆的 mian.js
内容结合起来,最后生成 token
并返回就可以了。首先我们写一个函数,将 VM 文件内容粘贴过来,将 mian.js
未格式化的内容(这里是为了防止JS代码进行格式化检测)粘贴过来并注释掉,再一层层解封 mian.js
文件中的方法:
[!ATTENTION]
本题中 JS 代码使用的
iil
变量包含不常见字符,会在 Python脚本中调用会引发报错,最好换一个名称。
jjencode编码
简单介绍
jjencode 编码:就是将正常的 JS 代码编码成形如 [$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$
这样符号的字符串。
jjencode 解码网站:https://www.qtool.net/decode
jjencode解码流程和aaencode解码流程没有什么差别,例举内容如下:
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"('\\"+$.__$+$.$_$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+"\\"+$.$__+$.___+"\\"+$.__$+$.$_$+$._$_+"\\"+$.__$+$.$$_+$._$$+"\\"+$.__$+$.$_$+$._$_+"\\"+$.__$+$.$_$+$.__$+$.$_$_+"\\"+$.__$+$.$_$+$.$_$+"\\"+$.__$+$.$_$+$.__$+"."+$.$$__+$._$+"\\"+$.__$+$.$_$+$.$_$+"')\\"+$.__$+$._$_+"\\"+$.__$+$.__$+"\\"+$.__$+$.__$+"\\"+$.__$+$.__$+"\"")());
上面的内容放到浏览器中执行就是如下内容:
ƒ anonymous() {
alert('hello jsjiami.com')
}
题目实践
难度:中等
访问网址获取任务,在 Network 里面的 Fetch/XHR 选项中定位到了该网页数据的来源请求:
观察响应结果可以发现,返回的数值当中只有三等奖金的数值,先不着急,点击 Initiator 中 request 进行跳转:
跳转成功,代码格式化后,我们重点关注 success,前面讲过 success 代表着请求成功响应的结果:
将代码向后拉,可以看到 value 被多次使用,返回的值就是 value 的倍数,结合网页中显示的数值对比代码,可以发现如下规律:
**题目要求是计算一、二、三等奖之和,按照对应关系就是三等奖数值的24倍,及等于总销售额数值。**知道了数值的规律,接下来就是要分析请求了。经过多次请求发现请求头 headers 并未发生变化,而是 URL 的参数在不断变化:得出初步接结论,本题的加密重点为URL的请求参数:未知参数 m
和未知参数 q
。
和上面一样,回到请求的 Initiator 中,点击 request 进行跳转,未知参数 m
和未知参数 q
的组成一目了然:
window.i:初始为空字符串
t:时间戳
page:页码
m:未知函数r(t, window.o)
q:(window.i:初始为空字符串)每次请求加等window.o + '-' + t + "|"
window.o:每次请求加1
**现在的未知参数就变成了未知函数 r
和 window.o
的初始值了。**在 r
函数处打上断点,发现指向的是另一个文件:
点击 r
函数进行跳转,格式化后代码如下:
**发现在这个文件当中也使用到了 window.o
,而且当 window.o
的值大于等于6时,页面不会再发送 Ajax 请求,而是重新加载页面,当前我们最关心的就是最后一行 return z(param1, param2);
所返回的结果。**我们将所有的代码拷贝下来,格式化,发现里面有两处经过编码后的js代码:
我们将第一处aaencode代码,放入解密网站当中,点击aaencode解密,结果如下:
**这一下,就解决了 window.o
的初始值。通过整体的分析来看, window.o
就是一个翻页累加器,当前文件中就只有一处使用到了,就是上面的小于等于 6 那里,其目的就是控制翻页数的增加导致请求的 URL 参数越来越长,作用不大可以直接删除。**接下来,将第二处的 JSFuck 代码放入网站解密,其结果就是一个 false:
代码解码替换后,接下就是补环境,开始补环境前,我们再回顾以下 Node 环境和浏览器环境的差异:
因为在 Node 环境中没有 BOM,所以浏览器环境的全局对象 window
是用不了的,因此这里我们就必须使用 Node 环境的全局对象 global
,它类似于浏览器环境中的 window
对象。但这里有一个问题就是,从浏览器中抠出来的 JS 代码的凡是使用全局对象的都是 window
,没有 global
。其实这个问题很简单,只要在 JS 代码最前面加上一句 window = global;
就可以了。不过这里还要注意下面有一句代码 window = {};
会重置了我们前面加的代码,所以这一句要注释或者删掉:
到这里就基本 JS 代码差不多了,另外 r
函数会调用 z
函数从而调用 jsencrypt
方法,熟悉前端的话可以直接看出这里使用的是 RSA 加密算法,在 jsencrypt
下可以看到首先被设置了一个固定的公钥,加密的时候是将两个传入的参数拼接,然后进行加密后返回。因为这里使用的不是标准的 RSA 算法,所以就不深入分析,同时也没有办法使用 Python 的标准库进行加密,所以直接使用 Node 去调用 JS 文件计算:
完成上面的步骤,JS 代码就大体成型了,最后再补一个时间戳 t
函数方便调用。