文章总结: 文章提出一套基于JSHook的Burp流量加解密通用方案:通过中间人注入脚本劫持网页encrypt/decrypt函数,实时将明文/密文上报本地服务;配套浏览器扩展与RPC接口,实现BurpRepeater内一键加解密,无需逆向算法即可审计加密Web接口。作者给出完整HTML示例、Hook代码、轮询脚本及插件使用截图,并开源实现地址,方便红队快速移植至各类JS加密站点。 综合评分: 78 文章分类: WEB安全,红队,渗透测试,安全工具,实战经验
基于JS_HOOK的web流量加解密方案
原创
kkk mr
漏洞推送
2026年1月12日 17:14 浙江
最近遇到一个web网站,流量是通过js的加密的,于是设计了一套较为通用的流量js hook配置burp的流量加解密方案。
方案分为以下几个部分:
•加密函数的参数和返回值记录•解密函数的的参数和返回值记录•生成请求的Rpc•解密响应的Rpc
优点: 不用管具体的加密算法的实现,找到函数即可
具体实现如下:
记录请求的密文和明文
假设现在网站源码如下:
<!DOCTYPE html><html lang="zh-CN">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <script> function encrypt(data) { return btoa(unescape(encodeURIComponent(data))); } function decrypt(data) { return decodeURIComponent(escape(atob(data))); }
async function send() { const inputData = "test"; if (!inputData) { return; } const encryptedData = encrypt(inputData); const payload = { message: encryptedData, timestamp: new Date().getTime() };
try { const response = await fetch('https://httpbin.org/post', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
if (response.ok) { const result = await response.json(); alert("resonpse:"+ decrypt(JSON.parse(result.data).message)); } else { alert("error: " + response.status); } } catch (error) { } } </script></head>
<body> <button type="button" onclick="send()">send</button></body>
</html>
encrypt是加密函数,decrypt是解密函数
通过burp中间人注入hook代码,hook后代码为
<!DOCTYPE html><html lang="zh-CN">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>demo</title> <script> function encrypt(data) { return btoa(unescape(encodeURIComponent(data))); } window.raw_encrypt = encrypt; encrypt = function (x) { const BASE_URL = 'http://127.0.0.1:9999'; async function reportData(plain, cipher) { await fetch(`${BASE_URL}/report`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ plaintext: plain, ciphertext: cipher }) }); }; plaintext = x; ciphertext = window.raw_encrypt(x); reportData(plaintext, ciphertext); return ciphertext };
function decrypt(data) { return decodeURIComponent(escape(atob(data))); } window.raw_decrypt = decrypt; decrypt = function (x) { const BASE_URL = 'http://127.0.0.1:9999'; async function reportData(plain, cipher) { await fetch(`${BASE_URL}/report`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ plaintext: plain, ciphertext: cipher }) }); }; ciphertext = x; plaintext = window.raw_decrypt(x); reportData(plaintext, ciphertext); return plaintext };
async function send() { const inputData = "test"; if (!inputData) { return; } const encryptedData = encrypt(inputData); const formData = new URLSearchParams(); formData.append('data', encryptedData); try { const response = await fetch('https://httpbin.org/post', { method: 'POST', headers: { // 必须指定 Content-Type 'Content-Type': 'application/x-www-form-urlencoded' }, body: formData // 直接传入 URLSearchParams 对象 });
if (response.ok) { const result = await response.json(); alert("resonpse:" + decrypt(JSON.parse(result.data).message)); } else { alert("error: " + response.status); } } catch (error) { } } </script></head>
<body> <button type="button" onclick="send()">send</button></body>
</html>
这样就将我们将加解密都hook成我们的函数,并且在执行的时候会进行上报
至此,我们可以实现浏览器流量的加解密,效果如下:
原始请求:
解密请求:
原始响应包:
解密响应包:
Rpc实现请求加密
通过右键扩展,将明文数据发送到重放器
效果如下:
我们修改包的参数,然后在浏览器执行如下js代码:
(function () { const BRIDGE_URL = "http://127.0.0.1:9999";
/** * Site-specific Encryption Logic */ function Encryption(plainText) { return window.raw_encrypt(plainText); }
/** * Site-specific Decryption Logic * Replace 'window.targetDecrypt' with the actual function found on the site */ function Decryption(cipherText) { return window.raw_decrypt(cipherText); }
/** * Send result back to Burp Bridge */ async function reportResult(taskId, result) { try { await fetch(`${BRIDGE_URL}/task`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: taskId, result: result }) }); } catch (e) { console.error("Failed to report result:", e); } }
async function pollTask() { try { const resp = await fetch(`${BRIDGE_URL}/task`); const task = await resp.json();
// Ignore IDLE state to reduce console noise if (task.type === "IDLE") { return; }
console.log("New Task Received:", task.type, task.id);
let result = null; if (task.type === "ENCRYPT") { result = await Encryption(task.payload); } else if (task.type === "DECRYPT") { console.log( "DECRYPT",task.payload) result = await Decryption(task.payload); }
if (result !== null) { await reportResult(task.id, result); console.log("Task Completed:", task.id); }
} catch (e) { // console.error("Poll Error:", e.message); } finally { // Use 200ms-500ms for better responsiveness setTimeout(pollTask, 300); } }
console.log("JS Bridge Client Started... Waiting for tasks."); pollTask();})();
加密请求
然后选中我们要加密的文本,右键
js收到请求后处理:
加密效果:
解密请求
原始响应:
点击响应的Decrypted tag 触发rpc
插件使用方法
示例代码开源在:
https://github.com/lanyi1998/js_hook_decrype
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:漏洞推送 kkk mr《基于JS_HOOK的web流量加解密方案》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。





![成果分享|[USENIXSecurity2025]功能变更驱动的远程软件版本识别方法](/images/random/titlepic/6.jpg)




评论