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

序列化和反序列化(一)

          因为通过这段时间的学习,发现,序列化和反序列化的考点和漏洞在平时遇到的还是比较多的,而且自己也没有特别去学习过这个知识点,所以在这里写一篇关于这里序列化和反序列话的博客,废话就停止在这里了。

        在介绍具体的序列化和反序列化基础之前,因为没有系统性地整理过php的知识点,所以还是选择整理一下php的一些基础知识点

php面向对象基本概念、类与对象

一.面向对象

        (一)基本介绍

        面向对象(Object-Oriented,简称 OO)是一种编程思想和方法,它将程序中的数据和操作数据的方法封装在一起,形成"对象",并通过对象之间的交互和消息传递来完成程序的功能。

        在面向对象的程序设计(英语:Object-oriented programming,缩写:OOP)中,对象是一个由信息及对信息进行处理的描述所组成的整体,是对现实世界的抽象。举个例子,在现实世界里我们所面对的事情都是对象,如计算机、电视机、自行车等。

PHP 面向对象 | 菜鸟教程

        面向对象编程强调数据的封装、继承、多态和动态绑定等特性,使得程序具有更好的可扩展性、可维护性和可重用性。

        (二)面向对象编程三大特征:封装、继承、多态

1、封装:将对象的属性和行为封装起来,将对象的属性和行为封装起来的载体就是类
2、继承:继承性是子类自动共享父类数据结构和方法的机制,是类之间的一种关系;当处理一个问题时,可以将一些有用的类保留下来,这些类通常有相同的属性甚至相同的方法,当遇到同样的问题时可以拿来复用

父类:一个类被其它类继承,可将该类成为父类;

子类:一个类继承其他类称为子类(派生类);
3、多态:将父类对象应用于子类的特征就是多态。子类继承了父类的特点,同时子类又有自己的特点即是多态,多态指的是一个类的实例(对象)可以表现出多种形态。

二.面向过程

        面向过程是一种以“整体事件”为中心的编程思想,编程的时候把解决问题的步骤分析处理,然后用函数把这些步骤实现,再一步步的具体步骤中再按顺序调用函数

三.类

        (一)定义(类和对象的关系)

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

        举个例子

class Zerotwo
{//类体:由成员函数(方法)和成员变量(属性)组成//成员变量声明//成员函数声明}

        在这个例子里面:

        class为定义类的关键字,Zerotwo为类的名字,{}中为类的主体

        类体中的内容为类的成员;

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

        类中的函数称为成员函数(方法):定义在类的内部,可用于访问对象的数据。

        (二)类的内容    

1.预定义      
class Zerotwo
{var $name;    //声明成员变量,var是一种修饰符var $sexl;    function state($var1)    //声明成员函数(方法){echo $this->name;    //使用预定义$this调用成员变量echo $var1;    //成员函数传参$var1可直接调用}
}

        运行结果可见,实际上这个定义了以后,因为只是定义好了类和类体,语言类型等等关键信息都没有加上,所以会被编译器自动识别,然后直接输出。那么接下来我们就要将这个类实例化和赋值

2、实例化和赋值
<?php
class Zerotwo
{var $Darling;    //声明成员变量,var是一种修饰符var $Franxx;function state($var1)    //声明成员函数(方法){echo $this->Darling;    //使用预定义$this调用成员变量echo $var1;    //成员函数传参$var1可直接调用}
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
$zzc->Darling = '02,02,02';    //参数赋值
$zzc->Franxx = 'guojiadui';
print_r($zzc);    //打印对象?>

        那么这里的运行结果就不一样很多了,从运行结果可以看见这里的类Zerotwo被实例化了,并且被对象zzc赋值了

        再演示一个不指向的

<?php
class Zerotwo
{var $Darling;    //声明成员变量,var是一种修饰符var $Franxx;function state($var1)    //声明成员函数(方法){echo $this->Darling;    //使用预定义$this调用成员变量echo '关于'.$var1;    //成员函数传参$var1可直接调用}
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象lin
$zzc->Darling = '02';    //参数赋值
$zzc->state('国家队');//调用函数?>

运行结果

 

3、类的访问权限修饰符

        PHP 支持三种访问修饰符:publicprotected 以及 private,这些修饰符所提供的访问级别具体如下。

public:公共的,在类的内部、子类中 或者类的外部都可以使用,不受限制;

protected:受保护的,在类的内部、子类中可以使用,但不能在类的外部使用;

private:私有的,只能在类的内部使用,在类的外部或者子类中无法使用。

        上图:

还是用刚刚的代码的例子

        外部

<?php
class Zerotwo
{public $Franxx = '国家队';    //声明成员变量,var是一种修饰符private $Darling = '02';protected $zerotwo = '比翼鸟';function state($var1)    //声明成员函数(方法){echo $this->Darling;    //使用预定义$this调用成员变量echo $var1;    //成员函数传参$var1可直接调用}
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
echo $zzc->Franxx;    //外部可用
echo $zzc->Darling;   //外部不可用
echo $zzc->zerotwo;   //外部不可用?>

        运行结果如下

        这里的代码是会报错的,因为违背了封装原则,这里尝试通过 $zzc->Darling 和 $zzc->zerotwo 在类的外部访问私有和受保护属性,就会导致错误,但是这个错误在这里无伤大雅,会在子类那边出错。

        子类

        再次修改代码进行访问

<?php
class Zerotwo       //父类
{public $Franxx = '国家队';    //声明成员变量,var是一种修饰符private $Darling = '02';protected $zerotwo = '比翼鸟';function state($var1)    //声明成员函数(方法){echo $this->Darling;    //使用预定义$this调用成员变量echo $var1;    //成员函数传参$var1可直接调用}
}
class Zerotwo2 extends Zerotwo       //子类
{function test(){echo $this->Darling."<br />";       //private子类不可用echo $this->zerotwo."<br />";       //protected子类可用echo $this->Franxx."<br/>";        //public子类可以用}
}
$zzc = new Zerotwo();    //实例化类Zerotwo()为对象zzc
$zzc2 = new Zerotwo2();
echo $zzc->Franxx."<br />";    //外部可用
echo $zzc->Darling;   //外部不可用
echo $zzc2->test();?>分析

        (这里的"<br />"是html语言的换行,php编译器是无法识别的,只会将它作为字符串输出,php语言的换行可见下面的代码)

        这个时候会发现,出错了 ,这个结果并没有像编译的代码一样输出“$zzc2->test();”的内容,这里的原因是因为在 PHP 中,访问私有属性时,如果尝试从类的外部或从子类访问一个私有属性,会导致一个致命错误(Fatal Error)。这种错误会立即停止脚本的执行,因此任何后续的代码,包括 $zzc2->test();,都不会被执行。这里也是为了演示一下,如果强行去访问私有属性会带来的后果。

        修改以后的代码

<?php
class Zerotwo       //父类
{public $Franxx = '国家队';    // 公有成员变量private $Darling = '02';      // 私有成员变量protected $zerotwo = '比翼鸟'; // 受保护成员变量function state($var1)    // 声明成员函数{echo $this->Darling;    // 使用 $this 调用成员变量echo $var1;    // 成员函数传参 $var1 可直接调用}
}class Zerotwo2 extends Zerotwo       //子类
{function test(){// echo $this->Darling."<br />"; // 不能访问私有属性,需移除或通过方法访问echo $this->zerotwo . PHP_EOL;  // 受保护成员变量,子类可用echo $this->Franxx . PHP_EOL;   // 公有成员变量,子类可用}
}$zzc = new Zerotwo();    // 实例化类 Zerotwo() 为对象 $zzc
$zzc2 = new Zerotwo2();echo $zzc->Franxx . PHP_EOL;    // 外部可用
// echo $zzc->Darling;   // 外部不可用,需移除或通过方法访问
$zzc2->test();
?>

(这里的PHP_EOL就是php语言中的换行)

        这里下面的两个输出就是由对象zzc2控制的。

        那问题又来了,要怎么去访问私有属性呢?还是在原代码的基础上进行修改。

<?php
class Zerotwo       //父类
{public $Franxx = '国家队';private $Darling = '02';   //定义了私有成员protected $zerotwo = '比翼鸟';function state($var1)    // 声明成员函数{echo $this->Darling;    // 使用 $this 调用成员变量echo $var1;    // 成员函数传参 $var1 可直接调用}private function test2()    //定义私有成员的方法{echo $this->Darling;     //在类的内部访问私有成员变量}function test3()            //在类的内部访问私有成员的方法{$this->test2();}
}class Zerotwo2 extends Zerotwo       //子类
{function test(){// echo $this->Darling; // 私有属性,子类不可用echo $this->zerotwo . PHP_EOL;  // 受保护成员变量,子类可用echo $this->Franxx . PHP_EOL;   // 公有成员变量,子类可用}
}$zzc = new Zerotwo();    // 实例化类 Zerotwo() 为对象 $zzc
$zzc2 = new Zerotwo2();echo $zzc->Franxx . PHP_EOL;    // 外部可用
//echo $zzc->Darling;   // 外部不可用,需移除或通过方法访问$zzc2->test();$zzc ->test3();     //通过在类的外部访问Zerotwo中的公有成员,间接访问Zerotwo中的私有成员//私有成员变量无法直接从定义它的类的外部及该类的子类中直接访问
?>

        通过这种间接访问的方法,就可以访问到这个私有成员了

        这里就不再过多进行实验了,给出关于这个访问修饰符的文章

闪耀的钥匙:PHP 与访问修饰符_php访问修饰符-CSDN博客

序列化基础知识

        一.PHP序列化:serialize()

        序列化:是将变量或对象转换成字符串的过程( 序列化只作用于对象,不序列化方法),用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构。

        简单而言       

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

对象/数组\rightarrow字符串

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

        php序列化的字母标识:

a - 数组 (Array): 一种数据结构,可以存储多个相同类型的元素。
b - 布尔型 (Boolean): 一种数据类型,只有两个可能的值:true 或 false。
d - 双精度浮点数 (Double): 一种数据类型,用于存储双精度浮点数值。
i - 整型 (Integer): 一种数据类型,用于存储整数值。
o - 普通对象 (Common Object): 一个通用的对象类型,它可以是任何类的实例。
r - 引用 (Reference): 指向对象的引用,而不是对象本身。
s - 字符串 (String): 一种数据类型,用于存储文本数据。
C - 自定义对象 (Custom Object): 指由开发者定义的特定类的实例。
O - 类 (Class): 在面向对象编程中,类是一种蓝图或模板,用于创建对象。
N - 空 (Null): 在许多编程语言中,null 表示一个不指向任何对象的特殊值。
R - 指针引用 (Pointer Reference): 一个指针变量,其值为另一个变量的地址。
U - 统一码字符串 (Unicode String): 一种数据类型,用于存储包含各种字符编码的文本数据。

         各类型值的serialize序列化:

空字符       null  ->     N;
整型         123   ->     i:123;
浮点型       1.5   ->     d:1.5;
boolean型    true   ->    b:1;
boolean型    fal    ->    b:0;
字符串       “haha”  ->   s:4:"haha";

         测试一下看看

        (一)对象序列化
<?phpclass Zerotwo                       //定义了一个test类{public $Franxx = 11;private $Darling = aa;protected $Zerotwo = true;public function zerotwo(){echo $this->Franxx;}}$zzc = new Zerotwo();            //将test这个类实例化echo serialize($zzc);            //序列化对象zzc

        在这里的输出结果中:(11是公有成员输出的值)

  1. O: 这是一个标识符,表示接下来的数据是一个对象(O
  2. 7:"Zerotwo": 这表示对象的类名是 Zerotwo,并且类名包含 7 个字符(实际上应该是 8 个字符,包括引号内的内容)。

  3. :3:: 这表示对象有 3 个属性。

  4. {...}: 花括号内包含了对象的属性和它们的值。

    • s:6:"Franxx";i:11;:

      • s:6:"Franxx": 表示一个字符串属性名 Franxx,该字符串有 6 个字符。
      • i:11: 表示属性值是一个整数 11
    • s:16:" Zerotwo Darling";s:2:"aa";:

      • s:16:" Zerotwo Darling": 表示一个字符串属性名  Zerotwo Darling,该字符串有 16 个字符(注意前面的空格)。
      • s:2:"aa": 表示属性值是一个字符串 aa,该字符串有 2 个字符。
    • s:10:" * Zerotwo";b:1;:

      • s:10:" * Zerotwo": 表示一个字符串属性名  * Zerotwo,该字符串有 10 个字符(注意前面的空格和星号)。
      • b:1: 表示属性值是一个布尔值 true(在序列化中,布尔值 true 被表示为 1false 被表示为 0)。

           同时,需要注意的是,protected 和private输出时有不可打印字符,如下图

         所以在构造payload的时候,会使用urlencode函数,来实现构造

        这里还有补充的一个小点是序列化的格式

序列化格式

  • 私有属性(private): 私有属性在序列化时,属性名会被格式化为 "\0类名\0属性名",以确保在反序列化时仍然能识别出这是一个私有属性,并且属于哪个类。
  • 受保护属性(protected): 受保护属性在序列化时,属性名会被格式化为 "\0*\0属性名",其中 * 表示受保护属性。
  • 公有属性(public): 公有属性在序列化时,属性名不会有特殊前缀,直接使用属性名。

这种序列化格式确保了在序列化和反序列化过程中,属性的可见性和所属类信息不会丢失。

        (二)成员属性调用对象

<?php
class Zerotwo
{var $zzc='zhu';function  test(){echo $this->zzc;}
}class Zerotwo2
{var $abc;function  __construct()         //使用了__construct魔术方法构造函数{$this->abc=new Zerotwo();}}$a = new Zerotwo2();
echo serialize($a);

       

         在这个例子中,实例化的对象$a的成员变量‘abc’调用实例化后的对象Zerotwo()

        (三)pop链序列化

           面向属性编程POP( Property Oriented Programming)

POP链就是利用魔法方法在里面进行多次跳转然后获取敏感数据的一种payload

<?php
class Zerotwo
{public $a="11";public $b=true;public $c=0202;
}
class Zerotwo2
{public $d;public $e="zzczzc";
}$m=new Zerotwo();
$n=new Zerotwo2();
$n->f=$m;
echo serialize($n);
 

        代码中,$n->f = $m;这一行是将$m对象赋值给$n对象的新属性$f。这里,$f动态创建的,并不是在Zerotwo2类的定义中显式声明的。这里m的值被嵌套在了n里面

(四)数组序列化

<?php
$zzc=array("zerotwo",0202,false);
echo serialize($zzc);

        这里的a表示这是一个数组的序列化(上面的内容有提到),成员属性名为数组的下标,格式 {i:数组下标;类型:长度:“值”; 以此类推}

二.PHP反序列化(unserialize)        

(一)反序列化的特性

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

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

3.反序列化不触发类的成员方法;需要调用方法后才能触发

  (二)反序列化的作用

反序列化:将序列化后的参数还原成实例化的对象。

字符串\rightarrow对象

(三)例子演示    

<?php
class Zerotwo
{public $Franxx = 'zzc';private $Darling = 0202;protected $zerotwo = true;public function displayVar(){echo $this->Franxx;}
}
$d=new Zerotwo();
$b=serialize($d);
print_r(unserialize($b));$a='O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';//反序列化生成的对象的成员属性值由被反序列化的字符串决定,与原来类预定义的值无关
$c=unserialize($a);    //$c把字符串$b反序列化为对象
var_dump($c);        //var_dump()用于打印变量的相关信息,包括变量的类型,值,长度等

     在这个例子中,可以发现的是,反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关。为了方便观察,我将一开始预定义里面的值也打印出来了。

<?php
class Zerotwo
{public  $Franxx = 'zzc';protected $Darling = 0202;private  $zerotwo = true;public function displayVar(){echo $this->Franxx;         //这里没有被调用}
}
$d = 'O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';
$a = urldecode($d);
$c = unserialize($a);
$c->displayVar();

        在这个例子中,反序列化不触发类的成员方法;需要调用方法后才能触发

$d = 'O:7:"Zerotwo":3:{s:6:"Franxx";i:123123123;s:16:" Zerotwo Darling";s:2:"aa";s:10:" * Zerotwo";b:1;}';
$a = urldecode($d);
$c = unserialize($a);

        这段代码将字符串反序列化为一个 Zerotwo 类的对象 $c。但是,反序列化过程并不会调用 Zerotwo 类中的任何方法。只有当显式调用 $c->displayVar() 方法时,displayVar 方法中的代码才会被执行。

$c->displayVar();

         在这个方法中,echo $this->Franxx; 会输出 Franxx 属性的值。在反序列化后的对象中,Franxx 的值被设置为 123123123,因此调用 displayVar 方法将输出 123123123

(四)反序列化漏洞(简单介绍扩展一下)

1.PHP反序列化漏洞成因

        通过上面的代码,可知在反序列化过程中,unserialize()接收的值(字符串)可控;通过改变这个值(字符串),得到所需要的代码,即生成的对象的属性值。

        通过调用方法,触发代码执行。简单来讲,大概就是一种允许攻击者通过将恶意数据反序列化为PHP对象来执行任意代码的漏洞,我现在的理解是这样的。

2. PHP反序列化工作原理

        PHP反序列化是一种将存储在字符串中的PHP对象转换为PHP变量的过程。这可以通过使用unserialize()函数来实现。

unserialize()函数:将字符串中的数据解析为一个PHP对象,并将其分配给一个变量。

3.PHP 反序列化漏洞的常见方法

(1)反弹 Shell。 这是一种在远程计算机上执行命令的方法。可以通过使用 exec() 或 system() 等函数来完成。
(2)文件上传。 这是一种将文件上传到远程计算机的方法。可以通过使用 move_uploaded_file() 函数来完成。
(3)本地文件包含。 这是一个在远程计算机上包含本地文件的方法。可以通过使用 include() 或 require() 等函数来完成。
(4)数据库访问。 这是一个访问远程计算机上的数据库的方法。可以通过使用 mysql_connect() 或 mysqli_connect() 等函数来完成。

4.防御PHP反序列化漏洞

(1)使用最新版本的 PHP。 最新版本的 PHP 通常包含针对已知漏洞的修复程序。
(2)禁用反序列化。 可以通过在 php.ini 文件中设置 unserialize_callback_func 选项来禁用反序列化。
(3)验证用户输入。 在对用户输入进行反序列化之前,请务必对其进行验证。
(4)使用白名单。 仅允许反序列化来自受信任来源的字符串。
(5)使用签名。 在序列化字符串之前,请使用签名对其进行签名。这将有助于防止恶意字符串被反序列化。

(五)魔术方法

        魔术方法是一个预定好的、在特定情况下自动触发的行为方法。(触发前提:魔术方法所在的类被调用

__construct 当一个对象创建时被调用,__destruct 当一个对象销毁时被调用,__toString 当一个对象被当作一个字符串被调用。__wakeup() 使用unserialize时触发__sleep() 使用serialize时触发__destruct() 对象被销毁时触发__call() 对不存在的方法或者不可访问的方法进行调用就自动调用__callStatic() 在静态上下文中调用不可访问的方法时触发__get() 用于从不可访问的属性读取数据__set() 在给不可访问的(protected或者private)或者不存在的属性赋值的时候,会被调用__isset() 在不可访问的属性上调用isset()或empty()触发__unset() 在不可访问的属性上使用unset()时触发__toString() 把类当作字符串使用时触发,返回值需要为字符串__invoke() 当脚本尝试将对象调用为函数时触发__clone() 使用clone关键字拷贝完一个对象后触发
......

还是来一波实操

1.对象被创建时触发__construct()方法,对象使用完被销毁时触发__destruct()方法
<?php
class Zerotwo
{public $Darling = "02";public  function __construct(){echo "创建成功----";}public function __destruct(){echo "销毁成功";}
}$Darling = new Zerotwo();

        实例化test类为对象赋值给a时就被触发。

2.对象被序列化时触发__sleep(),字符串被反序列化时触发__wakeup()
<?php
class Zerotwo
{public $Darling = "02";public  function __sleep(){echo "使用了serialize()----";return array("Darling");}public function __wakeup(){echo "使用unserialize";}
}$Darling = new Zerotwo();
$Franxx=serialize($Darling);
$zerotwo=unserialize($Franxx);

3.echo $a对象当成字符串输出触发__toString(),$a() 对象当成函数执行触发__invoke()
<?php
class Zerotwo
{public $Darling = "02";public  function __toString(){return "字符串----";}public function __invoke(){echo "函数";}
}$Darling = new Zerotwo();
echo $Darling;
$Darling ();
 4.$a->callxxx()  调用了不存在的方法 触发__call()方法
<?php
class Zerotwo
{public function __call($Franxx,$Darling){echo "鸡鸣寺的樱花开了";}
}
$Franxx = new Zerotwo();
$Franxx->callxxx();

$a::callxxx() 静态调用 或 调用成员常量时使用不存在的方法,触发 __callStatic()方法
<?php
class Zerotwo
{public function __callStatic($Franxx,$Darling){echo "$Franxx";}
}
$Franxx = new Zerotwo();
$Franxx::callxxx();

5.调用成员属性不存在时触发__get()方法       
<?php
class Zerotwo
{public $Darling;public  function __get($Darling){echo $Darling;}
}$zerotwo= new Zerotwo();
$zerotwo->Franxx;
 6.给不存在的成员属性赋值时触发__set()方法
<?php
class Zerotwo
{public $Darling;public  function __set($Darling,$Franxx){echo "$Franxx,$Darling";}
}$zerotwo= new Zerotwo();
$zerotwo->zzc=0202;

传参$Franxx,$Darling,返回不存在的成员属性名称及其值

        这里特意换了一下位置看看

7.对不可调用的属性使用isset()或empty()时,isset()会被调用
   对不可调用的属性使用unset()时,unset()会被调用

传参$Darling,返回不存在的成员属性名称

<?php
class Zerotwo
{protected $Darling;public  function __isset($Darling){echo "$Darling";}
}$zerotwo= new Zerotwo();
isset($zerotwo->Darling);

<?php
class Zerotwo
{protected $Darling;public  function __unset($Darling){echo "$Darling";}
}$zerotwo= new Zerotwo();
unset($zerotwo->DarlingDarling);

8.使用clone拷贝完成一个对象后,新对象会自动调用__clone()方法 
<?php
class Zerotwo
{public $Darling='0202';public function __clone(){echo "调用了__clone()";}
}
$zerotwo=new Zerotwo();
$Franxx=clone($zerotwo);

__wakeup()函数漏洞原理:(反序列化漏洞CVE-2016-7124)

当序列化字符串表示对象属性个数的值 大于 真实个数的属性时就会跳过__wakeup的执行

正则匹配大写字母O后不能跟数字时,可在数字前加+号绕过

 

相关文章:

序列化和反序列化(一)

因为通过这段时间的学习&#xff0c;发现&#xff0c;序列化和反序列化的考点和漏洞在平时遇到的还是比较多的&#xff0c;而且自己也没有特别去学习过这个知识点&#xff0c;所以在这里写一篇关于这里序列化和反序列话的博客&#xff0c;废话就停止在这里了。 在介绍具体的序列…...

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版) 文章目录 Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)一.环境准备1.服务器准备2.环境配置3.设置主机名4.修改国内镜像源地址5.配置时间同步6.配置内核转发及网桥过滤二.容器运行时Containerd安装(所有节点)…...

取子串(指针)

#include <stdio.h> #include <string.h>char* substr(char *s, int startloc, int len) {static char result[51]; // 定义一个足够大的静态数组来存储结果static char result1[] {N,U,L,L,\0};int i, j;// 检查startloc是否在字符串的范围内if (startloc < 1…...

Linux系列之如何更换Centos yum源?

系列博客专栏&#xff1a; JVM系列博客专栏SpringBoot系列博客 环境 Centos7Xshell7 问题描述 最近安装了一个虚拟机&#xff0c;准备用来学习&#xff0c;不过使用yum命令安装一些软件&#xff0c;不过使用这个命令时候&#xff0c;提示 Cannot find a valid baseurl fo…...

过滤器和拦截器的区别详解

文章目录 过滤器和拦截器的区别详解1. 来源不同2. 触发时机不同3. 实现原理不同4. 支持的项目类型不同5. 使用场景不同6. 核心区别总结**总结** 过滤器和拦截器的区别详解 在 Web 开发中&#xff0c;过滤器&#xff08;Filter&#xff09; 和 拦截器&#xff08;Interceptor&a…...

centos使用mkisofs构建无人值守镜像(附官方学习文档)

安装mkisofs yum install -y mkisofs 挂载镜像并确认 并拷贝文件(/mnt 为我们的工作目录) 1.3 准备自动应答文件(保存为 ins.ks) 修改系统引导 实际上就是添加inst.ks 这个引导参数 传递应答文件 传统模式引导 UEFI模式引导 打包镜像 通用选项 -v&#xff1a;启用详细模式&a…...

Pyside6+qml+Qtcreator项目实战

Pyside6+qml+Qtcreator项目实战 B站视频教程,进去后记得点赞。最终运行效果: PYTHON and QT QUICK - Custom Buttons With QML And JavaScript - [MODERN GUI]-#012 开发环境: 1、Qt 6.7.2 2、Pyside6 3、Python 3.11.4 4、Windows 10 原视频是用的Qt5,我这里采用Qt6重新…...

秒鲨后端之MyBatis【1】环境的搭建和核心配置文件详解

​ 别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01;! ! ! Mybatis简介 MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下&#xff…...

编译原理复习---目标代码生成

适用于电子科技大学编译原理期末考试复习。 1. 目标代码 是目标机器的汇编代码或机器码&#xff0c;在本课程中指的是类似于汇编代码的一种形式&#xff0c;由一条条的指令构成目标代码。 抽象机指令格式&#xff1a;OP 目的操作数&#xff0c;源操作数。 我们要做的&…...

Winnows基础(2)

Target 了解常见端口及服务&#xff0c;熟练cmd命令&#xff0c;编写简单的 .bat 病毒程序。 Trail 常见服务及端口 80 web 80-89 可能是web 443 ssl心脏滴血漏洞以及一些web漏洞测试 445 smb 1433 mssql 1521 oracle 2082/2083 cpanel主机管理系统登陆&#xff08;国外用的…...

酒蒙子骰子小程序系统

酒蒙子流量变现小程序小游戏 后端tp8 前端uniapp 会员变现 分销推广 流量主 …...

网络安全防范

实践内容 学习总结 PDR&#xff0c;$$P^2$$DR安全模型。 防火墙&#xff08;Firewall&#xff09;&#xff1a; 网络访问控制机制&#xff0c;布置在网际间通信的唯一通道上。 不足&#xff1a;无法防护内部威胁&#xff0c;无法阻止非网络传播形式的病毒&#xff0c;安全策略…...

重拾设计模式--组合模式

文章目录 1 、组合模式&#xff08;Composite Pattern&#xff09;概述2. 组合模式的结构3. C 代码示例4. C示例代码25 .应用场景 1 、组合模式&#xff08;Composite Pattern&#xff09;概述 定义&#xff1a;组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成…...

红米Note 9 Pro5G刷小米官方系统

前言 刷机有2种方式&#xff1a;线刷 和 卡刷。 线刷 线刷&#xff1a;需要用电脑刷机工具&#xff0c;例如&#xff1a;XiaoMiFlash.exe&#xff0c;通过电脑和数据线对设备进行刷机。 适用场景&#xff1a; 系统损坏无法开机。恢复官方出厂固件。刷机失败导致软砖、硬砖的…...

渗透测试-前端加密分析之RSA加密登录(密钥来源服务器)

本文是高级前端加解密与验签实战的第6篇文章&#xff0c;本系列文章实验靶场为Yakit里自带的Vulinbox靶场&#xff0c;本文讲述的是绕过RSA加密来爆破登录。 分析 这里的代码跟上文的类似&#xff0c;但是加密的公钥是通过请求服务端获取的 http://127.0.0.1:8787/crypto/js/…...

踩准智能汽车+机器人两大风口,速腾聚创AI+机器人应用双线爆发

日前&#xff0c;RoboSense速腾聚创交出了一份亮眼的Q3财报。受到多重利好消息影响&#xff0c;其股价也应势连续大涨。截止12月9日发稿前&#xff0c;速腾聚创股价近一个月内累计涨幅已超88%。 财务数据方面&#xff0c;速腾聚创在今年前三季度实现总收入约11.3亿元&#xff0…...

YOLOv8全解析:高效、精准的目标检测新时代——创新架构与性能提升

目录 前言 一、模型介绍 二、网络结构 Backbone改进 特征增强网络(neck) 检测头(head) 其它部分 三、Loss计算 四、性能表现 五、YOLOv8使用详解 添加模型 其它部分 创建数据集 数据标注 模型训练 模型预测 六、YOLOv8总结 前言 YOLO&#xff08;You Only Lo…...

【Python】使用Selenium 操作浏览器 自动化测试 记录

【自动化】Python SeleniumUtil 工具 开启开发者模式 自动安装油猴用户脚本等-CSDN博客文章浏览阅读389次。【自动化】Python SeleniumUtil 工具。https://blog.csdn.net/G971005287W/article/details/144565691?spm1001.2014.3001.5501【学习记录】浏览器指纹相关学习记录&am…...

GDPU软件工程习题(挖空版)

答案&#xff1a; GDPU软件工程24期末复习-CSDN博客 1.8 练习题 一、填空题 软件工程是一门综合性的交叉学科&#xff0c;它涉及计算机学科、( )学科、( )学科和( )学科。软件工程研究的主要内容是 ( )、( )、( ) 三个方…...

【活动邀请·深圳】深圳COC社区 深圳 AWS UG 2024 re:Invent re:Cap

re:Invent 是全球云计算领域的顶级盛会&#xff0c;每年都会吸引来自世界各地的技术领袖、创新者和实践者汇聚一堂&#xff0c;分享最新的技术成果和创新实践&#xff0c;深圳 UG 作为亚马逊云科技技术社区的重要组成部分&#xff0c;将借助 re:Invent 的东风&#xff0c;举办此…...

Hutool工具包的常用工具类的使用介绍

前言 Hutool 是一个轻量级的 Java 工具类库&#xff0c;提供了非常丰富的工具方法&#xff0c;可以大大减少开发时的重复性工作。它的目标是让 Java 开发更简单、更高效。Hutool 提供了多种常用功能&#xff0c;以下是一些常用工具类的使用介绍&#xff1a; 1. StrUtil - 字符…...

C++简明教程(文章要求学过一点C语言)(2)

一、什么是代码文件&#xff08;头文件和源文件&#xff09; 想象你在写一篇很长的故事&#xff08;这就好比是一个 C 程序&#xff09;&#xff0c;你可能会把故事分成不同的章节&#xff08;类似于 C 中的文件&#xff09;。 头文件&#xff08;.h&#xff09;&#xff1a;它…...

防火墙技术与网络安全

网络已经成为了人类所构建的最丰富多彩的虚拟世界&#xff0c;网络的迅速发展&#xff0c;给我们的工作和学习生活带来了巨大的改变。我们通过网络获得信息&#xff0c;共享资源。如今&#xff0c;Internet遍布世界任何一个角落&#xff0c;并且欢迎任何一个人加入其中&#xf…...

html 中 表格和表单的关系与区别

在 HTML 中&#xff0c;表格 (<table>) 和表单 (<form>) 是两种常用于展示数据和收集用户输入的元素。它们具有不同的功能和结构。以下是关于这两者的详细介绍&#xff1a; 1. HTML 表格&#xff08;<table>&#xff09; 表格用于展示结构化的数据&#xf…...

基于Java的购物网站毕业论文

标题:基于 Java 的购物网站 内容:1.研究背景 1.1.国内研究进展 近年来&#xff0c;随着我国电子商务市场的不断发展&#xff0c;越来越多的企业开始涉足电子商务领域。其中&#xff0c;基于 Java 的购物网站成为了众多企业的首选。Java 语言具有跨平台、安全性高、稳定性好等优…...

Redis——缓存预热+缓存雪崩+缓存击穿+缓存穿透

文章目录 1、 缓存预热2、 缓存雪崩3、 缓存击穿4、 缓存穿透总结 1、 缓存预热 什么是预热&#xff1a; mysql加入新增100条记录&#xff0c;一般默认以mysql为准作为底单数据&#xff0c;如何同步给redis&#xff08;布隆过滤器&#xff09;这100条新数据。 为什么需要预热…...

wxWidgets使用wxStyledTextCtrl(Scintilla编辑器)的正确姿势

开发CuteMySQL/CuteSqlite开源客户端的时候&#xff0c;需要使用Scintilla编辑器&#xff0c;来高亮显示SQL语句&#xff0c;作为C/C领域最成熟稳定又小巧的开源编辑器&#xff0c;Scintilla提供了强大的功能&#xff0c;wxWidgets对Scintilla进行包装后的是控件类&#xff1a;…...

【ETCD】【实操篇(二)】如何从源码编译并在window上搭建etcd集群?

要在 Windows 上编译 etcd 及 etcdctl 工具&#xff0c;并使用 bat 脚本启动 etcd 集群&#xff0c;首先需要准备好开发环境并确保依赖项正确安装。下面是从 etcd 3.5 源码开始编译和启动 etcd 集群的详细步骤&#xff1a; 目录 1. 安装 Go 环境2. 获取 etcd 源码3. 编译 etcd…...

服务器数据恢复—V7000存储中多块磁盘出现故障导致业务中断的数据恢复案例

服务器存储数据恢复环境&#xff1a; 一台V7000存储上共12块SAS机械硬盘&#xff08;其中1块是热备盘&#xff09;&#xff0c;组建了2组Mdisk&#xff0c;创建了一个pool。挂载在小型机上作为逻辑盘使用&#xff0c;小型机上安装的AIXSybase。 服务器存储故障&#xff1a; V7…...

冯诺依曼架构与哈佛架构的对比与应用

冯诺依曼架构&#xff08;Von Neumann Architecture&#xff09;&#xff0c;也称为 冯诺依曼模型&#xff0c;是由著名数学家和计算机科学家约翰冯诺依曼&#xff08;John von Neumann&#xff09;在1945年提出的。冯诺依曼架构为现代计算机奠定了基础&#xff0c;几乎所有现代…...