当前位置: 首页 > news >正文

关于 js:9. Node.js 后端相关

一、Node 环境搭建与执行流程

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它让 JS 不再局限于浏览器内,而是可以在服务器、终端、本地脚本中运行

核心定位:让我们可以用 JS 写本地程序、脚本、爬虫、加密逻辑、hook 工具、代理服务器等一切“非网页”程序。

1. Node.js 安装与环境搭建

1)下载 Node.js

官网地址:Node.js — Run JavaScript Everywhere

建议安装 LTS(长期支持版),比如 Node 18.x,因为一些库在新版本可能不兼容。

2)验证是否安装成功

打开终端输入:

node -v    # 显示 Node 版本
npm -v     # 显示 Node 的包管理器 npm 的版本

3)使用 nvm 管理多个版本

在实际项目中,不同工具/库可能依赖不同 Node 版本,这时用 nvm 可以快速切换版本。

安装(以 Linux/macOS 为例):

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

然后安装/切换版本:

nvm install 18
nvm use 18
nvm install 14
nvm use 14

Windows 用户可以安装 nvm-windows

2. Node 执行流程与原理

1)执行一个 Node 脚本

node myscript.js

Node 会按照以下流程处理这段 JS:

步骤解析:

  1. 加载模块
    加载内置模块(如 fscrypto)和你写的文件或库(require()

  2. 构造运行环境
    创建一个伪装的浏览器环境,提供 globalprocessconsolesetTimeout 等函数

  3. 使用 V8 编译代码为机器码
    Node 使用 V8 引擎将 JS 代码编译为机器码并执行(所以跑得飞快)

  4. 执行主线程代码
    运行 myscript.js 中的同步代码

  5. 进入事件循环
    处理异步任务(如 setTimeout, http 请求, 文件读写 等)

2)Node 与浏览器环境的不同

功能Node.js浏览器
全局对象globalwindow
DOM 操作 无 有
网络请求httphttps模块fetch, XHR
加密模块crypto(强大)受限
沙箱执行vmvm2 无

所以在逆向时,如果把网页 JS 拿到本地来跑,大多数时候需要用 Node.js 模拟执行,尤其适合调试加密逻辑。

3. Node 工程结构

my-script/
├── index.js         # 入口文件
├── encrypt.js       # 加密函数
├── utils.js         # 工具方法
├── data/            # 保存中间数据
├── logs/            # 日志输出
├── package.json     # 项目依赖描述文件

举例:

/*
Project: my-script
Structure:my-script/├── index.js         # 入口文件├── encrypt.js       # 加密函数├── utils.js         # 工具方法├── data/            # 保存中间数据├── logs/            # 日志输出└── package.json     # 项目依赖描述文件
*/// --- package.json ---
{"name": "my-script","version": "1.0.0","description": "示例 Node.js 项目,演示加密与日志","main": "index.js","scripts": {"start": "node index.js"},"dependencies": {}
}// --- encrypt.js ---
// 加密函数模块,使用 HMAC-SHA256 将文本与密钥签名
const crypto = require('crypto');/*** 对文本进行 HMAC-SHA256 签名* @param {string} text - 待加密的文本* @param {string} secret - 密钥* @returns {string} 十六进制签名*/
function encrypt(text, secret) {return crypto.createHmac('sha256', secret).update(text).digest('hex');
}module.exports = { encrypt };// --- utils.js ---
// 工具方法模块,提供文件和日志操作
const fs = require('fs');
const path = require('path');const DATA_DIR = path.resolve(__dirname, 'data');
const LOG_DIR = path.resolve(__dirname, 'logs');// 确保目录存在
function ensureDir(dir) {if (!fs.existsSync(dir)) {fs.mkdirSync(dir, { recursive: true });}
}// 写入 JSON 数据到 data 目录
function writeData(filename, obj) {ensureDir(DATA_DIR);const filePath = path.join(DATA_DIR, filename);fs.writeFileSync(filePath, JSON.stringify(obj, null, 2), 'utf-8');
}// 日志输出到 logs 目录
function log(message) {ensureDir(LOG_DIR);const timestamp = new Date().toISOString();const logLine = `[${timestamp}] ${message}\n`;const logFile = path.join(LOG_DIR, 'app.log');fs.appendFileSync(logFile, logLine, 'utf-8');console.log(logLine.trim());
}module.exports = { writeData, log };// --- index.js ---
// 项目入口文件,演示加密和数据保存流程
const { encrypt } = require('./encrypt');
const { writeData, log } = require('./utils');// 示例输入,可以改为从 process.argv 或 env 中读取
const inputText = 'Hello, Reverse Engineering!';
const secretKey = 'my_secret_key';log('项目启动');
const signature = encrypt(inputText, secretKey);
log(`加密结果: ${signature}`);// 保存结果到 data/result.json
writeData('result.json', { text: inputText, signature });
log('结果已保存到 data/result.json');log('项目结束');

运行方式:

node index.js

4. npm / npx 使用(包管理器)

npm install axios
npm install puppeteer
npm install vm2

npx 可以临时运行工具包,不用全局安装:

npx asar extract app.asar ./unpacked

总结

名称作用
Node.js用于本地运行 JS 脚本(突破浏览器限制)
nvm管理多个 Node 版本(防止依赖冲突)
npm/npx安装运行依赖工具库
node 脚本可执行 JS 文件,用于爬虫/hook/加密调试
事件循环保证异步逻辑(如文件/网络)不阻塞主线程

二、fs 模块

fs 是 Node.js 的内置模块,提供对文件系统的操作功能,包含:

  • 文件读写

  • 文件夹操作

  • 文件信息查询

  • 监听文件变化

  • 创建/删除/重命名

可以用它做类似 Python 中 open()osshutil 的事。

1. 引入 fs 模块

const fs = require('fs');

Node.js 中一切 IO 操作(包括 fs)默认提供两套接口:

类型描述适用场景
同步(Sync)阻塞后续代码执行,简单易用小脚本、调试逻辑
异步(Async)非阻塞,有回调或返回 Promise高并发、生产级程序

2. 常见用法大全(对照表)

功能异步方法同步方法
读文件fs.readFile(path, cb)fs.readFileSync(path)
写文件fs.writeFile(path, data, cb)fs.writeFileSync(path, data)
追加写入fs.appendFile(path, data, cb)fs.appendFileSync(path, data)
判断文件是否存在fs.existsSync(path) 同步的
读目录fs.readdir(path, cb)fs.readdirSync(path)
创建目录fs.mkdir(path, cb)fs.mkdirSync(path)
删除文件fs.unlink(path, cb)fs.unlinkSync(path)
重命名/移动fs.rename(oldPath, newPath, cb)fs.renameSync(oldPath, newPath)
文件信息fs.stat(path, cb)fs.statSync(path)

3. 示例详解

1)读取文件内容

异步方式:

fs.readFile('secret.txt', 'utf8', (err, data) => {if (err) return console.error('读取失败:', err);console.log('内容是:', data);
});

同步方式(调试时很好用):

const data = fs.readFileSync('secret.txt', 'utf8');
console.log('内容是:', data);

2)写入/覆盖文件

fs.writeFileSync('output.txt', '保存一些加密参数...');

3)追加写入(如日志)

fs.appendFileSync('log.txt', `[${new Date()}] 请求参数: ${param}\n`);

4)判断文件是否存在

if (fs.existsSync('result.json')) {console.log('已有缓存文件,可直接读取');
}

5)遍历目录中所有文件(递归)

function walk(dir) {const files = fs.readdirSync(dir);for (const file of files) {const fullPath = dir + '/' + file;const stat = fs.statSync(fullPath);if (stat.isDirectory()) {walk(fullPath);} else {console.log('发现文件:', fullPath);}}
}walk('./src');

4. 在逆向/爬虫中的实际用途

场景使用方式
保存爬虫抓取的数据fs.writeFileSync('data.json', JSON.stringify(res))
保存 cookie / headersfs.writeFileSync('cookie.txt', cookieString)
记录日志 / 错误fs.appendFileSync('log.txt', error.stack)
修改已打包 JS 文件读取 app.asar 里的 main.js 后用正则或 AST 修改后再写回
将 hook 到的函数参数保存下来在 hook 逻辑里 appendFileSync() 输出

5. 注意事项

  • 文件路径建议使用 path.join() 而不是硬编码 './a/b.txt',防止跨平台路径问题(Windows 用反斜杠)

  • 写文件前可判断目录是否存在:

if (!fs.existsSync('./logs')) fs.mkdirSync('./logs');
  • 异步操作都带回调;要用 Promise 化的版本建议使用 fs/promises
const fs = require('fs/promises');await fs.writeFile('a.txt', 'hello');

总结

模块功能
fs.readFileSync()读取文件内容
fs.writeFileSync()写入(覆盖)内容
fs.appendFileSync()追加写入
fs.readdirSync()读取目录下的所有文件
fs.statSync()获取文件大小、类型等信息
fs.existsSync()判断文件/文件夹是否存在

三、http 模块

Node.js 的 http 模块是用来创建 Web 服务和发送 HTTP 请求的内置模块,无需安装。

功能包含:

类别常用功能
服务端启动一个 HTTP 服务器,监听端口、处理请求
客户端向目标地址发送 GET / POST 等请求

Node 的 http 模块是底层 API,不像 axios / fetch 那么简洁,但可以完全控制请求头、数据结构,适合底层调试与逆向用途。

1. http 服务端:构建本地 HTTP 服务器

这是最常见的用途,比如写一个本地服务,监听请求、打印参数、调试 JS。

示例:创建一个本地服务器

const http = require('http');const server = http.createServer((req, res) => {console.log('收到请求:', req.method, req.url);// 接收数据let body = '';req.on('data', chunk => body += chunk);req.on('end', () => {console.log('请求体:', body);res.writeHead(200, { 'Content-Type': 'application/json' });res.end(JSON.stringify({ status: 'ok', msg: '已收到' }));});
});server.listen(3000, () => {console.log('服务器运行在 http://localhost:3000');
});

用途:

  • 在调试前端 JS 加密时,你可以把它改成一个假接口,接收参数打印出来

  • 在模拟客户端请求时,观察 JS 发送的 headers、payload、cookie

  • 在本地模拟行为验证服务器(如极验的行为验证请求)

2. http 客户端:发送 HTTP 请求

http.request() 是 Node 最底层的发请求方法,适合精细控制 headers、加密数据包。

示例:发送 GET 请求

const http = require('http');const options = {hostname: 'example.com',port: 80,path: '/api/data',method: 'GET',headers: {'User-Agent': 'NodeReverse/1.0',}
};const req = http.request(options, res => {let data = '';res.on('data', chunk => data += chunk);res.on('end', () => {console.log('响应结果:', data);});
});req.on('error', err => {console.error('请求失败:', err);
});req.end();

示例:发送 POST 请求(传递 JSON 数据)

const postData = JSON.stringify({ username: 'test', password: '123' });const options = {hostname: 'example.com',port: 80,path: '/api/login',method: 'POST',headers: {'Content-Type': 'application/json','Content-Length': Buffer.byteLength(postData),}
};const req = http.request(options, res => {let data = '';res.on('data', chunk => data += chunk);res.on('end', () => {console.log('登录响应:', data);});
});req.write(postData); // 写入请求体
req.end();

3. 在爬虫/逆向中的实战用途

场景用法
 监听前端请求参数本地搭建 server 打印 JS 发出的请求
 模拟滑动/行为验证的接口建本地服务模拟验证码验证流程
 模拟客户端请求自定义 headers/cookie/加密参数
 创建中间人代理拦截原始请求/响应内容用于分析(比如 hook 极验行为参数)
 本地调试 JS 文件请求前端访问你的 http://127.0.0.1/mock.js,返回伪造 JS

4. http vs axios 对比

特点httpaxios
是否内置 Node 内置模块 需额外安装
是否支持 Promise 不支持 原生支持
用法复杂度底层、繁琐简洁、方便
灵活性控制一切细节(如 TCP 层)封装好,调试不方便

所以在 底层逆向、调试请求细节(cookie、加密数据包) 时建议用 http,而普通 API 爬虫用 axios 更方便。

5. 基于 http 构建代理服务器

可以使用 http.createServer() + http.request() 构建一个转发代理。

简单版本:

// 接收请求 -> 修改参数 -> 发出新请求 -> 返回响应
http.createServer((req, res) => {const newReq = http.request({hostname: '真实服务器地址',path: req.url,method: req.method,headers: req.headers,}, realRes => {realRes.pipe(res);});req.pipe(newReq);
}).listen(8000);

用途:

  • 中间人分析原始请求

  • 实时 hook 某个 cookie / 参数

  • 拦截极验验证发出的请求,替换掉 w 值再发出

总结

方法功能
http.createServer()创建 HTTP 服务器
http.request()发送 HTTP 请求(底层控制)
res.writeHead()设置返回状态码与 header
req.on('data')获取请求体内容(用于 POST)
res.end()响应客户端请求

四、process 模块

process 是 Node.js 的全局对象,不需要 require(),可以直接使用。

它是对当前运行中的 Node 进程的抽象,可以让你:

功能示例用途
获取命令行参数分析 CLI 参数,支持传参运行
获取环境变量判断运行环境、账号密码等配置
控制进程退出脚本出错时终止运行
捕获异常和退出信号做异常日志记录
获取内存使用情况检查内存泄漏/性能问题
切换工作目录动态切换执行路径

1. 常用功能详解

1)获取命令行参数(process.argv

node app.js --url=https://test.com
console.log(process.argv);
// 输出示例: [ 'node', '/path/app.js', '--url=https://test.com' ]

可以用来做命令行脚本参数解析,比如自动化逆向:

const args = process.argv.slice(2); // 取参数部分
const urlArg = args.find(x => x.startsWith('--url='));
const url = urlArg ? urlArg.split('=')[1] : null;

2)获取环境变量(process.env

console.log(process.env.NODE_ENV); // 'development' or 'production'

在开发时通常会用 .env 文件配合,做自动配置切换:

NODE_ENV=production node app.js
if (process.env.NODE_ENV === 'production') {console.log('生产环境逻辑');
}

在安全逆向时,也可以用来控制不同设备、账号、token 的切换。

3)控制程序退出(process.exit()

if (!url) {console.error('缺少 URL 参数');process.exit(1); // 返回非 0 表示异常退出
}

process.exit(0) 表示正常退出
process.exit(1) 表示有错误退出

适用于:

  • 参数错误就终止脚本

  • 抓不到数据就退出

  • 自动化测试流程中

4)捕获异常(process.on('uncaughtException')

process.on('uncaughtException', err => {console.error('发生未捕获错误:', err);fs.appendFileSync('error.log', err.stack);
});

适合在逆向调试时保底捕获错误日志,防止程序直接崩溃。

5)获取当前工作目录(process.cwd()

console.log(process.cwd()); // /home/user/project

配合 fs 读取相对路径很有用:

const filePath = path.join(process.cwd(), 'data', 'config.json');

6)修改当前工作目录(process.chdir()

process.chdir('/tmp');

在脚本执行前切换路径,或者做类似 cd 的效果。

7)获取内存占用(process.memoryUsage()

console.log(process.memoryUsage());

输出:

{rss: 4935680,heapTotal: 1826816,heapUsed: 650472,external: 49879
}

适合分析 Node 服务是否存在内存泄漏(如 puppeteer 没关闭、死循环等)

2. 实战场景应用

场景用法
 参数传递调试脚本node decrypt.js --key=abc123
 切换环境变量运行process.env.NODE_ENV === 'dev'
 错误日志保存捕获异常后写入 error.log
 多账户批量登录process.argv 动态传账号密码列表
 获取相对路径fs.readFileSync(path.join(process.cwd(), 'xxx'))
 CLI 工具封装包装你写的爬虫脚本变成命令行工具(支持参数)

3. 实战示例:批量解密脚本

命令:

node decrypt.js --input=enc.txt --key=abc123

代码片段:

const fs = require('fs');
const path = require('path');const args = process.argv.slice(2);
const inputFile = args.find(x => x.startsWith('--input=')).split('=')[1];
const key = args.find(x => x.startsWith('--key=')).split('=')[1];if (!inputFile || !key) {console.error('缺少参数 --input / --key');process.exit(1);
}const content = fs.readFileSync(path.join(process.cwd(), inputFile), 'utf8');
// 这里进行解密...
console.log(`使用密钥 ${key} 解密成功`);

总结:process 模块核心 API

方法 / 属性作用
process.argv获取命令行参数数组
process.env获取环境变量对象
process.exit(code)终止程序(非0代表异常)
process.on('event', cb)监听进程事件(如异常、退出)
process.cwd()当前工作目录
process.chdir(dir)改变当前目录
process.memoryUsage()获取内存使用情况

五、使用 puppeteer / playwright 实现自动化爬虫

Puppeteer / Playwright 这两个工具都是用来控制浏览器自动化操作的工具

名称背景特点
PuppeteerGoogle 出品控制 Chromium,功能成熟,适合网页截图、PDF、调试逆向
Playwright微软出品支持 Chromium、Firefox、WebKit,多浏览器自动化更强大,更适合模拟人类操作

简单说:

  • Puppeteer 适合单页调试、网页 JS 参数逆向

  • Playwright 适合行为模拟、滑块验证码、设备模拟

1. 安装和环境准备

使用 Node.js 环境:

安装 Puppeteer:

npm install puppeteer

安装 Playwright:

npm install playwright
npx playwright install

Playwright 会自动安装 Chromium、Firefox、WebKit 等浏览器内核。

2. 核心功能

功能Puppeteer / Playwright 都能做
 打开网页page.goto()
 模拟点击page.click()
 输入内容page.type()
 获取元素内容page.$eval()
 执行 JSpage.evaluate()
 截图、PDFpage.screenshot()
 拦截请求page.on('request', ...)
 设置 Cookie / UA / Headerspage.setUserAgent()
 控制多页、多标签页browser.newPage()

3. Puppeteer 示例(核心 API)

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch({ headless: false }); // 非 headless 方便调试const page = await browser.newPage();await page.goto('https://example.com');// 获取元素文本const title = await page.$eval('h1', el => el.innerText);console.log('标题:', title);// 模拟输入和点击await page.type('#username', 'test');await page.type('#password', '123456');await page.click('#login');// 拦截请求page.on('request', req => {console.log('请求地址:', req.url());});// 等待页面加载完成await page.waitForTimeout(3000);await browser.close();
})();

4. Playwright 示例(行为模拟更强)

const { chromium } = require('playwright');(async () => {const browser = await chromium.launch({ headless: false });const page = await browser.newPage();await page.goto('https://example.com');// 模拟滑块滑动const slider = await page.$('#slider');const box = await slider.boundingBox();await page.mouse.move(box.x + 10, box.y + box.height / 2);await page.mouse.down();await page.mouse.move(box.x + 200, box.y + box.height / 2, { steps: 30 });await page.mouse.up();await page.screenshot({ path: 'page.png' });await browser.close();
})();

Playwright 能控制真实鼠标移动,适合破解行为识别、极验、滑块等场景。

5. 实战用途

场景用法
 动态网页加载(JS 渲染)打开页面 + page.content() 获取完整 HTML
 参数加密流程分析page.on('request') 抓取发送请求参数(观察 w、sign 等)
 极验滑块破解模拟鼠标移动 + canvas 获取轨迹
 Hook JS 函数page.evaluate 注入函数替换(如 hook encrypt())
 分析行为验证获取 JS 执行后生成的 token / trace 参数
 绕过 WebSocket 加密监听 WS 发送数据(适配 sekiro 等场景)
 调试前端 JS 模块使用控制台调试加密 JS 脚本流程

6. 逆向技巧实战:hook JS 函数

可以用 page.evaluateOnNewDocument() 来劫持 JS 函数:

await page.evaluateOnNewDocument(() => {const originalEncrypt = window.encrypt;window.encrypt = function (...args) {console.log('调用 encrypt 参数:', args);return originalEncrypt.apply(this, args);}
});

这样可以在页面加载之前注入 Hook,非常适合调试混淆函数、密钥生成函数、行为参数构造函数

7. 使用 puppeteer 拿动态加密参数(完整流程)

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();// 打开页面await page.goto('https://xxx.com');// 模拟输入和点击登录await page.type('#username', 'test');await page.type('#password', '123456');await page.click('#login');// 拦截登录请求并查看加密参数page.on('request', req => {if (req.url().includes('/api/login')) {console.log('登录请求发出,参数:', req.postData());}});await page.waitForTimeout(5000);await browser.close();
})();

总结对比

功能PuppeteerPlaywright
支持浏览器ChromiumChromium、Firefox、WebKit
跨平台稳定性较强更强
鼠标/键盘模拟一般精准、支持人类行为模拟
多页面控制支持更方便
社区支持成熟活跃、更新快
是否推荐还行更强大

六、node-hook

node-hook 是一个可以拦截 require() 加载过程的模块。可以在模块被引入前,动态修改它的源码注入自定义代码。 

非常适用于 hook 掉某个 Node.js 模块,在加载时修改源码或替换功能逻辑。

比如可以:

  • hook 掉 crypto 模块,打印所有加密参数

  • hook 掉某个自定义模块,替换为 mock 实现

  • hook 掉混淆代码模块,在加载时插入 console.log

安装

npm install node-hook

核心原理

在 Node.js 中,.js 文件通过 Module._extensions['.js'] 加载。

node-hook 就是通过劫持这个加载流程,在模块加载前修改源码,像下面这样:

require('node-hook').hook('.js', (source, filename) => {console.log('[HOOK]', filename);return modifiedSourceCode;
});

1. 核心 API 用法

1)基础 hook

const hook = require('node-hook');hook.hook('.js', function (source, filename) {if (filename.includes('target-module.js')) {// 在模块加载前,插入调试日志source = "console.log('hooked!');\n" + source;}return source;
});

2)hook 指定模块

hook.hook('js', (source, filename) => {if (filename.includes('encrypt.js')) {source = source.replace('function encrypt', 'function encrypt_hooked');}return source;
});

2. 实战:hook 加密模块分析参数

假设有一个模块叫 encrypt.js

// encrypt.js
function encrypt(data) {return data.split('').reverse().join('');
}
module.exports = encrypt;

想看看谁调用了它,以及传了什么参数。

hook 分析:

const hook = require('node-hook');hook.hook('.js', (source, filename) => {if (filename.endsWith('encrypt.js')) {source = `console.log('[HOOKED] 加密函数被调用');${source.replace('function encrypt','function encrypt(data) { console.log("参数:", data); ')}`;}return source;
});// 调用真实代码
const encrypt = require('./encrypt');
encrypt('abc123');

输出:

[HOOKED] 加密函数被调用
参数: abc123

3. 配合 vm2 使用:沙箱调试第三方加密代码

有些混淆代码不想直接执行,可以使用 vm2 加上 node-hook

const { NodeVM } = require('vm2');
const hook = require('node-hook');hook.hook('.js', (source, filename) => {if (filename.includes('secret.js')) {// 劫持加密函数return source.replace('encrypt(', 'hooked_encrypt(');}return source;
});const vm = new NodeVM({require: {external: true,context: 'sandbox'}
});vm.run(`require('./secret')`, __dirname);

4. 高级玩法:用 fake 模块替代真实模块

有时候想直接用假的模块来替换真实模块,比如替换掉 axios

const hook = require('node-hook');// 替换 axios
hook.hook('.js', (source, filename) => {if (filename.endsWith('axios/index.js')) {return `module.exports = {get(url) { console.log("拦截 GET:", url); return Promise.resolve({ data: 'fake-data' }); },post() {}};`;}return source;
});

适合绕过外部请求、分析数据结构、脱离真实环境调试。

5. 常见应用场景

目标用法
 调试混淆加密模块插入 log,观察传参与返回值
 替换模块实现模拟外部模块、伪造返回值
 分析依赖模块调用链打印 require 加载路径
 沙箱执行 + hookvm2 搭配,做静态分析或安全隔离
 自动打包分析在 Electron、webpack 项目中动态插桩分析模块逻辑

总结

特性说明
 模块加载前拦截拦截所有 .js 文件加载流程
 修改源码注入可注入 log、替换函数、插入 hook
 支持条件拦截按文件路径、模块名判断是否 hook
 配合 vm2用于 JS 沙箱安全执行
 适合逆向快速分析混淆模块、嵌套依赖模块行为

七、vm2 用于 hook 模块

vm2 是一个基于 Node.js 原生 vm 模块的封装库,用于:

  •  在沙箱中安全运行 JS 代码

  •  控制 JS 脚本能访问什么模块和对象

  •  分析或执行第三方混淆代码而不污染主环境

  •  配合 node-hook 拦截模块源码,实现更强的 hook 调试

它解决了原生 vm 沙箱“容易逃逸”的问题,是做 JS 逆向非常重要的一环。

安装

npm install vm2

1. 基本用法:安全执行 JS 代码

const { VM } = require('vm2');const vm = new VM({sandbox: {console,test: 123}
});vm.run(`console.log("test =", test);  // 输出:test = 123
`);

可以在 sandbox 中定义允许访问的全局变量。沙箱外的所有变量默认是不可访问的。

2. NodeVM 用于 require 模块

NodeVMvm2 提供的增强型沙箱,支持:

  • require() 外部模块(可配置是否允许)

  • 模拟 Node.js 环境(带模块系统)

  • 可以 hook 模块加载过程(配合 node-hook

示例:

const { NodeVM } = require('vm2');const vm = new NodeVM({console: 'inherit',sandbox: {},require: {external: true,       // 允许加载外部模块builtin: ['fs', 'crypto'],root: "./",           // 限定模块搜索路径}
});vm.run(`const crypto = require('crypto');console.log("md5 =", crypto.createHash('md5').update("abc").digest('hex'));
`);

可以用它加载并执行整个 encrypt.js 模块,而不会污染主进程上下文

3. 实战场景:逆向混淆代码(脱离主进程执行)

假设有一段混淆代码:

// encrypt.js
function getToken(a, b) {return a.split('').reverse().join('') + b;
}
module.exports = getToken;

NodeVM 来安全加载并调用:

const { NodeVM } = require('vm2');
const path = require('path');const vm = new NodeVM({console: 'inherit',sandbox: {},require: {external: true,root: __dirname}
});const getToken = vm.run(`module.exports = require('./encrypt');`, __dirname);
console.log(getToken('abc', '123'));  // 输出:cba123

这个过程中 encrypt.js 是在沙箱中运行的,可以随时对其源码进行 hook 替换。

4. 配合 node-hook 实现模块 hook + 沙箱执行

我们可以在模块加载前插入 log:

const hook = require('node-hook');
const { NodeVM } = require('vm2');hook.hook('.js', (source, filename) => {if (filename.includes('encrypt.js')) {return `console.log('[HOOK] 调用了 getToken');${source}`;}return source;
});const vm = new NodeVM({console: 'inherit',require: {external: true,root: './'}
});vm.run(`module.exports = require('./encrypt');`, __dirname);

实现:模块还没执行前,就能插入 log 或替换函数。

5. 典型用途(逆向工程)

场景用法
 运行混淆 JS 模块把目标模块放进沙箱执行,防止污染主程序
 hook 模块函数逻辑配合 node-hook 替换敏感函数(如加密函数)
 分析模块间调用关系在 require 时打印加载路径和依赖结构
 分析 Electron 打包代码把 Electron 的主进程 JS 文件拿来在沙箱里运行
 跑非信任代码执行爬虫目标站点提供的 JS 参数生成器而不怕执行恶意代码

6. 实战模板(沙箱执行 + hook + 参数打印)

完整模板:

const hook = require('node-hook');
const { NodeVM } = require('vm2');
const path = require('path');// 1. hook 加密模块,插入打印
hook.hook('.js', (source, filename) => {if (filename.includes('encrypt.js')) {return source.replace('function getToken',`function getToken(...args) { console.log('[HOOK]', args); `);}return source;
});// 2. 构建 NodeVM 沙箱
const vm = new NodeVM({console: 'inherit',sandbox: {},require: {external: true,root: __dirname}
});// 3. 在沙箱中运行加密模块
const encrypt = vm.run(`module.exports = require('./encrypt');`, __dirname);// 4. 调用函数观察行为
encrypt('abc123', 'XyZ');

输出结果:

[HOOK] [ 'abc123', 'XyZ' ]

总结

能力vm2
安全执行 JS可以
沙箱隔离环境可以
模拟 require可以(NodeVM)
控制模块权限可以
hook 模块函数可以(配合 node-hook)
执行混淆代码可以
防止逃逸攻击可以(比原生 vm 更安全)

八、沙箱模拟执行

沙箱模拟执行指的是在一个受限环境中运行 JavaScript 代码,确保它:

  • 不会访问本地文件系统、网络、进程等敏感资源

  • 不会污染全局环境

  • 能被动态 hook、插入打印、调试参数

它是分析第三方加密模块、运行不可信代码时的安全保障。

1. 为何要沙箱模拟执行?

场景 1:混淆 JS 函数逆向

例如遇到某站点使用 encrypt.js 生成签名参数,源代码非常复杂、混淆严重:

function x1(_0xabc123, key) {// 复杂逻辑...
}

我们可以:

  • 不理解它所有逻辑

  • 但可以在沙箱中跑它,观察输入输出、hook 内部函数

场景 2:避免执行恶意代码

  • 某些脚本可能访问你的磁盘、发送网络请求、执行 Shell 命令

  • 放进沙箱,阻止这些操作,只分析逻辑结构

2. 如何使用 vm2 搭建沙箱环境

1)基础沙箱:运行字符串代码

const { VM } = require('vm2');const vm = new VM({sandbox: { a: 5, b: 3 }
});const result = vm.run(`a + b`);
console.log(result);  // 输出:8

此处 a + b 在沙箱中执行,外部无法访问内部变量,反之亦然。

2)NodeVM:运行模块代码(重点)

const { NodeVM } = require('vm2');const vm = new NodeVM({console: 'inherit',sandbox: {},require: {external: true,builtin: ['crypto'],root: "./",}
});const result = vm.run(`module.exports = function(data) {const crypto = require('crypto');return crypto.createHash('md5').update(data).digest('hex');};
`, __dirname);console.log(result('abc'));  // md5 输出

可以沙箱加载一个文件、函数,像真正模块一样调用。

3. 实战:沙箱模拟执行混淆模块

目标模块:encrypt.js(混淆代码)

// encrypt.js
function genToken(uid) {return uid.split('').reverse().join('') + "_abc";
}
module.exports = genToken;

我们不想污染主进程,就放进沙箱里执行:

const { NodeVM } = require('vm2');const vm = new NodeVM({console: 'inherit',require: {external: true,root: __dirname}
});// 沙箱内加载 encrypt 模块
const genToken = vm.run(`module.exports = require('./encrypt');`, __dirname);
console.log(genToken('user123'));  // 输出:321resu_abc

沙箱执行结果和真实一样,但更加安全、可控。

4. 与 node-hook 联合使用

我们可以配合 node-hook 实现动态 hook:

const hook = require('node-hook');
const { NodeVM } = require('vm2');hook.hook('.js', (source, filename) => {if (filename.includes('encrypt.js')) {return `console.log('[HOOK] genToken 被调用');${source.replace('function genToken', 'function genToken(...args) { console.log("参数:", args);')}`;}return source;
});const vm = new NodeVM({console: 'inherit',require: {external: true,root: __dirname}
});const genToken = vm.run(`module.exports = require('./encrypt');`, __dirname);
genToken('abc123');

输出:

[HOOK] genToken 被调用
参数: [ 'abc123' ]

5. 分析真实加密模块流程

适用于以下逆向任务:

项目用法
极验、滑动验证码把 JS 加密代码扔进沙箱执行,hook w 参数生成
Electron 项目分析 main.js 入口模块的行为
JS加密项目hook 所有函数、插入 log、打印参数
自动化测试 JS 模块拿目标模块脱离环境执行验证正确性

6. 额外技巧

设置沙箱 console 为 inherit

console: 'inherit'

可以把沙箱中的 console.log 输出同步到主进程控制台。

限制 require 权限

require: {external: true,builtin: ['fs', 'crypto'],root: __dirname
}

防止恶意代码 require('child_process') 去执行 shell 命令。

捕获异常防止崩溃

try {vm.run(code);
} catch (e) {console.log("沙箱执行错误:", e.message);
}

总结

能力是否支持
沙箱运行 JS 代码
安全执行混淆模块
控制 require 模块
配合 hook 修改代码
捕获 console / 参数
分析混淆函数输入输出
防止主进程被污染或攻击

九、electron 项目逆向

Electron 是一个跨平台的桌面应用框架,本质上就是:

Node.js + Chromium + HTML/JS 前端页面

可以理解为一个浏览器壳 + Node.js 脚本。很多主流软件(如微信PC、钉钉、VS Code)都是 Electron 写的。

逆向 Electron 项目目标:

目标举例
获取打包前 JS 源码解包后恢复源码进行分析
获取核心逻辑找到登录加密、通信接口等
绕过客户端验证破解授权、本地签名校验
做爬虫 / 自动化拿到核心接口加密流程
安全研究查找硬编码 token、配置等敏感信息

1. Electron 应用结构

大多数 Electron 应用的目录结构如下(安装目录或 asar 包内):

app/
├── main.js             // 主进程入口(Node.js)
├── preload.js          // 注入渲染进程的桥梁
├── renderer/           // 渲染进程(前端页面)
│   ├── index.html
│   └── app.js
├── node_modules/       // 第三方依赖
├── package.json        // 描述整个 App
└── ...

主进程的 JS 就是我们逆向的重点。

2. 逆向核心步骤

步骤 1:获取资源(解包)

多数 Electron 应用都打包成了 .asar 文件:

app.asar

解包工具:

npm install -g asarasar extract app.asar output_folder

得到完整源码结构后,我们就可以进行下一步分析。

步骤 2:分析 main.js 主进程

main.js 是 Electron 启动时执行的主文件,类似于 Node.js 的入口。

看点:

  • 创建窗口的逻辑

  • 本地资源加载路径

  • preload 脚本路径

  • 是否有硬编码 token、接口地址、加密参数

const { app, BrowserWindow } = require('electron');function createWindow() {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js'),nodeIntegration: false,contextIsolation: true}});win.loadURL('https://example.com');
}

步骤 3:分析 preload.js(桥梁代码)

preload.js 是连接主进程和前端 JS 的桥梁,可以注入全局函数到页面中。

常见 hook 点:

contextBridge.exposeInMainWorld('myAPI', {encrypt(data) {return crypto.encrypt(data);}
});

我们可以:

  • hook 这个 API(用 node-hook 替换)

  • 或在页面层分析 window.myAPI.encrypt() 的调用参数

步骤 4:分析渲染层 JS(前端逻辑)

这部分 JS 通常会包含:

  • 页面交互逻辑

  • 登录、注册表单提交

  • 各类参数拼接、加密调用

如果看到这些代码被混淆了:

!function(a){var b=function(c){...}(window);

可以使用工具还原:

  • js-beautify 美化

  • Babel AST 解混淆

  • SourceMap 查源码(如果未移除)

3. 常用技巧与 hook 手段

1)打印主进程参数

// 替换 main.js 内容,加一行打印
console.log("[HOOK] app launched");app.on('ready', () => {console.log("[HOOK] 创建窗口!");
});

2)注入渲染进程 hook(页面层)

preload.js 添加全局监听:

window.addEventListener('DOMContentLoaded', () => {console.log('[HOOK] 页面已加载');
});

或注入 API:

window.myAPI.encrypt = function(data) {console.log('[HOOK] 加密参数:', data);return 'fake_result';
}

4. 实战逆向:提取登录加密参数

很多软件(如 Electron 版聊天软件)在登录时会调用加密函数:

window.encrypt('用户名+密码')  =>  加密串fetch('https://api.xxx.com/login', {method: 'POST',body: {data: 加密串}
});

可以:

  1. 解包 asar

  2. 找到 preload.js 和前端 js

  3. node-hookvm2 sandbox 执行加密模块

  4. 打印调用栈、参数、还原加密算法

5. 辅助工具推荐

工具用途
asar解包 Electron 应用
js-beautify美化混淆代码
vm2沙箱执行模块
node-hook动态插桩打印
Chrome DevTools调试渲染进程页面
electron-devtools-installer安装调试插件
frida/electron-inject动态分析运行时数据(高阶)

6. 逆向流程小结

1. 解包 asar 文件,获取源码
2. 分析 main.js 入口逻辑,识别 preload.js
3. 查看 preload 里是否 expose 函数给页面
4. 分析页面 js 中的调用链
5. 还原加密函数(用 vm2 + node-hook)
6. 打印输入输出,实现模拟调用或替换

十、打包 JS 分析

在实际项目中,前端代码一般不会以原始形式暴露,而是经过打包压缩,常见工具有:

工具作用
Webpack模块打包(ES6 import/export → bundle)
Rollup更适合库打包
Vite现代化打包工具(ESM支持)
esbuild极快的打包压缩
UglifyJS / Terser混淆、压缩

目的是:

  • 减小体积

  • 加速加载

  • 防止源码泄露

1、逆向难点

打包后的 JS 文件一般有如下特点:

1)文件名混淆

/assets/abc123.chunk.js
/app.min.js
/main.[hash].js

2)变量名混淆

var a = "xx";
function b(c) {return d(c + a);
}

3)函数结构扁平化 / IIFE 包裹

!function(){...}(); // 立即执行函数

4)模块包裹结构(如 Webpack)

(()=> {var __webpack_modules__ = {123: function(module, exports) { ... }};__webpack_require__(123);
})();

2. 打包 JS 的分析目标

目标方法
找到核心函数搜索关键函数 / 输入参数调用链
恢复源码结构使用还原工具(AST / sourcemap)
模拟加密流程提取关键逻辑并重写执行
插桩调试hook、打印、沙箱执行
解混淆还原变量名、结构优化

3. 常用工具链

1)美化工具

  • js-beautify

  • prettier

  • de4js(可视化)

js-beautify app.min.js -o app.beauty.js

2)AST 工具分析器

  • Babel Parser

  • @babel/traverse

  • @babel/generator

  • acorn, esprima

可以用它来:

  • 还原混淆函数

  • 替换函数名

  • 还原字符串加密

示例:提取所有字符串常量

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;const code = `var a = "secret";`;const ast = parser.parse(code);traverse(ast, {StringLiteral(path) {console.log("字符串:", path.node.value);}
});

3)source map 还原(若未删除)

如果网站保留了 .map 文件,例如:

https://xxx.com/app.min.js.map

可以:

  • 下载 .map

  • source-map-visualization 还原函数名

4)模块结构识别(如 Webpack)

Webpack 打包后的结构通常是:

(function(modules) {// Webpack runtimereturn __webpack_require__(0);
})([ function(module, exports) {// 模块 0 的代码
}, function(...) {...} ]);

可以用 webpack-bundle-analyzer 或写脚本提取每个模块:

Object.keys(__webpack_modules__).forEach(k => {console.log(k, __webpack_modules__[k].toString());
});

4. 手动逆向打包 JS 的实战流程

假设我们要逆向一个加密函数 gen_w(data),文件是 main.min.js

步骤 1:格式化

js-beautify main.min.js > main.js

步骤 2:搜索函数名或接口关键字

例如搜索:

  • gen_w

  • sign

  • fetch(...)

  • XMLHttpRequest

  • .toString().slice(...)

通过参数依赖、接口调用追踪定位函数。

步骤 3:用 AST 重写或提取

比如找到了:

function gen_w(data) {var b = a(data);return b + "_xyz";
}

可以使用 @babel/parser 提取 a() 的依赖,再用 vm2 沙箱执行整段代码:

const { VM } = require('vm2');
const fs = require('fs');const code = fs.readFileSync('./gen_w.js', 'utf8');const vm = new VM();
const result = vm.run(code + '\ngen_w("abc")');console.log(result);

步骤 4:hook 并插桩打印关键参数

gen_w = function(data) {console.log("hook: 参数 =", data);return "fake_w";
}

步骤 5:还原模块名

如 Webpack 中 t(123) 表示调用模块,可以还原模块 ID 与源码对应:

const modules = __webpack_modules__;
Object.entries(modules).forEach(([id, fn]) => {console.log("模块 ID:", id);console.log(fn.toString());
});

5. 如何快速定位目标函数?

  1. 抓包接口,找到关键参数(如 w、sign、token)

  2. 全局搜索该参数值出现场景(如 body.data = w

  3. 向上追溯调用链,找到定义函数(如 gen_w()

  4. 分析函数依赖链(用 AST、格式化工具)

  5. 沙箱执行还原函数

总结

操作工具 / 方法
格式化压缩代码js-beautify, prettier
AST 分析@babel/parser, traverse
模块还原自写脚本、webpack runtime 还原
逆向执行vm2, node-hook, 控制台打印
解混淆手动替换变量名、字符串还原
找函数抓包 + 搜索关键字符串或接口
还原源码结构SourceMap、bundle-analyzer

相关文章:

关于 js:9. Node.js 后端相关

一、Node 环境搭建与执行流程 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它让 JS 不再局限于浏览器内,而是可以在服务器、终端、本地脚本中运行。 核心定位:让我们可以用 JS 写本地程序、脚本、爬虫、加密逻辑、hook 工具、…...

More Effective C++:改善编程与设计(上)

More Effective C: 目录 More Effective C: 条款1:仔细区别pointers和 references 条款2:最好使用C转型操作符 条款3:绝对不要以多态方式处理数组 条款4:非必要不要提供default constructor 条款5:对定制的“类型转换函数”保持警觉 …...

SCDN如何有效防护网站免受CC攻击?——安全加速网络的实战解析

在互联网安全威胁日益复杂化的今天,CC(Challenge Collapsar)攻击已成为网站运营者面临的主要挑战之一。这种攻击通过模拟大量合法用户请求,消耗服务器资源,导致正常用户无法访问。而**安全内容分发网络(SCD…...

关于并发编程AQS的学习

目录 1. AQS的核心作用 2. AQS的核心结构 3. 关键方法 4. AQS的应用示例 4.1、ReentrantLock的实现 4.2、CountDownLatch的实现 5. AQS的优势 6. 对比其他同步机制 前言 AQS(AbstractQueuedSynchronizer) 是Java并发编程中一个核心的同步器框架…...

16S18S基础知识(1)

相关内容: https://blog.csdn.net/weixin_34315189/article/details/86397125?fromshareblogdetail&sharetypeblogdetail&sharerId86397125&sharereferPC&sharesource2302_80012625&sharefromfrom_link https://metagenome.blog.csdn.net/art…...

Java Spring Boot 控制器中处理用户数据详解

目录 一、获取请求参数1.1 获取查询参数1.2 获取路径参数 二、处理表单提交2.1 处理表单数据 三、处理 JSON 数据3.1 接收 JSON 数据 四、返回 JSON 数据五、处理文件上传5.1 单文件上传5.2 多文件上传 六、总结 在 Spring Boot 应用开发中,控制器(Contr…...

AI产品上市前的“安全通行证“

首席数据官高鹏律师团队 如今AI 产品如雨后春笋般涌现,从智能音箱到自动驾驶汽车,从语音助手到医疗诊断软件,它们正全方位渗透进我们的生活。然而,在 AI 产品迈向市场、走进千家万户之前,有一系列强制性安全认证如同坚…...

sql server 2019 将单用户状态修改为多用户状态

记录两种将单用户状态修改为多用户状态,我曾经成功过的方法,供参考 第一种方法 USE master; GO -- 终止所有活动连接 DECLARE kill_connections NVARCHAR(MAX) ; SELECT kill_connections KILL CAST(session_id AS NVARCHAR(10)) ; FROM sys.dm_ex…...

[滑动窗口]越短越合法(可转化成越长越合法)

题目链接 题意 给你一个整数数组 nums 和一个整数 k ,请你返回子数组内所有元素的乘积严格小于k 的连续子数组的数目。 首先当ans增加时 我们认为r固定 方法一、转化成越长越合法 思路 算出乘积 ≥ k \ge k ≥k的子数组数量 再用所有子数组数量减去上面算出来…...

idea中编写spark程序

### 在 IntelliJ IDEA 中配置和编写 Spark 程序 要在 IntelliJ IDEA 中高效地开发 Spark 程序,需要完成一系列必要的环境配置以及项目搭建工作。以下是详细的说明。 --- #### 1. 安装与配置 IntelliJ IDEA 为了确保 IDE 可以支持 Scala 开发,首先需要…...

机器学习入门(一)

机器学习入门(一) 文章目录 机器学习入门(一)一、机器学习分类1.1 监督学习1.2 半监督学习1.3 无监督学习1.4 强化学习 二、scikit-learn工具介绍scikit-learn安装 三、数据集3.1 sklearn玩具数据集介绍3.2 sklearn现实世界数据集…...

力扣每日一题之移动零

题目说明: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 思路分析:我们可以考虑使用双指针来解答该题。双指针分…...

GaiaEx 盖亚:从合规出发,一家新兴交易平台的全球化路径探索

在加密货币交易平台日益激烈的竞争中,监管趋严、安全要求提升、用户体验优化已成为行业发展的三大核心议题。2025年初正式上线的GaiaEx 盖亚交易所,正是在这一市场背景下,以“合规 产品 生态”的多维路径,逐步建立起自身的发展方…...

车载网关--- 职责边界划分与功能解耦设计

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...

EasyRTC嵌入式音视频通信SDK打造带屏IPC全场景实时通信解决方案

一、方案概述​ 在智能安防与物联网快速发展的背景下,带屏IPC(网络摄像机)不仅承担着视频采集与监控的基础功能,还逐渐向多样化交互与智能化方向演进。EasyRTC作为一款强大的实时通信框架,具备低延迟、高稳定性、跨平…...

STM32入门笔记(05):内部高速8Mhz时钟最大时钟可以设置 64 Mhz?如何修改system_stm32f10x.c里面的代码?

6.2 Clocks 最大系统时钟频率 当 STM32F103 系列仅使用内部高速振荡器(HSI,8 MHz)作为时钟源,并通过 PLL 放大时,最大可达 64 MHz。([forum.mikroe.com][1], [keil.com][2]) HSI 被内部除以 2(即 4 M…...

iOS 阅后即焚功能的实现

iOS阅后即焚功能实现步骤 一、功能设计要点 消息类型支持:文本、图片、视频、音频等。销毁触发条件: 接收方首次打开消息后启动倒计时。消息存活时间可配置(如5秒、1分钟)。 安全要求: 端到端加密(E2EE&a…...

二叉树前中后序遍历统一迭代法详解:空标记法与栈操作的艺术

二叉树的 前序、中序、后序 遍历是算法中的经典问题。递归实现简单直观,而迭代法则能更好地理解栈的操作逻辑。前文中(中序,前序与后序)所讲过传统的迭代法需要为每种遍历设计不同的入栈顺序,但 统一迭代法 通过引入 空标记节点&a…...

Spark 集群配置、启动与监控指南

Spark 集群的配置和启动需要几个关键步骤。以下是完整的操作流程,包含配置修改、集群启动、任务提交和常见错误排查方法。 1. 修改 Spark 配置文件 首先需要编辑 Spark 配置文件,设置集群参数: bash # 进入 Spark 配置目录 cd $SPARK_HOM…...

综述:拓扑材料的热磁性质

Adv. Funct. Mater. 2025, 2506631 https://doi.org/10.1002/adfm.202506631 近年来,越来越多的拓扑材料表现出优异的热磁(TM)性能,其显著的双极效应和线性能带带来的高载流子迁移率改善了这种性能。 本文综述了TM输运理论、基于…...

lanqiaoOJ 652:一步之遥 ← 扩展欧几里得定理

【题目来源】 https://www.lanqiao.cn/problems/652/learning/ 【题目背景】 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 【题目描述】 从昏迷中醒来,小明发现自己被关在X星球的废矿车里。矿车停在平直的废弃…...

双目云台摄像机:双摄安防功能全方位

双目云台摄像机是一种具有革命性设计的云台摄像机设备,其核心在于其独特的双摄像头配置。以下是对这种先进安防设备的详细介绍: 一、核心原理 双目云台摄像机的核心原理在于利用两个摄像头从不同角度捕捉同一场景,通过先进的算法计算两个图…...

Linux - 基础指令

目录 linux下基本指令 ls pwd cd touch mkdir rmdir rm man cp mv cat ​more less head tail | 匿名管道 find 指令 which alias grep zip/unzi rz/sz tar 重要的⼏个热键 学习linux操作系统,学习指令是必不可少的 尽管有图形化的linux操作系统供学者学习&am…...

深圳无人机展览即将开始,无人机舵机为什么选择伟创动力

深圳无人机展览即将开始,无人机舵机为什么选择伟创动力 2025年5月23日至25日,伟创动力(Kpower)将携旗下多款高性能舵机及微型驱动系统方案亮相2025国际低空经济与无人系统博览会(深圳无人机展),全面展示其在无人机、机…...

ajax提交form表单数据举例

目录 一、HTML 表单准备二、JavaScript 文件(form.js)三、服务器端处理(Spring Boot 示例)四、运行和测试五、总结在现代 Web 开发中,为了提供更流畅、无需页面刷新的用户体验,AJAX(Asynchronous JavaScript and XML)技术被广泛应用于提交表单数据。本文将通过一个具体…...

IDEA 新建 SpringBoot 项目时,没有高版本 SpringBoot 可选

环境描述 IDEA 2025.1.1JDK17Maven 3.9.9 问题描述 IDEA 新建 SpringBoot 项目时,没有高版本 SpringBoot 可选,可以看到此时的最高版本为 3.0.2: 问题分析 返回上一步,可以发现 Spring Initializr 的服务地址为阿里云&#…...

下载的旧版的jenkins,为什么没有旧版的插件

下载的旧版的jenkins,为什么没有旧版的插件,别急 我的jenkins版本: 然后我去找对应的插件 https://updates.jenkins.io/download/plugins/ 1、Maven Integration plugin: Maven 集成管理插件。 然后点击及下载成功 然后 注意&…...

java连数据库

一、准备工作 ​​安装MySQL数据库​​ 确保已安装MySQL服务器并启动服务 ​​下载JDBC驱动​​ 官方驱动&#xff1a;MySQL Connector/JMaven依赖&#xff1a; <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactI…...

常见排序算法及其java实现

常见排序算法 一、冒泡排序&#xff08;Bubble Sort&#xff09;​二、选择排序&#xff08;Selection Sort&#xff09;​​ ​​三、插入排序&#xff08;Insertion Sort&#xff09;​​四、快速排序&#xff08;Quick Sort&#xff09;​​ ​​五、归并排序&#xff08;Me…...

【Python 算法零基础 2.模拟 ④ 基于矩阵】

目录 基于矩阵 Ⅰ、 2120. 执行所有后缀指令 思路与算法 ① 初始化结果列表 ② 方向映射 ③ 遍历每个起始位置 ④ 记录结果 Ⅱ、1252. 奇数值单元格的数目 思路与算法 ① 初始化矩阵 ② 处理每个操作 ③ 统计奇数元素 Ⅲ、 832. 翻转图像 思路与算法 ① 水平翻转图像 ② 像素值…...

2025年PMP 学习十三 第9章 项目资源管理(9.1,9.2)

2025年PMP 学习十三 第9章 项目资源管理&#xff08;9.1,9.2&#xff09; 序号过程过程组9.1规划资源管理规划9.2估算活动资源规划9.3获取资源执行9.4建设团队执行9.5管理团队执行9.6控制资源监控 文章目录 2025年PMP 学习十三 第9章 项目资源管理&#xff08;9.1,9.2&#xf…...

IEEE802.16 标准介绍

IEEE802.16 标准又称为IEEE Wireless MAN 空中接口标准&#xff0c;对工作于不同频带的无线接入系统空中接口进行了规范。由于它所规定的无线系统覆盖范围在公里量级&#xff0c;因此802.16 系统主要应用于城域网。 根据使用频带高低的不同&#xff0c;802.16 系统可分为应用于…...

Nginx配置与应用案例详解

Nginx 是一款高性能的 HTTP 服务器和反向代理服务器,广泛用于负载均衡、静态资源托管和动态内容转发。以下是对 Nginx 配置的详细解析及常见应用场景案例。 一、Nginx 配置文件结构 Nginx 的配置文件通常位于 /etc/nginx/nginx.conf,包含以下核心模块: 全局块 (Main Contex…...

Hadoop-HDFS-Packet含义及作用

在 HDFS&#xff08;Hadoop Distributed File System&#xff09;中&#xff0c;Packet 是数据读写过程中用于数据传输的基本单位。它是 HDFS 客户端与数据节点&#xff08;DataNode&#xff09;之间进行数据交互时的核心概念&#xff0c;尤其在写入和读取文件时&#xff0c;Pa…...

作业帮Android面试题及参考答案

简单描述 Java 类加载机制 Java 类加载机制是将类的字节码载入 JVM 并生成对应的 Class 对象的过程&#xff0c;主要包括以下几个阶段。 加载是类加载的第一个阶段&#xff0c;通过类的全限定名来获取其字节码流&#xff0c;然后将字节码流解析成方法区中的运行时数据结构&…...

分布式1(cap base理论 锁 事务 幂等性 rpc)

目录 分布式系统介绍 一、定义与概念 二、分布式系统的特点 三、分布式系统面临的挑战 四、分布式系统的常见应用场景 CAP 定理 BASE 理论 BASE理论是如何保证最终一致性的 分布式锁的常见使用场景有哪些&#xff1f; 1. 防止多节点重复操作 2. 资源互斥访问 3. 分…...

如何下载 MySQL 驱动 JAR 包

下载 MySQL 驱动 JAR 包的 4 种方式&#xff1a; 官网下载&#xff1a;从 MySQL 官网 下载对应版本的 ZIP 包Maven&#xff1a;在 pom.xml 添加 mysql-connector-java 依赖Gradle&#xff1a;在 build.gradle 使用 implementation mysql:mysql-connector-java:8.0.x直接下载&a…...

unordered_map和unordered的介绍和使用

目录 unordered系列关联式容器 unordered_map unordered_map的接口说明 unordered_map的定义方式 unordered_map接口的使用 unordered_map的容量 unordered_map的迭代器 unordered_map的元素访问 unordered_map的查询 unordered_map的修改操作 unordered_multimap u…...

【原创】使用阿里云存放一个临时共享的文件

在某些场合&#xff0c;需要临时将一个文件存储到一个可被公网访问的地方&#xff0c;某个服务需要访问一下这个文件。这个文件基本上就是一次寿命&#xff0c;也就是你上传一下&#xff0c;然后被访问一下&#xff0c;这个文件的寿命就结束了。 对于这种需求&#xff0c;自建…...

C++学习细节回顾(汇总二)

一.初始化列表相关 1.初始化顺序受申明顺序影响 2.在必要时可以部分不采用初始化列表&#xff0c;避免受特性1影响 二.非类型模板参数 template< class T , size_t N 10 > 三.特化–特殊化处理 template< class T > bool less(T left , T right) { return left&…...

【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀

文章目录 &#x1f9f3; 访问者模式&#xff08;Visitor Pattern&#xff09;深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码&#xff08;游戏物品系统&#xff09;1. 定义元素与访问者接口2. 实现具体元素类3. 实现具体访问者4. 对象结构管理5. 客户端使用 …...

ubuntu系统安装配置adb工具

获取adb tools 1. 下载最新版&#xff08;替换链接中的版本号&#xff09; wget https://dl.google.com/android/repository/platform-tools-latest-linux.zip2. 解压到当前目录 unzip platform-tools-latest-linux.zip3. 移动文件到系统目录 sudo mv platform-tools /usr/…...

基于Python的量化交易实盘部署与风险管理指南

基于Python的量化交易实盘部署与风险管理指南 一、模拟交易与参数优化 1.1 券商API接入与模拟交易 在量化交易落地前&#xff0c;模拟交易是策略验证的“安全沙箱”&#xff0c;其核心价值在于用零成本环境暴露策略缺陷。以股票市场为例&#xff0c;同花顺与通达信模拟盘接口…...

MySQL 入门大全:数据类型

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

WPF Datagrid 数据加载和性能

这篇文章并非讨论 WPF Datagrid 的性能数据&#xff0c;而只是简单介绍一下为了使其性能良好&#xff0c;你需要注意哪些方面。我不太想使用性能分析器来展示实际数据&#xff0c;而是尽可能地使用了 Stopwatch 类。这篇文章不会深入探讨处理海量数据的技术&#xff0c;例如分页…...

商城小程序源码介绍

今天要为大家介绍一款基于ThinkPHP、FastAdmin以及UniApp开发的商城小程序源码&#xff0c;这款源码在设计和功能上都有不俗的表现&#xff0c;非常适合想要搭建线上商城的开发者。 该源码采用了ThinkPHP作为后端框架&#xff0c;利用其强大的性能和灵活性&#xff0c;保障了系…...

【大模型】OpenManus 项目深度解析:构建通用 AI Agent的开源框架

OpenManus 项目深度解析&#xff1a;构建通用 AI Agent的开源框架 一、项目概述项目特点 二、项目运行方式与执行步骤&#xff08;一&#xff09;环境准备方法 1&#xff1a;使用 conda方法 2&#xff1a;使用 uv&#xff08;推荐&#xff09; &#xff08;二&#xff09;配置&…...

数据科学和机器学习的“看家兵器”——pandas模块 之一

目录 pandas 模块介绍 4.1 pandas 数据结构 一、课程目标 二、Series 对象介绍 三、DataFrame 对象介绍 四、Series 和 DataFrame 在具体应用中的注意事项 (一)Series 注意事项 (二)DataFrame 注意事项 五、实战案例 案例 1:学生成绩分析 案例 2:销售数据分析 案例 3:股…...

Linux服务之lvs集群与dr模式部署

目录 一.lvs相关概述 1.lvs集群的工作模式 2.lvs调度算法 3.ipvsadm工具 二.DR模式部署 一.lvs相关概述 1.lvs集群的工作模式 lvs-nat&#xff1a;修改请求报文的目标IP,多目标IP的DNAT lvs-dr&#xff1a;操纵封装新的MAC地址&#xff08;直接路由&#xff09;lvs-tu…...

LVS负载均衡群集和keepalive

目录 一. 集群概述 1.1 集群的定义 1.2 集群的分类 1. 高可用集群 HA 2. 高性能运输群集 HPC 3.负载均衡群集 LB 4. 分布式存储集群 二. LVS概述 2.1 LVS的定义 2.2 LVS的工作原理 2.3 LVS 的三种工作模式 2.4 LVS 三种工作模式的对比 2.5 LVS 调度算法 1. 静态…...