2.如何定位加密
第一章 哪里可以加密
第一节 每次请求可以携带什么
> 回顾网站数据交换的过程(假设高加密的网址):
①页面收集数据: pageindex, total, searchkey,...,时间戳,特定**鉴权信息**[加密A]
°页面发送数据给==>后端°
②后端处理数据: pageindex,...,对鉴权信息`解密A`并验证===>**返回数据**[加密B]
°后端返回数据给==>前端°
③页面拿到数据: 对后端给的数据`解密B`(抓包看到的),并渲染到页面上
> 每次请求可以携带什么[后面为在开发者工具的具体位置]**加密A**
1.正常请求参数(page, total,keyVale..)--->请求参数[载荷]
2.用户信息(username,userpassword...)--->Cookie[标头.Cookie/浏览器.内存.存储.Cookie]
3.用户浏览器信息(UA,Sign,TimeStamp..)--->请求头[标头.请求标头]
> 服务器返回什么[后面为在开发者工具的具体位置]**加密B**
4.响应数据(data,statecode..)--->[响应]
> 由此推出
也就是上述这4个地方可以加密,我们就只需要观察这4个地方是否有加密,有我们找JS解密,即可模拟发送请求
第二节 可以加密的地方
1.2.1 误区纠正GET和POST
- 查询字符串参数: 就是拼接在URL?后面的内容, 只是浏览器为了展示在, “载荷”一栏中展示, 不要错认为是表单数据了!!!
- GET请求: 点击”载荷”一栏后看到的是 “查询字符串参数” ; 这个参数是拼接在网址后面的, 在 link
- POST请求: 点击”载荷”一栏后看到的是 “表单数据” ; 也可以有 “查询字符串参数” link
1.2.2 四大加密位置




第二章 定位加密—DOM/XHR
第一节 DOM断点
2.1.1 概念解析
**用户在页面触发事件** --> 构造请求对象 --> 请求拦截器 --> [加密数据] --> 发送请求 --> 返回数据 --> 响应拦截器 --> 请求成功的回调 --> 展示到开发者工具包中
- $ 概念: 使用 DOM事件断点,你可以指定在哪些 DOM 事件上设置断点,比如点击(click)、改变(change)、加载(load)等。一旦设置了 DOM 事件断点,当相应的事件被触发时,浏览器会自动在触发事件的 JavaScript 代码行上暂停执行
- $ 特点: 执行的比较靠前, 往后找, 距离加密函数比较远
2.1.2 实战DOM断点调试
需求: 找到 link 加密的位置
- 选中需要要定位的元素, 右侧 “事件监听器” 选中click 下的文件一个个进去下断点
- click下可能不止一个文件
- 文件不一定是JS, 如下就是HTML, 但调试下一步, 就会进到
Passprt.Login()方法

第二节 XHR断点
XHR可能不是最快的, 但是一定能定位到加密的方法
2.2.1 概念解析
用户在页面触发事件 --> 构造请求对象 --> 请求拦截器 --> **发送请求** --> 返回数据 --> 响应拦截器 --> 请求成功的回调 --> 展示到开发者工具包中
- $ 概念: XMLHttpRequest, 浏览器自动帮你拦截 “指定URL” 发请求的 “send方法”
- $ 特点: 往前找, 栈底找
- & 说明:
- ①XHR(XMLHttpRequest)是浏览器原生API, 底层通信协议实现
- ②无论是ajax还是axios等其底层都是用的XHR发请求, 浏览器中发请求90%都是XHR
- ③因为网址用的是ajax/axios, 所以他们的开发人员调用的是
$.get()方法, 但是底层都会到XMLHttpRequest.send()方法去真正发请求
- ! 注意: 浏览器自带的xhr拦截的是
XMLHttpRequest.send()方法,
2.2.2 XHR完整请求流程
- $ 语法: ①
xhr.open()这个方法初始化请求 ②xhr.send()真正的发送请求 ③xhr.onreadystatechange()成功/失败的回调
// 1. 创建实例
const xhr = new XMLHttpRequest();
// 2. 初始化请求(未真正发送)
xhr.open('GET', 'https://api.example.com/data', true); // 第三个参数为是否异步
// 3. 设置请求头(可选)
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
// 4. 事件监听(核心回调)[必须写在 open之后, send之前]
xhr.onreadystatechange = function() {
// 请求状态变化时触发(会多次触发)
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log('成功响应:', xhr.responseText);
} else {
console.error('请求失败:', xhr.status);
}
}
};
// 其他事件监听方式
xhr.addEventListener('load', function() {
console.log('请求完成');
});
xhr.addEventListener('error', function() {
console.error('网络错误');
});
xhr.addEventListener('timeout', function() {
console.error('请求超时');
});
// 5. 配置超时(单位毫秒)
xhr.timeout = 5000;
// 6. 发送请求(GET请求通常不传body)
xhr.send(/* POST数据放这里,例如 JSON.stringify(data) */);
2.2.3 axios拦截器
- & 说明:
- ①基于xhr的有
ajax/$,axios,Fetch API,umi-request这些都可以发请求, 底层用的都是XHR - ②并且每个都可以实现 “请求拦截“, 和 “响应拦截“
- ③而在 拦截方法 里面就有可能存在加密/解密, 由此就可以定位 (但需要注意不是所有的网址都用拦截器)
这里就展示
axios的拦截器
- ①基于xhr的有
// npm install axios
axios = require('axios')
//设置请求拦截器
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功')
config.headers['sign'] = 'lili'
return config;
}, function (error) {
console.log('请求拦截器 失败')
return Promise.reject(error);
});
//设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功')
console.log('调解密函数进行解密数据')
// 鉴权通过后, 加密显示在 调试工具的包中给你看
return response.data; //修改响应数据
}, function (error) {
console.log('响应拦截器 失败')
return Promise.reject(error);
});
//发送请求
axios.get('http://httpbin.org/get').then(res=>console.log(res))
2.2.4 实战XHR断点调试
需求: 找到 link 加密的位置
- 抓包, 找到需要卡的网址, 然后 “掐头去尾“ 复制 “路径“ 部分
https://oauth.d.cn/auth/login?query_parameters...#section1
└──┬─┘ └───┬──────┘└───┬─────┘└─────┬─────┘ └───┬───┘
协议 域名 路径 查询参数 片段(不发给服务器, 只供客户端用)
- 粘贴到如下位置, 并打钩, 然后所有的包含这个 “路径” 的请求都会断住
- ! 注意: 这个是断在
xhr.send()位置
2.2.5 XHR进阶技巧❗
- $ 技巧一: 对栈进行二分 去看
- & 举例: 例如栈为A, B, C, D(D为栈底); 如果A加密, 看D; 如果D没加密, 看B; 如果B没加密, C加密===>加密在C; 二分时间O(nlogn)
- $ 技巧二: 在异步的回调中加密
- & 说明:
n.then(成功的回调, 失败的回调)这里的n.then是在一个for循环里面的, 回调函数是放在一个 “长度为6的数组” 中的, 那其中0, 2, 4就是成功的回调(t.shift()方法是删除数组第0个元素, 并返回) 那加密就是在0, 2, 4里面去找
- & 说明:
- $ 技巧三: 栈突然往前跳!
- & 说明: 还记得拦截器吗? 服务器返回数据 –> 拦截器 –> 成功的回调; 如果拦截器写在前面的栈里面, 当调用成功的回调时就会前跳

- & 说明: 还记得拦截器吗? 服务器返回数据 –> 拦截器 –> 成功的回调; 如果拦截器写在前面的栈里面, 当调用成功的回调时就会前跳
第三节 搜索关键字
搜索关键字的技巧比较多, 也是最快的, 常见的有以下几种
- 同一个”请求参数”中比较明显的参数进行搜索,
- 和启动器结合, 搜索关键中, 在启动器方法里面的
- 精确搜索, (比如要pass 排除password等), pass: pass=…
第三章 定位加密—Hook
第一节 Hook JSON.parse
用户在页面触发事件 --> 构造请求对象 --> 请求拦截器 --> 发送请求 --> **返回数据** --> 响应拦截器 --> 请求成功的回调 --> 展示到开发者工具包中
| 请求头 | 请求参数 | Cookie | 响应数据 | |
|---|---|---|---|---|
| JSON.parse | √ | √ |
3.1.1 适用场景
js对象(字典/表单) ---JSON.stringify()--->JSON字符串
<--JSON.parse()--------
- @ 问题: 所以该Hook能用在哪里?
- & 说明: 有表单的位置, ①请求参数 ②响应数据; 只要这两个地方出现加密, 都可以考虑用这个Hook
(function() {
var _parse = JSON.parse;
JSON.parse = function(ps) {
console.log("Hook JSON.parse ——> ", ps);
debugger;
return _parse(ps); // 不改变原有的执行逻辑
}
})();
3.1.2 实战【响应数据加密】
需求: 找到 link 解密翻译结果的方法
- 确定需要 JSON.parse进行Hook
- 在调试前注入Hook代码
- ! 注意: Hook代码一定要在调试开始前执行



第二节 Hook Cookie
| 请求头 | 请求参数 | Cookie | 响应数据 | |
|---|---|---|---|---|
| JSON.parse | √ |
3.2.1 适用场景
Object.definProperty 是ES5支持的代理, ES6变为了Proxy 视频讲解Proxy
- $ 语法: 记得hook cookie前, 先清除下cookie [[1.JS基础与浏览器开发工具#7. 拦截对象的get和set方法]] link
(function () {
cookieTemp = document.cookie;
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.indexOf('需要捕获的Cookie名称') != -1) {
debugger;
}
console.log('Hook捕获到cookie设置->', val);
cookieTemp = val;
},
get: function () {
return cookieTemp;
},
});
})();
3.2.2 实战 【Cookie加密】
需求: 还没找到网站….
3.2.3 注意事项
cookie一般都需要刷新网页, 而刷新网页会导致hook的代码失效, 所以提供一下两种方法去解决
- 脚本断点: 等到第一个网页的js文件加载的时候 注入hook代码
- 油猴: 教程 油猴可以实现, 在网页加载(前/body加前等)时机进行hook; 如下给一个油猴hook的模板
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 2025-02-05
// @description try to take over the world!
// @author You
// @match https://www.cnvd.org.cn/flaw/typelist?typeId=27
// @icon https://www.google.com/s2/favicons?sz=64&domain=csdn.net
// @grant none
// ==/UserScript==
(function () {
var cookieTemp = document.cookie;
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.indexOf('__jsl_clearance_s') != -1) {
debugger;
}
console.log('Hook捕获到cookie设置->', val);
cookieTemp = val;
},
get: function () {
return cookieTemp;
},
});
})();
第三节 Hook XHR请求
用户在页面触发事件 --> 构造请求对象 --> 请求拦截器 --> **发送请求** --> 返回数据 --> 响应拦截器 --> 请求成功的回调 --> 展示到开发者工具包中
3.3.1 适用场景
- & 什么讲的原生XHR中, 有
XMLHttpRequest.open()(初始化请求) ; 和XMLHttpRequest.send()(真正发请求), 浏览器的xhr断点是断send, 我们可以手段断open(), 因为open()离发送请求的地方较近
// 如果是正数 表示存在里面
// 如果是-1 表示不在里面
(function () {
var open = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, url, async) {
if (url.indexOf("analysis") != -1) {
debugger;
}
return open.apply(this, arguments);
};
})();
3.3.2 实战【请求参数加密】
需求: 找到 七麦数据 请求参数加密位置
进过一番查找, 因为这里是异步的, 很难找; 但总的思路还是在的, 因为XHR open 就准备发送了, 加密一定往前找, 顶多就是多看几个栈
这里和原生的 浏览器 xhr断点 做一个对比: 有总比没有好
第四章 B/S的通讯
❗为什么要单独整理这个??? 因为只有知道别人请求是怎么发送的, 你XHR断点才有目标, 否则就算找到也是碰运气!
第一节 名词辨析
- & 问题: XHR, Fetch, ajax, Jquery , Axios, Promise, async 这些都是啥😰 看完下面这4点, 就能明白, 耐心点!
- 概念: Ajax(Asynchronous JavaScript + XMLHttpRequest)①是一个概念, 支持异步发送请求, ②最原来浏览器渲染是不支持异步的, 只能通过 form/链接 给后端发送请求, 而如果想更新页面数据, 就必须刷新页面, ③直到有了Ajax这个技术, 才支持异步模式(不刷新网页, 也能更新数据)
- 浏览器API层: ①XHR(2005)和Fetch(2015)都是浏览器原生的API, ②都是基于Ajax这个概念, 支持和后端进行异步通讯
- 封装层: ①因为XHR和Fetch写起来很麻烦(原生的都很麻烦) ②才有了诸如, jquery, axios等工具库 ③✔️, 他们是js的工具库 ④其中jquery ajax和ajax是不同的概念, 前者是工具库,jquery中除了有ajax来发送请求, 还有可以获取页面元素的”语法糖”, 是一个js工具库; 后者单独的ajax是一个模式/技术, 是异步技术;
- JS语法: ①Promise和async可以理解为JS的语法 ②配合XHR/Fetch才能实现请求方发送
经历的阶段:
3. 传统模式:通过浏览器默认导航行为(表单form/链接href)的**同步页面跳转** [必须刷新才能更新数据]
4. AJAX模式:使用**XHR/Fetch**等技术实现的**异步HTTP请求** [不刷新也能更新数据]
5. WebSocket:独立实现的**双向实时通信**方案(不属于AJAX体系)[不关注]
浏览器可以给后端发请求的相关概念
├─ 浏览器API层
│ ├─ XHR (XMLHttpRequest) 【原生Ajax; Ajax模式(异步模式)】
│ ├─ Fetch API 【Ajax模式(异步模式)】
│ └─ WebSocket API 【不关注】
│
└─ 封装层
├─ jQuery AJAX(XHR封装)
└─ axios(基于XHR的Promise封装)
第二节 XHR发送请求
- $ 语法: 原生的XHR没有 “请求拦截器” or “响应拦截器”
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>XHR GET实现</title>
</head>
<body>
<!-- 添加点击事件监听 -->
<button id="sendBtn">发送XHR GET请求</button>
<script>
// 封装请求函数
function sendRequest() {
// 每次点击创建新的XHR实例(避免重复请求问题)
const xhr = new XMLHttpRequest();
const params = new URLSearchParams({
ts: '2132312',
sign: '321321'
});
xhr.open('GET', `http://localhost:8080/get?${params}`);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log('响应数据:', JSON.parse(xhr.responseText));
} else {
console.error('请求失败:', xhr.status);
}
}
}
xhr.send();
}
// 绑定点击事件
document.getElementById('sendBtn').addEventListener('click', function(e) {
e.preventDefault(); // 防止按钮默认行为
console.log('开始发送请求...');
sendRequest();
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>XHR POST实现</title>
</head>
<body>
<button id="sendBtn">发送XHR POST请求</button>
<script>
function sendRequest() {
const xhr = new XMLHttpRequest();
// POST请求地址
xhr.open('POST', 'http://localhost:8080/post');
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');
// 请求参数(URL参数+请求体)
const urlParams = new URLSearchParams({
ts: '2132312',
sign: '321321'
});
// 请求体数据
const postData = {
page: '1',
content: 'test'
};
// 状态监听
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(`状态码: ${xhr.status}`, xhr.responseText);
}
}
// 合并URL参数并发送(GET风格参数 + POST请求体)
xhr.send(JSON.stringify(postData));
}
// 绑定点击事件
document.getElementById('sendBtn').addEventListener('click', function(e) {
e.preventDefault();
console.log('开始POST请求...');
sendRequest();
});
</script>
</body>
</html>
第三节 Fetch发送请求
第四节 JQuery发送请求
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery GET实现</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<button id="sendBtn">发送jQuery GET请求</button>
<script>
// 请求拦截器(全局设置)
$.ajaxSetup({
beforeSend: function(xhr) {
// 公共请求头设置
xhr.setRequestHeader('Authorization', 'Bearer token123');
// 添加公共参数
this.url += `?ts=${Date.now()}&sign=${btoa('secret')}`;
}
});
// 发送GET请求
function sendGet() {
$.ajax({
url: 'http://localhost:8080/get',
method: 'GET',
headers: {
'X-Custom-Header': 'jquery-demo'
},
data: {
page: 1,
size: 20
},
success: function(response) {
console.log('解密后的响应:', decrypt(response));
},
error: function(xhr) {
console.error('请求失败:', xhr.status);
}
});
}
// 绑定点击事件
$('#sendBtn').click(function(e) {
e.preventDefault();
console.log('jQuery GET请求启动');
sendGet();
});
</script>
</body>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery POST实现</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<button id="sendBtn">发送jQuery POST请求</button>
<script>
// 请求前置拦截器
$.ajaxPrefilter(function(options) {
if (options.method === 'POST') {
// 加密请求体
options.data = JSON.stringify(encryptData(options.data));
options.contentType = 'application/json';
}
});
// 发送POST请求
function sendPost() {
$.ajax({
url: 'http://localhost:8080/post',
method: 'POST',
headers: {
'X-Request-Source': 'jquery'
},
data: {
username: 'admin',
password: 'encrypted123'
},
success: function(response) {
console.log('响应处理:', response);
}
});
}
// 绑定点击事件
$('#sendBtn').click(function(e) {
e.preventDefault();
console.log('jQuery POST请求启动');
sendPost();
});
</script>
</body>
</html>
第五节 axios发送请求
第五章 不同位置的加密怎么找
这里都是针对 XHR 的!!!
第一节 请求头加密
你XHR都是定位到send的位置, 设置请求头, 在发送请求前的任何位置都有可能
第二节 请求参数加密
第三节 载荷加密
第四节 响应体加密
第五节 Cookie加密
- Title: 2.如何定位加密
- Author: 明廷盛
- Created at : 2026-02-12 01:17:04
- Updated at : 2025-02-15 15:36:00
- Link: https://blog.20040424.xyz/2026/02/12/🐍爬虫工程师/第二部分 JS逆向/2.如何定位加密/
- License: All Rights Reserved © 明廷盛











