upload-labs详解(1-12)文件上传分析
目录
uploa-labs-main
upload-labs-main第一关
前端防御
绕过前端防御
禁用js
Burpsuite抓包改包
upload-labs-main第二关
上传测试
错误类型
upload-labs-env
upload-labs-env第三关
上传测试
查看源码
解决方法
重命名,上传
upload-labs-env第四关
测试方法
上传文件
upload-labs-env第五关
代码解析
解题思路——大小写绕过
upload-labs-env第六关
代码
空格绕过
upload-labs-env第七关
代码
绕过
upload-labs-env第八关
::$DATA 绕过
upload-labs-env第九关
代码
思路
upload-labs-env第十关
代码
双写绕过
upload-labs第-env十一关
代码
思路——00截断问题(只存在于php5.2版本中)——get传参(url编码方式)
upload-labs-env第十二关
代码
思路——00截断——save_path是post传参
uploa-labs-main
upload-labs-main第一关
前端防御
有一个过滤函数checkFile()
绕过前端防御
禁用js
Chrome禁用js
设置—隐私与安全—网站设置—内容—JavaScript—不允许网站使用JavaScript
再次尝试上传,成功
Burpsuite抓包改包
首先为文件进行重命名,shell.php重命名为shell.jpg
上传shell.jpg文件
Burpsuite打开抓包
网页点击确定上传,
发送到重放器,改包,将shell.jpg改为shell.php,重新发送,上传成功
upload-labs-main第二关
上传测试
错误类型
文件类型不正确,
使用Burpsuite抓包改包
修改为image/png
上传成功
upload-labs-env
upload-labs-env第三关
上传测试
查看源码
$is_upload = false;$msg = null;if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array('.asp','.aspx','.php','.jsp');//定义一个数组$deny_ext,包含不允许上传的文件扩展名$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if(!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];//获取上传文件的临时路径,文件在服务器上以临时文件的形式存储$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}}
分析源码
需要绕过黑名单的过滤
.php3 、Phtml等都可以被解析
需要修改Apache的配置文件httpd.conf,使.php3 .phtml也可以被解析,当Apache和php版本低时,服务端可以修改
在配置文件中添加
AddType application/x-httpd-php .phtml
重启Apache
注意:在靶场实验中可能存在这个漏洞,真实项目中不会存在
解决方法
黑名单绕过
在upload-labs-env原版环境中,Apache的配置文件httpd.conf有将 .php3 .phtml解析成php文件
重命名,上传
上传成功
解析成功
upload-labs-env第四关
测试方法
需要.htaccess文件
我们下载upload-labs-env原版环境,自带phpstudy的低版本
在Apache的低版本中,如果在目录中上传一个.htaccess文件
AddType application/x-httpd-php .jpg
会将后来上传的jpg文件解析成php,shell代码得以执行
上传文件
解析成功
upload-labs-env第五关
代码解析
$is_upload = false;
$msg = null;# isset - 检测变量是否已经声明并且不为空
# $_POST['submit'] - 表示表单中名为 submit 的按钮被点击
if (isset($_POST['submit'])) {# file_exists — 检查文件或目录是否存在返回值为true或falseif (file_exists(UPLOAD_PATH)) {# 定义一个数组 $deny_ext,包含一系列禁止上传的文件扩展名$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");# trim — 去除字符串首尾处的空白字符(或者其他字符)# $_FILES['upload_file'] 是表单中 name="upload_file" 对应的上传文件信息# 它包含以下常见字段:# $_FILES['upload_file']['name']:上传文件的原始名称(如 example.jpg)。# $_FILES['upload_file']['type']:上传文件的 MIME 类型(如 image/jpeg)。# $_FILES['upload_file']['size']:上传文件的大小(以字节为单位)。# $_FILES['upload_file']['tmp_name']:上传文件的临时存储路径。# $_FILES['upload_file']['error']:与文件上传相关的任何错误代码$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点#strrchr — 查找指定字符在字符串中的最后一次出现的位置,返回从最后一个点开始到字符串末尾的部分$file_ext = strrchr($file_name, '.');#str_ireplace - 执行不区分大小写的字符串替换,在目标字符串中查找指定的子字符串(无视大小写),然后用另一个字符串替换它$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空#in_array — 检查数组中是否存在某个值,检查数组$deny_ext中是否存在$file_extif (!in_array($file_ext, $deny_ext)) {# $_FILES['upload_file']['tmp_name']:上传文件的临时存储路径。$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;#move_uploaded_file — 将上传的文件移动到新位置if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
解题思路——大小写绕过
文件后缀大写绕过
上传.php文件
修改后缀名为.PHP
上传成功
解析执行
upload-labs-env第六关
代码
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = $_FILES['upload_file']['name'];$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
空格绕过
文件名后缀加空格绕过
upload-labs-env第七关
代码
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空
绕过
文件后缀名后加点
upload-labs-env第八关
::$DATA 绕过
upload-labs-env第九关
代码
没有对代码进行重命名拼接路径
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
思路
deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来
更改文件名为 index.php. . 即.php点 空格 点
运行php时,首先删除文件名末尾的点,
...... ,
最后一步检查,去除最后的空格,
此时文件名为index.php.
上传到Windows环境中时,系统会将其视为一个没有扩展名的文件,
Windows会将 index.php.
解释为没有扩展名的文件,因为末尾的点会被忽略。文件的实际名称会变成 index.php
,但扩展名会被视为不存在
upload-labs-env第十关
代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = str_ireplace($deny_ext,"", $file_name);$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}
使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空(即将它删掉),可以使用双写绕过黑名单
双写绕过
upload-labs第-env十一关
代码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');//$_FILES['upload_file']['name']:获取上传文件的原始文件名//strrpos($_FILES['upload_file']['name'], "."):查找文件名中最后一个点(.)的位置//substr(..., strrpos(...) + 1):从最后一个点的下一个字符开始截取,得到文件扩展名$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){//$_FILES['upload_file']['tmp_name']:获取上传文件的临时存储路径$temp_file = $_FILES['upload_file']['tmp_name'];//$_GET['save_path']:从 URL 参数中获取保存路径//rand(10, 99):生成一个 10 到 99 之间的随机数//date("YmdHis"):生成当前日期时间字符串,格式为 年月日时分秒//最终路径格式:保存路径/随机数+时间戳.扩展名$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = '上传出错!';}} else{$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}
思路——00截断问题(只存在于php5.2版本中)——get传参(url编码方式)
在c语言中\0是结束符
php底层是运行c语言
使用\0使截断代码,使后面代码不再运行
使用的传递方式是urlcode传参,%00使用url解码后为空字符
当一个字符串中存在空字符的时候,在被解析的时候会导致空字符后面的字符被丢弃
当php代码运行到
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){
时,路径变成了/upload/web.php 后面的连接字符都被丢弃了,
之后将文件上传文件index.jpg的文件内容移动到web.php中,这样恶意代码就可以被解析了
upload-labs-env第十二关
代码
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传失败";}} else {$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}
思路——00截断——save_path是post传参
0x00
是十六进制表示的空字符(ASCII 值为 0)
在web.php后面加一个空格,在Burpsuite的hex转换中,找到这个空格(十六进制空格的编码为20)
将其修改为十六进制的空字符表示00
修改后
发送
相关文章:

upload-labs详解(1-12)文件上传分析
目录 uploa-labs-main upload-labs-main第一关 前端防御 绕过前端防御 禁用js Burpsuite抓包改包 upload-labs-main第二关 上传测试 错误类型 upload-labs-env upload-labs-env第三关 上传测试 查看源码 解决方法 重命名,上传 upload-labs-env第四关…...

RAG系统(检索增强生成)的优化策略
RAG(检索增强生成)系统的优化可以从多个方面入手,主要包括数据、查询、检索、生成、框架和评估等几个重要环节。本文将详细介绍这些优化策略,并为每个环节提供具体的操作方法。 一、数据优化 1. 数据清洗和增强 数据质量直接影响检索和生成的效果,因此需要进行细致的数据…...

写毕业论文用哪个AI好?这6款AIGC论文工具给你答案
撰写毕业论文是一项艰巨的任务,AIGC 论文工具的出现为同学们提供了有力支持。以下 6 款工具在功能、适用场景等方面各有优势,助你高效完成毕业论文。 文赋 AI 论文 文赋 AI 论文堪称毕业论文写作的得力助手。它的生成速度令人惊叹,短短 5 分…...

loadingcache优化
问题分析 通过当前现场的火焰图进行分析 原本的loadingcache public LoadingCache<Integer, Student> map Caffeine.newBuilder().refreshAfterWrite(CONTRACT_CACHE_HOURS, TimeUnit.HOURS).maximumSize(CONTRACT_CONFIG_CACHE_SIZE).recordStats().build(key -> …...

【Vue3 Element UI - Plus + Tyscript 实现Tags标签输入及回显】
Vue3 Element Plus TypeScript 实现 Tags 标签输入及回显 在开发后台管理系统或表单页面时,动态标签(Tags) 是一个常见的功能需求。用户可以通过输入框添加标签,并通过关闭按钮删除标签,同时还需要支持标签数据的提…...

STM32 子设备通过CAN发送数据到主设备
采集ADC、GPS经纬坐标、温湿度数据、大气压数据通过CAN方式发送给主设备端,帧ID按照如下定义: 我尼玛一个标准帧ID位数据是11位,扩展帧才是111829位,它说最开头的是四位是真类型,并给我如下解释: 它把帧的定…...

Python可视化——地理空间型图表(自用)
地图信息可视化的实现就是将不可展开的曲面上的地理坐标信息转化为二维平面进行显示,这个过程也叫地图投影(空间三维投影到平面二维) 地图投影的要求:等面积、等角度、等距离。总的来说就是映射到二维平面中的任何点通过比例尺放大…...

WordPress报502错误问题解决-php-fpm-84.service loaded failed failed LSB: starts php-fpm
文章目录 问题描述问题排查问题解决 问题描述 服务器环境: php:8.4MySQL:8.0Nginx:1.26.2 在访问站点时,一直报502,而两天前还能正常访问。 问题排查 导致502的问题很多,比如站点访问量太大…...

Python在SEO中的自动化应用爬虫开发与日志分析实例
引言 搜索引擎优化(SEO)是数字营销中至关重要的一环,旨在提高网站在搜索引擎结果页面(SERP)中的排名。随着互联网数据的爆炸式增长,手动进行SEO分析和管理变得愈发困难。Python作为一种强大的编程语言&…...

thingsboard edge 在windows 环境下的配置
按照官方文档:Installing ThingsBoard Edge on Windows | ThingsBoard Edge,配置好java环境和PostgreSQL。 下载对应的windows 环境下的tb-edge安装包。下载附件 接下来操作具体如下 步骤1,需要先在thingsboard 服务上开启edge 权限 步骤2…...

nnMamba:基于状态空间模型的3D生物医学图像分割、分类和地标检测
摘要 本文提出了一种基于状态空间模型(SSMs)的创新架构——nnMamba,用于解决3D生物医学图像分割、分类及地标检测任务中的长距离依赖建模难题。nnMamba结合了卷积神经网络(CNN)的局部特征提取能力与SSMs的全局上下文建…...
nginx 配置403页面(已亲测)
问题:GET请求访问漏洞url即可看到泄露的内网ip 解决方式: 1.配置nginx 不显示真实Ip 2.限制接口只能是POST请求 具体配置: 编写一个403.html 在nginx的配置文件中,配置location参数: location /api/validationCode…...

SyntaxError: Invalid or unexpected token in JSON at position x
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...

Uncaught TypeError: Cannot read properties of undefined (reading ‘xxx‘)
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...
Nginx 跨域配置详细讲解
一、跨域请求概述 跨域资源共享(CORS,Cross-Origin Resource Sharing)是一种机制,它使用额外的HTTP头部来告诉浏览器让运行在一个origin(域)上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资…...
前端开发基石:HTML语义化深度解析与实践指南
一、语义化设计的本质价值 1.1 从文档结构到信息表达 在Web诞生初期(1991年),HTML仅包含18个标签用于学术文档展示。经过30年发展,HTML5已拥有超过110个标签,其中语义化标签占比提升至60%。这种演进背后是互联网从简…...

mongodb安装教程以及mongodb的使用
MongoDB是由C语言编写的一种面向文档的NoSQL数据库,旨在为WEB应用提供可扩展的高性能数据存储解决方案。与传统的关系型数据库(如 MySQL 或 PostgreSQL)不同,MongoDB 存储数据的方式是以 BSON(类似于 JSON 的二进制格式…...
C# 中的多线程同步机制:lock、Monitor 和 Mutex 用法详解
在多线程编程中,线程同步是确保多个线程安全地访问共享资源的关键技术。C# 提供了几种常用的同步机制,其中 lock、Monitor 和 Mutex 是最常用的同步工具。本文将全面介绍这三种同步机制的用法、优缺点以及适用场景,帮助开发者在多线程开发中做…...

【通义万相】蓝耘智算 | 开源视频生成新纪元:通义万相2.1模型部署与测评
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能(AI)通过算法模拟人类智能,利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络(如ChatGPT&…...

期权帮|中证1000股指期权交割结算价怎么算?
期权帮锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 中证1000股指期权交割结算价怎么算? 一、按照最后交易日结算价: (1)计算方法:最后交易日标的指数(…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...

npm安装electron下载太慢,导致报错
npm安装electron下载太慢,导致报错 背景 想学习electron框架做个桌面应用,卡在了安装依赖(无语了)。。。一开始以为node版本或者npm版本太低问题,调整版本后还是报错。偶尔执行install命令后,可以开始下载…...