JS逆向学习之JS语法(一)
目录
1.前言:
为什么在渗透测试/安全领域要熟悉 JS 逆向?
▪ 典型场景与案例分析
2. JavaScript 基础语法概览
2.1变量
2.1.1 变量声明方式
2.1.2 常用数据类型
2.2运算符
2.3函数
2.3.1 函数声明 & 表达式
2.3.2 箭头函数
2.3.3 作用域与闭包
2.4流程控制
3.逆向相关核心语法点
1.常见对象与原型链
2. 字符串相关
3. 动态代码执行
4. 常用加密与数据序列化API
5. 异步与网络相关
6. 事件与 DOM 相关
7. 调试相关要点
1.前言:
为什么在渗透测试/安全领域要熟悉 JS 逆向?
在黑盒渗透测试实践中,我们频繁遭遇各类请求加解密场景。这是由于为满足等保合规要求,大量行业系统(如金融、政务领域)开始对 HTTP 请求体进行加密处理,并引入动态签名、时间戳校验、随机 RequestId等防御机制。这些技术手段直接导致传统渗透方式(如暴力破解、数据包重放/篡改)失效——攻击者无法直接解析请求结构,更难以构造有效攻击载荷。
典型困境示例:
- 无法爆破登录接口:密码字段被前端 RSA/AES 加密,原始字典直接发包将被服务端拒绝
- 难以批量测试越权:请求需携带动态生成的 HMAC 签名,但签名逻辑完全封装在前端 JS 中
- 无法绕过风控拦截:请求头需附加由 JS 生成的设备指纹/行为轨迹加密参数
此时,JS逆向分析便成为突破此类防御体系的核心技术手段——通过逆向加密算法、解析签名规则、提取关键参数生成逻辑,攻击者可精准复现合法请求构造流程,进而穿透前端防护实现深度渗透。
▪ 典型场景与案例分析
这里我介绍一个靶场https://github.com/0ctDay/encrypt-decrypt-vuls/,这是一个本地JS逆向靶场,当我们需要练习JS逆向时,可以在这上面进行练习。
这里我推荐使用fofa在网上搜索一个
body="encrypt-labs" && country="CN"随便打开一个就可以了,之所以这里我推荐使用fofa寻找靶场,是因为JS靶场不用拿到flag,不用担心目录乱改和后端魔改,只需要在前端成功逆向出来即可,这时完全可以使用网上的靶场。(因为不知道网上的靶场过段时间还能不能连接,所以就不放链接了)
这时可能有人会有疑问,这不就是一个普通的登录页面吗?为什么会用上js呢?别急,我们抓包来看看。
首先请求体这里可以看到一大串加密数值,这种情况根本无法从burp进行爆破,这时就需要还原其加密及预处理机制了。
你以外就仅仅只有这点吗?再来看看这个
这是0佬写的靶场vue/_demo,点进去是这样
抓个包来看看
你可能会说,这不是和上一个一样吗?不不不,我们可以放到repeater里重放试试
这里可以看到相同的数据造成了不同的回显结果,这是因为其携带动态生成的requestID,在这个数据包中,同时拥有签名认证sign和requestID,当requestID中的值重复或者不满足格式时,便会被waf拦截。所以js逆向好啊,得学啊。
2. JavaScript 基础语法概览
2.1变量
每一种语言都是从变量开始学的,js也不例外,因为主要学习的是js逆向,所以这里仅对js语法进行简单说明。
2.1.1 变量声明方式
var:函数作用域,可被重复声明,变量提升(重点了解“提权”问题);let:块级作用域,不可重复声明,不变量提升;const:块级作用域,声明后不可重新赋值,常用于常量。
练习js的工具我们需要用到vscode和node.js,相信大家都已经安装过了吧,如果没有可以看这个帖子。
//这里附之前js环境搭建帖子链接//
2.1.2 常用数据类型
- 原始类型:
String,Number,Boolean,null,undefined,Symbol,BigInt - 引用类型:
Object,Array,Function,Date等
示例:用typeof测试各类型变量(typeof检测变量类型)
console.log( typeof "abc", typeof 5, typeof true, typeof {}, typeof [], typeof function(){});2.2运算符
到了运算符环节了,其实js和大多数语言一样,运算符也是来来回回那么几样,这里也不再多说了。
2.3函数
学习js逆向就是和各种函数打交道,所以函数也是必须要了解的。
2.3.1 函数声明 & 表达式
函数的声明有两种方式,表达式和函数声明。
- 声明:
function foo(){} - 表达式:
const foo = function(){}
区别:
- 函数声明会被提升到当前作用域顶部,因此可以在声明前调用
- 函数表达式中的命名,只在函数内部可用,外部无法访问
- 函数声明必须有函数名称,而表达式可以匿名
sayHello(); // 函数调用,声明函数可在声明前调用 function sayHello() { console.log("Hello!"); } // 2. 函数表达式 - 不会提升 try { sayGoodbye(); // 先尝试调用,报错: sayGoodbye is not a function } catch (e) { console.log("错误:", e.message); } const sayGoodbye = function() { console.log("Goodbye!"); }; sayGoodbye();//这里正常调用 // 3. 匿名函数表达式 const multiply = function(a, b) {//这里没有函数名称 return a * b; }; console.log("乘法结果:", multiply(3, 4)); // 4. 命名函数表达式(有名称标识符) const calculate = function factorial(n) {//函数名称是factorial return n <= 1 ? 1 : n * factorial(n - 1); }; console.log("阶乘结果:", calculate(5)); // 尝试访问函数表达式内部名称(外部不可访问) try { console.log(factorial(5)); //尝试直接使用函数名称调用函数,报错: factorial is not defined } catch (e) { console.log("错误:", e.message); }2.3.2 箭头函数
- 相比普通函数语法更简洁,只能作为表达式,常规用法不能用作构造函数(不支持 new)。
- 箭头函数不会创建自己的
this,其this绑定在定义时所在的外层作用域。
示例:使用this访问箭头函数和普通函数的对象
const obj = { name: 'Object', normal: function() { console.log(this.name); }, arrow: () => { console.log(this.name); } }; obj.normal(); // 输出: "Object" (this 指向 obj) obj.arrow(); // 输出: undefined (因为 window.name 未定义,this 指向全局 window 对象)2.3.3 作用域与闭包
- 作用域:变量的有效范围,包括全局/函数/块级作用域。
- 闭包:闭包指“函数可以记住并访问其定义时的作用域”,即使在其外部执行。其常见于函数内部返回一个内部函数,内部函数能访问外部函数的变量,常用于隐藏变量/敏感数据,对逆向极为重要。
示例:实现一个基本闭包计数器
function makeCounter(){ let count = 0; return function(){ return ++count; } } let counter = makeCounter(); console.log(counter()); //1 console.log(counter()); //22.4流程控制
到了典型的流程控制了,条件语句:if、switch循环语句:for、while、do...while跳转语句:break、continue、return等等,这些想必在其它语言时已经学习过了,因语法格式相同,就不在过多讲述了。
3.逆向相关核心语法点
想必到了这里你已经可以看懂大部分的js代码了,进入这一步已经可以开始最初的加密函数定位操作了,在渗透测试中,我们所需要的js知识到这一步已经差不多了,剩下的可以在实战中进行提升。当然,如果你的最终目的不是渗透测试,或者非常高级的渗透测试,想要达到通过反混淆–分析代码逻辑–研究参数作用–添加补环境–最终通过本地运行JS来加解密,那可能你还需要很多逆向相关的知识点,这里我举一些例子:
这里你还需要学习
1.常见对象与原型链
对象的创建:字面量、new Object()、构造函数
属性访问与操作:点/中括号访问,增删改查属性,delete 用法
对象枚举遍历:for…in、Object.keys()、Object.values()、Object.entries()
原型链与继承:proto、prototype、构造函数继承、Object.create
方法与 this:对象方法定义,this 的多种指向情况、箭头函数不绑定 this
hasOwnProperty:属性归属判断,混淆常避开此方法
对象 API 常用:Object.assign()、Object.defineProperty、JSON.stringify/parse
getter/setter:调试时常见属性访问拦截
对象解构、剩余参数:混淆时常用于分散变量
属性特性:可枚举性、可写性、可配置性(Object.getOwnPropertyDescriptor)
类型判断:typeof/instanceof、Array.isArray()
2. 字符串相关
常用方法:split、substring、substr、slice、replace、charCodeAt、fromCharCode
编码/解码:decodeURIComponent、encodeURIComponent、unescape、escape
拼接与拆解:字符串拼接混淆、模板字符串、Unicode/十六进制转义
3. 动态代码执行
eval / new Function:动态执行字符串中的代码,常被用做混淆和运行时还原
setTimeout/setInterval:传递匿名函数或字符串另类动态执行途径
4. 常用加密与数据序列化API
Base64:atob/Btoa,手写和常见第三方库
CryptoJS等调用:如何识别并断点调试加密运算过程
常见加密算法识别:md5, sha1, aes等在源码中的实现模式
JSON:JSON.stringify/parse,体会序列化/反序列化过程
5. 异步与网络相关
异步实现方式:回调、Promise、async/await
定时器:setTimeout/setInterval,影响代码流程
XHR/Fetch:识别和定位加密请求参数的生成与发送位置
6. 事件与 DOM 相关
事件绑定:addEventListener/onclick,常作为逆向入口埋点
常见 API 监听点:window.onload、表单提交、按钮点击等
DOM 读取/设置:getElementById、querySelector、innerText/innerHTML 等,与反爬有关的字段捕获
7. 调试相关要点
断点下标查找:所有动态加解密出现地
代码插桩:console/alert/log注入,随时打点观察关键变量变化
异常处理:try…catch拦截隐藏流程
《网络安全从零到精通全套学习大礼包》
96节从入门到精通的全套视频教程免费领取
如果你也想通过学网络安全技术去帮助就业和转行,我可以把我自己亲自录制的96节 从零基础到精通的视频教程以及配套学习资料无偿分享给你。
网络安全学习路线图
想要学习 网络安全,作为新手一定要先按照路线图学习,方向不对,努力白费。对于从来没有接触过网络安全的同学,我帮大家准备了从零基础到精通学习成长路线图以及学习规划。可以说是最科学最系统的学习路线,大家跟着这个路线图学习准没错。
配套实战项目/源码
所有视频教程所涉及的实战项目和项目源码
学习电子书籍
学习网络安全必看的书籍和文章的PDF,市面上网络安全书籍确实太多了,这些是我精选出来的
面试真题/经验
以上资料如何领取?
fb5d4309b20.jpeg#pic_center)