Skip to content

简单的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代码:

20211216162240

我们打开解码网站,将代码粘贴进去,解码后的结果为:false

20211216164553

编码后的代码放在控制台中执行,可能有如下四种情况:

  1. 控制台执行报错,且非 unsafe 错误:点击报错信息即可还原代码;
  2. 控制台执行不报错,删除一些语法(以括号为主),强制令其报错;
  3. 控制台报 unsafe 错误:自己写个 html 运行,然后删除语法令其报错即可还原;
  4. 仅仅混淆部分数字的情况,一般情况下,上面的说法就失效了,只能一段一段的敲入 console 中或者采取网上一键解混淆。

题目实践

题目难度:非常简单

访问题目获取题目信息,并找到数据来源接口:

20220309171638

向后翻了 2 页,发现请求中的 POST 参数每次都会发生变化,其中 page 参数是页码,uc 参数是加密参数 :

20220309172220

选择 Initiator 选项卡,点击请求回调栈中的 call 跳转到发送该请求的位置:

20220309171740

跳转后,发现了想要的参数信息。从图中可以看到 window.a 是一个需要传参的函数,但在下面的 POST 传递的参数中 window.a 是一个加密字符串,说明该变量在代码过程当中被重新赋值了,而中间代码就只剩下 [](![]+[])... 这段了,根据内容判断该段代码是经过JS_Fuck编码后的代码:

20220309172733

我们将这段代码拷贝下来,在Console栏中运行,发现报错了,并提示了错误位置:

20220309174025

我们点击错误位置,追进去后就是还原后的 JS 代码了。发现 window.a 被重新赋值了:

20220309174239

aaencode编码

简单介绍

aaencode 编码:将正常的 JS 代码编码为好玩的特殊网络表情符号,如: ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) 这样的表情文字。

aaencode 解码网站:https://www.qtool.net/decode

20211216162210

我们打开解码网站,将 aaencode 代码代码粘贴进去,解码后的结果为:window.o = 1;

20211216163749

20211216163814

题目实践

题目难度:非常简单

访问题目,一来就首先遇到 debugger,我们在左边侧栏右键选择 Never pause here 永远不停留这里:

20220313033406

注意外面定时器 setInterval(function(){} 和里面 debugger 都要打上断点,在右侧 Breakpoint 显示有两个断点,效果如下:

20220313034537

理解题目要求,找到数据接口:

20220313033744

往后翻动两页,观察请求头,发现每次请求 safe 参数都会有所变化:

20220313033934

选择 Initiator 选项卡,点击请求回调栈中的 call 跳转到发送该请求的位置:

20220313034128

跳转后,发现了想要的参数信息。在我们打断点的位置上面两行,有一个 request.setRequestHeader 设置请求头的操作,参数名称是 safe,值是 token,但我们全局搜索发现整个页面 token 只有一个,那么很有可能 token 产生于中间那一串表情字符的 aaencode 代码当中了:

20220313034256

为了验证我们猜想,在 201 行、202 行打上断点,并在控制台分别打印 token 的值,发现两次打印 token 的值都不一样,说明 aaencode 代码对 token 进行了赋值操作:

20220313035349

我们将这段代码拷贝下来,在 Console 栏中运行并没有报错,返回了一个undefined,说明代码是很可能是一个没有设置返回值的自执行函数

20220313035640

在上图中末尾有一个独立的 ('_') 符号,我们删掉它再次打印,就会发现函数的内容:

20220313040551

双击输出的函数内容就会跳转到一个临时的 VM 文件里面,其内容就是完整的函数内容,逻辑也很简单就是围绕 a 这个有关时间戳的变量进行编码加密,我们在不熟悉的方法前面打上断点,继续运行:

20220313040848

所有不熟悉的方法都指向了 mian.js 这个文件:

20220313041219

进入这个 mian.js 文件,发现内容也是被 ob 混淆了的,但无论怎么混淆,它终究是可以运行的:

20220313041416

接下来,就是将 VM 文件里面的函数内容和被混淆的 mian.js 内容结合起来,最后生成 token 并返回就可以了。首先我们写一个函数,将 VM 文件内容粘贴过来,将 mian.js 未格式化的内容(这里是为了防止JS代码进行格式化检测)粘贴过来并注释掉,再一层层解封 mian.js 文件中的方法:

20220313042544

[!ATTENTION]

本题中 JS 代码使用的 iil 变量包含不常见字符,会在 Python脚本中调用会引发报错,最好换一个名称。

jjencode编码

简单介绍

jjencode 编码:就是将正常的 JS 代码编码成形如 [$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$ 这样符号的字符串。

jjencode 解码网站:https://www.qtool.net/decode

jjencode解码流程和aaencode解码流程没有什么差别,例举内容如下:

javascript
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"('\\"+$.__$+$.$_$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+"\\"+$.$__+$.___+"\\"+$.__$+$.$_$+$._$_+"\\"+$.__$+$.$$_+$._$$+"\\"+$.__$+$.$_$+$._$_+"\\"+$.__$+$.$_$+$.__$+$.$_$_+"\\"+$.__$+$.$_$+$.$_$+"\\"+$.__$+$.$_$+$.__$+"."+$.$$__+$._$+"\\"+$.__$+$.$_$+$.$_$+"')\\"+$.__$+$._$_+"\\"+$.__$+$.__$+"\\"+$.__$+$.__$+"\\"+$.__$+$.__$+"\"")());

上面的内容放到浏览器中执行就是如下内容:

javascript
ƒ anonymous() {
    alert('hello jsjiami.com')
}

题目实践

难度:中等

访问网址获取任务,在 Network 里面的 Fetch/XHR 选项中定位到了该网页数据的来源请求:

20211216153034

观察响应结果可以发现,返回的数值当中只有三等奖金的数值,先不着急,点击 Initiator 中 request 进行跳转:

20211216153459

跳转成功,代码格式化后,我们重点关注 success,前面讲过 success 代表着请求成功响应的结果:

20211216153657

将代码向后拉,可以看到 value 被多次使用,返回的值就是 value 的倍数,结合网页中显示的数值对比代码,可以发现如下规律:

20211216154359

**题目要求是计算一、二、三等奖之和,按照对应关系就是三等奖数值的24倍,及等于总销售额数值。**知道了数值的规律,接下来就是要分析请求了。经过多次请求发现请求头 headers 并未发生变化,而是 URL 的参数在不断变化:得出初步接结论,本题的加密重点为URL的请求参数:未知参数 m 和未知参数 q

20211216155518

和上面一样,回到请求的 Initiator 中,点击 request 进行跳转,未知参数 m 和未知参数 q 的组成一目了然:

20211216160129

window.i:初始为空字符串
t:时间戳
page:页码
m:未知函数r(t, window.o)
q:(window.i:初始为空字符串)每次请求加等window.o + '-' + t + "|"
window.o:每次请求加1

**现在的未知参数就变成了未知函数 rwindow.o 的初始值了。**在 r 函数处打上断点,发现指向的是另一个文件:

20211216161109

点击 r 函数进行跳转,格式化后代码如下:

20211216161337

**发现在这个文件当中也使用到了 window.o,而且当 window.o 的值大于等于6时,页面不会再发送 Ajax 请求,而是重新加载页面,当前我们最关心的就是最后一行 return z(param1, param2); 所返回的结果。**我们将所有的代码拷贝下来,格式化,发现里面有两处经过编码后的js代码:

20211216162210

20211216162240

我们将第一处aaencode代码,放入解密网站当中,点击aaencode解密,结果如下:

20211216163749

20211216163814

**这一下,就解决了 window.o 的初始值。通过整体的分析来看, window.o 就是一个翻页累加器,当前文件中就只有一处使用到了,就是上面的小于等于 6 那里,其目的就是控制翻页数的增加导致请求的 URL 参数越来越长,作用不大可以直接删除。**接下来,将第二处的 JSFuck 代码放入网站解密,其结果就是一个 false:

20211216164553

代码解码替换后,接下就是补环境,开始补环境前,我们再回顾以下 Node 环境和浏览器环境的差异:

image-20231213000003706

因为在 Node 环境中没有 BOM,所以浏览器环境的全局对象 window 是用不了的,因此这里我们就必须使用 Node 环境的全局对象 global,它类似于浏览器环境中的 window 对象。但这里有一个问题就是,从浏览器中抠出来的 JS 代码的凡是使用全局对象的都是 window,没有 global。其实这个问题很简单,只要在 JS 代码最前面加上一句 window = global; 就可以了。不过这里还要注意下面有一句代码 window = {}; 会重置了我们前面加的代码,所以这一句要注释或者删掉:

20211216170647

到这里就基本 JS 代码差不多了,另外 r 函数会调用 z 函数从而调用 jsencrypt 方法,熟悉前端的话可以直接看出这里使用的是 RSA 加密算法,在 jsencrypt 下可以看到首先被设置了一个固定的公钥,加密的时候是将两个传入的参数拼接,然后进行加密后返回。因为这里使用的不是标准的 RSA 算法,所以就不深入分析,同时也没有办法使用 Python 的标准库进行加密,所以直接使用 Node 去调用 JS 文件计算:

20211216171516

完成上面的步骤,JS 代码就大体成型了,最后再补一个时间戳 t 函数方便调用。