【安全攻防】网络安全中的序列化与反序列

1.序列化与反序列化

首先要了解序列化与反序列化的定义,以及序列化反序列化所用到的基本函数。

序列化:把对象转换为字节序列的过程称为对象的序列化,相当于游戏中的存档。

PHP中的序列化函数serialize()

**serialize()**函数用于序列化对象数组,并返回一个字符串。serialize()函数序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变

语法string serialize ( mixed $value )
参数说明$value: 要序列化的对象或数组。
返回值返回一个字符串。

示例:

<?php
highlight_file(__FILE__);
$sites=array('I', 'Like', 'PHP');
echo'<br/>';
var_dump(serialize($sites));    //把这个对象进行序列化
echo'<br/>';
​
classman{
public$name="xiaocui";
public$sex="man";
private$age=26;
}
$M=newman();//创建一个对象
var_dump(serialize($M)); //把这个对象进行序列化
​
?>

输出结果为:

string(47) "a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}"
string(79) "O:3:"man":3:{s:4:"name";s:7:"xiaocui";s:3:"sex";s:3:"man";s:8:"manage";i:26;}"

参数说明:

数组的序列化:
a 代表一数组  
3 代表数组中有3个元素
i 代表数组的下标
0 代表I元素的下标值
s 代表元素I的数据类型为字符型
1 代表元素I的长度为1
对象的序列化:
O 代表是一个对象
3 代表类名man的长度
3 代表类中的字段数
s 代表属性name的类型为字符型
4 代表属性name的长度

//后面的以此类推,序列化字符串中字段内容以{开始,;}结束

反序列化:把字节序列恢复为对象的过程称为对象的反序列化,相当于游戏中的读档。

【一一帮助安全学习,所有资源获取处一一】
①网络安全学习路线
②20份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥信息收集80条搜索语法
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析

PHP中的反序列化函数unserialize()

**unserialize()**函数用于将序列化后的字符串在还原为原来的数组或对象的过程。**unserialize()**函数可以快速将序列化的字符串还原出来,用来完成它本来的功能。

语法mixed unserialize ( string $str )
参数说明$str: 序列化后的字符串。
返回值返回的是转换之后的值,可为 integer、float、string、array 或 object。不可反序列化时返回FALSE,并抛出提醒。

示例代码:

<?php
highlight_file(__FILE__);
$sites=array('I', 'Like', 'PHP');
echo'<br/>';
echo$ser=serialize($sites).'<br/>';    //把这个对象进行序列化
var_dump(unserialize($ser)); //把序列化的字符串进行反序列化
echo'<br/>';
classman{
public$name="xiaocui";
public$sex="man";
private$age=26;
}
$M=newman();//创建一个对象
echo$ser=serialize($M).'<br/>'; //把这个对象进行序列化
var_dump(unserialize($ser));   //把序列化的字符串进行反序列化
​
?>

输出结果为:

a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}
array(3) { [0]=>string(1) "I"[1]=>string(4) "Like"[2]=>string(3) "PHP"}
​
O:3:"man":3:{s:4:"name";s:7:"xiaocui";s:3:"sex";s:3:"man";s:8:"manage";i:26;}
object(man)#2 (3) { ["name"]=> string(7) "xiaocui" ["sex"]=> string(3) "man" ["age":"man":private]=> int(26) } 

可以看出上述反序列化后的数组或对象,与原数据没有任何变化。

序列化与反序列化在系统中的作用

①把对象的字节序列永久放在磁盘中,需要时可以随时调用,大大节省磁盘占用空间。

②在传输过程中可以直接传输字节序列,而不是对象,这可以大大提高传输速率。

在业务系统中,需要对一些对象进行序列化存储,让他们离开内存空间,存放在一个文件中,以便持久化保存。例如:在用户注册并登录系统时,会将用户信息如用户名,密码,cookie等信息先通过序列化存储起来,当用户再次登录时将序列化后的字节序列通过反序列化成原对象到内存进行使用,可以大大节省内存开销。

2.魔术方法

PHP将所有以__(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以__为前缀。

PHP中常见魔术方法

__construct()

具有 __construct函数的类会在每次创建新对象时先调用此方法,适合在使用对象之前做一些初始化工作。

代码示例:

<?php
highlight_file(__FILE__);
classdemo{
public$name="xiaocui";
public$sex="man";
private$age=26;
publicfunction__construct()
{
echo"<br/>"."类被实例化时调用我!";
}
}
$D=newdemo();   //实例化对象
​
?>

输出结果:

类被实例化时调用我!

__destruct()

该函数会在到某个对象的所有引用都被删除或者当对象被销毁时执行

代码示例:

<?php
highlight_file(__FILE__);
class demo{
public $name="xiaocui";
public $sex="man";
private $age=26;
public function __construct()
{
echo "<br/>"."类被实例化时调用我!"."<br/>";
}
public function num($a,$b){
echo $c = $a + $b.'<br/>';
return $c;
}
public function __destruct(){
echo "当类中的所有方法都被销毁时调用我!";
}
public function person($per){
echo "We are $per !!!".'<br/>';
}
}
$D=new demo();   //实例化对象
$D->num(5,6);   //调用num()方法
$D->person(man);  //调用person()方法
?>

输出结果:

类被实例化时调用我!
11
Weareman!!!
当类中的所有方法都被销毁时调用我!

上述输出结果可以很直观的看到代码的执行顺序:__construct()=>num(5,6)=>person(nanren)=>__destruct()

实例化对象时首先要执行构造方法__construct(),然后接着执行类中的实例num()person(),当所有方法都执行完成销毁时,最后调用析构方法__destruct()

__wakeup()

在使用unserialize()时,会检查是否存在一个__wakeup()魔术方法。如果存在,则该方法会先被调用,预先准备对象需要的资源。

代码示例:

<?php
highlight_file(__FILE__);
classdemo{
public$name="xiaocui";
protected$sex="man";
private$age=26;
publicfunction__construct()
{
echo"<br/>"."类被实例化时调用我!"."<br/>";
}
publicfunction__destruct(){
echo"<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
}
publicfunction__wakeup()
{
echo"<br/>"."当反序列时首先调用我 !".'<br/>';
}
}
$D=newdemo();   //实例化对象
echo$ser=serialize($D);      //序列化对象$D
var_dump(unserialize($ser));    //反序列化字符串$ser
​
?>

输出结果:

由于$age为私有属性,在序列化时会在前后加空白字符%00,原本的字符长度为7,而在两侧加入空白字符则字符长度就会变为9

类被实例化时调用我!
O:4:"demo":3:{s:4:"name";s:7:"xiaocui";s:6:"*sex";s:3:"man";s:9:"demoage";i:26;}
当反序列时调用我 !
object(demo)#2
 (3) { ["name"]=> string(7) "xiaocui" ["sex":protected]=> 
string(3) "man" ["age":"demo":private]=> int(26) }
当类中的所有方法都被销毁时调用我!
​
当类中的所有方法都被销毁时调用我!

上述输出结果可以很直观的看到代码的执行顺序:__construct()=>serialize($D)=>__wakeup()=>unserialize($ser)=>__destruct()=>__destruct()

实例化对象时首先要执行构造方法__construct(),然后执行序列化serialize($D),然后再反序列化之前要执行__wakeup()方法,然后执行反序列化unserialize($ser),当所有方法都执行完成销毁时最后执行__destruct()析构方法,由于反序列化后将原来的序列化字符串还原又执行一次__destruct()

__toString()

__toString()方法用于定义一个类被当成字符串时该如何处理。

示例代码:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }
    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }
    public function __wakeup()
    {
        echo "<br/>"."当反序列时调用我 !".'<br/>';
    }
    public function __toString(){
        return "<br/>"."类被当成字符串处理时调用我!"."<br/>";
    }
}
$D=new demo();   //实例化对象
echo $D;   //类被当成字符串输出

?>

输出结果:

类被实例化时调用我!
​
类被当成字符串处理时调用我!
​
当类中的所有方法都被销毁时调用我!

上述输出结果可以看到,当类被当成字符串echo时,__toString()方法被调用并执行。

如果该类中没有__toString()方法,进行echo输出时,PHP会抛出致命性错误,错误如下:

Catchablefatalerror: ObjectofclassdemocouldnotbeconvertedtostringinD:\XXXX\phpstudy_pro\WWW\two\demo.phponline30

__sleep()

在使用serialize()函数时,程序会检查类中是否存在一个__sleep()魔术方法。如果存在,则该方法会先被调用,然后再执行序列化操作。

__sleep()方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,该函数就起到了很好的清理作用。

示例代码:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }
    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }
    public function __wakeup()
    {
        echo "<br/>"."当反序列时调用我 !".'<br/>';
    }
    public function __sleep(){
        echo "<br/>"."当序列时调用我 !".'<br/>';
        return array("name","sex","age");    //这里必须返回一个数值,里边的元素表示返回的属性名称
    }

}
$D=new demo();   //实例化对象

echo $ser = serialize($D);  //序列化对象

?>

输出结果:

类被实例化时调用我!
当序列时调用我!
O:4:"demo":3:{s:4:"name";s:7:"xiaocui";s:6:"*sex";s:3:"man";s:9:"demoage";i:26;}
当类中的所有方法都被销毁时调用我!

上述输出结果可以看到,当类被序列化时首先调用了__sleep()方法,该函数必须返回一个数值。如果该函数没有返回属性的话,序列化时会将属性清空。

__invoke()

当尝试以调用函数的方式调用一个对象时,__invoke方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)

代码示例:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }
    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }
    public function __wakeup()
    {
        echo "<br/>"."当反序列化时调用我 !".'<br/>';
    }
    public function __sleep(){
        echo "<br/>"."当序列化时调用我 !".'<br/>';
        return array("name","sex","age");

    }
    public function __invoke()
    {
		echo "<br/>"."当以函数的方式调用对象时会调用我!".'<br/>';
    }

}
$D=new demo();   //实例化对象

$D();    //以函数的方式调用对象
?>

结果输出:

类被实例化时调用我!
​
当以函数的方式调用对象时会调用我!
​
当类中的所有方法都被销毁时调用我!

上述结果可以看到当使用函数的方法调用对象时,就会调用__invoke()方法.

如果没有类中没有该方法,那么PHP会报出致命性错误,如下:

Fatalerror:
 UncaughtError: 
FunctionnamemustbeastringinD:\xxxxx\phpstudy_pro\WWW\two\demo.php:42Stacktrace:
 #0 {main} thrown in D:\xxxxx\phpstudy_pro\WWW\two\demo.php on line 42

__call()

在对象中调用一个不存在或者不可访问方法时,__call会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }
    public function num($a,$b){
        echo "<br/>".$c = $a + $b.'<br/>';
        return $c;
    }
    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }
    public function person($per){
        echo "<br/>"."We are $per !!!".'<br/>';
    }
    public function __wakeup()
    {
        echo "<br/>"."当反序列化时调用我 !".'<br/>';
    }
    public function __sleep(){
        echo "<br/>"."当序列时调用我 !".'<br/>';
        return array("name","sex","age");

    }
    public function __call($arg1,$arg2){
        echo  "<br/>"."当对象调用一个不存在或者不可访问的方法时调用我!".'<br/>';
    }

}
$D=new demo();   //实例化对象
$D->num1(1,2);   //调用一个不存在的方法
?>

结果输出:

类被实例化时调用我!
​
当对象调用一个不存在或者不可访问的方法时调用我!
​
当类中的所有方法都被销毁时调用我!

__set()

给不可访问属性赋值时,__set会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo extends demo1{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }
    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }
    public function person($per){
        echo "<br/>"."We are $per !!!".'<br/>';
    }
    public function __set($arg1,$arg2){

        echo "<br/>"."当给不存在或者不可访问的属性赋值时调用我!"."<br/>";

    }
}

class demo1{
    private $weight;
    public  $height;
    public function people(){
        echo $this->weight;
        echo $this->height;
    }
}

$D=new demo();   //实例化对象
$D->weight=74; //给不可访问的属性赋值
?>

输出结果:

类被实例化时调用我!
当给不存在或者不可访问的属性赋值时调用我!
当类中的所有方法都被销毁时调用我!

__isset()

对不可访问属性调用isset()empty()时,__iset()会被调用。

__unset()

对不可访问属性调用unset()时,__unset()会被调用。

__get()

读取不可访问属性的值时,__get会被调用。

代码示例:

<?php
highlight_file(__FILE__);
class demo extends demo1{
    public $name="xiaocui";
    protected $sex="man";
    private $age=26;
    public function __construct()
    {
        echo "<br/>"."类被实例化时调用我!"."<br/>";
    }

    public function __destruct(){
        echo "<br/>"."当类中的所有方法都被销毁时调用我!"."<br/>";
    }

    public function __get($arg1){
        echo "<br/>"."读取不存在或不可访问的属性时调用我!";
    }
}

class demo1{
    private $weight = 0;
    public  $height;
    public function people(){
        echo $this->weight;
        echo $this->height;
    }
}

$D=new demo();   //实例化对象

$D->weight;   //读取父类中不可访问的属性
?>

输出结果:

类被实例化时调用我!
读取不存在或不可访问的属性时调用我!
当类中的所有方法都被销毁时调用我!

3.反序列化漏洞

3.1 反序列化漏洞利用条件

① unserialize()函数中参数可控
② 存在可利用的类,且类中有魔术方法

代码示例1:

<?php
highlight_file(__FILE__);

class demo
{

    public $arg1 = "0";

   public function __destruct()
    {

        echo $this->arg1;  //输出用户传递的arg1值

    }

}

$a=$_GET['arg'];     //接收前端传递的arg1变量
$unser = unserialize($a);    //反序列化传递的arg1
?>

上述的代码满足反序列化漏洞的两个条件,arg参数可控,也就是unserialize()函数的参数可控;存在可利用的类demo,且demo类中有可利用的魔术方法__destruct(),然而__destruct()魔术方法中使用echo输出变量了arg

通过arg参数,构造序列化字符串,通过unserialize()函数进行反序列化,最后通过__destruct()魔术方法输出变量,造成XSS

image.png

1656063927_62b587b782d1ce26d9662.png

示例代码2

<?php
highlight_file(__FILE__);

class demo
{

    public $arg1 = "0";

    public function __destruct()
    {

        eval($this->arg1);  //eval()去执行用户传递的arg1值

    }

}

$a=$_GET['arg'];     //接收前端传递的arg1变量
$unser = unserialize($a);    //反序列化传递的arg1
var_dump($unser);
?>

如果魔术方法中存在eval(),且参数可控,那么通过构造序列化字符串,通过反序列化漏洞造成RCE

1656063978_62b587ea396a1888f7509.png

3.2 __wakeup()函数绕过

在序列化时传递对象的属性大于实际对象的属性时,__wakeup()魔术方法将不会被执行,从而导致绕过。

PHP版本<=5.6.25或者PHP版本<=7.0.11

示例代码:

<?php
highlight_file(__FILE__);

class demo
{

    public $arg1 = "0";

    public function __destruct()
    {

       eval($this->arg1);  //eval()去执行用户传递的arg1值

    }

    public function __wakeup(){
        foreach(get_object_vars($this) as $k => $v) {
                $this->$k = '';          //将传入的参数遍历,全部赋值为空
            }

    }

}

$a=$_GET['arg'];     //接收前端传递的arg1变量
$unser = unserialize($a);    //反序列化传递的arg1
var_dump($unser);
?>

如果属性值与对象实际属性值相同,则会在反序列化时执行__wakeup()函数将传入的变量值替换为空。
1656064048_62b58830a44fdeca601a9.png
如果属性值设置大于实际对象属性值则会绕过__wakeup()函数。
1656064071_62b588476b877e1951bf6.png

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

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

相关文章

jsqlparse工具拦截sql处理和拓展

前置知识 访问者模式 &#xff08;Visitor Pattern&#xff09;是一种行为设计模式&#xff0c;它允许你定义在不改变被访问元素的类的前提下&#xff0c;扩展其功能。通过将操作&#xff08;操作或算法&#xff09;从对象结构中提取出来&#xff0c;可以在不修改这些对象的前…

6.基于SpringBoot的SSMP整合案例-业务层开发

目录 1.业务层标准开发 1.1接口定义 1.2实现类定义 1.3测试类定义 1.4小结&#xff1a; 2.业务层快速开发 2.1使用MyBatisP1us提供有业务层通用接口(ISerivce)与业务层通用实现类(ServiceImpl),t> 接口定义&#xff1a; 实现类定义&#xff1a; 测试类&#xff1a; …

MergeBus封装模块

当模型有很多信号进行交互的时候&#xff0c;并且已经无法回避线条交叉的时候&#xff0c;我们会选择 From和Goto模块来提高模型的可读性&#xff0c;假如你拿到的模型如下图&#xff1a; 像不像芯片的电路&#xff0c;错综而复杂 该如何整理呢&#xff1f; 我相信有很多模型…

2024年移动手游趋势:休闲类手游收入逆势增长,欧美玩家成为主力

移动手游广告情报平台Sensor Tower近期发布的报告显示&#xff0c;从宏观数据来看&#xff0c;尽管2023年对于移动游戏市场来说是艰难的一年&#xff0c;无论是总下载量亦或是总收入都较去年有所下降&#xff0c;尤其是Google Play。但在总体下降的大趋势下&#xff0c;休闲游戏…

mac如何压缩视频大小不改变画质,mac怎么压缩视频软件

在数字时代&#xff0c;视频已成为信息传递和娱乐消遣的重要媒介。然而&#xff0c;视频带来的愉悦体验背后&#xff0c;是日益增长的存储和分享压力。大视频文件不仅占用大量存储空间&#xff0c;上传和下载也变得异常缓慢。那么&#xff0c;如何才能有效压缩视频&#xff0c;…

SAP中的 UPDATA TASK 和 BACKGROUND TASK

前言&#xff1a; 记录这篇文章起因是调查生产订单报工问题引申出来的一个问题&#xff0c;后来再次调查后了解了其中缘由&#xff0c;大概记录以下&#xff0c;如有不对&#xff0c;欢迎指正。问题原贴如下&#xff1a; SAP CO11N BAPI_PRODORDCONF_CREATE_TT连续报工异步更…

LoadRunner-Virtual User Generator组件学习(录制不上内容)

重点知识 LR工具是拿C写的&#xff0c;所以它的脚本默认也是C&#xff0c;但是最终生成的脚本不止是C&#xff0c;它是支持C和Java语言的&#xff0c;这个大家要清楚&#xff0c;对本身懂代码的就很友好&#xff0c;你了解java&#xff0c;那就可以把脚本改成java&#xff0c;…

不看后悔!国内AI大比拼的精彩看点全汇总

至2022年AI爆发后&#xff0c;在中国已催生了上千个AI产品。 这些产品涵盖了从头部大厂到高等院校&#xff0c;再到初创企业的广泛阵容。 如&#xff1a; 大厂&#xff1a;百度文心、阿里通义、腾讯元宝、字节豆包、讯飞星火等高校&#xff1a;清华大学、北京大学等初创&…

.NET 漏洞分析 | 某ERP系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

JAVA导出数据库字典到Excel

文章目录 1、查询某张表字段信息2、TableVo接收sql查询得到的数据3、excel导出4、导出案例 1、查询某张表字段信息 select column_name as columnName, -- 字段名 COLUMN_DEFAULT as colDefault, -- 默认值 column_key as columnKey, -- PRI-主键&#xff0c;UNI-唯一键&…

机器学习原理之 -- 朴素贝叶斯分类器:由来及原理详解

朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类器是一类基于贝叶斯定理&#xff08;Bayes Theorem&#xff09;的简单而有效的概率分类算法。由于其假设特征之间的条件独立性&#xff0c;因此被称为“朴素”贝叶斯分类器。尽管这种独立性假设在现实中很少完全成立&#xf…

VSCode使用ipynb文件高效地进行功能测试

一、ipynb是什么文件 .ipynb文件是Jupyter Notebook的专用格式&#xff0c;它允许用户在一个网页应用中混合编写Markdown文本、执行代码、查看输出结果及图表。Jupyter Notebook的本质是一个Web应用程序&#xff0c;支持运行40多种编程语言&#xff0c;包括Python。它的主要用…

Elasticsearch运维系列_ES之max_result_window 含义-对性能影响及参数调整

如果你觉得这篇文章能给你带来收获&#xff0c;请关注我公众号: 这篇文章主要给大家介绍max_result_window参数及其对性能影响。 Part1 背景描述 当前某个业务xxxdb单个索引值较大&#xff0c;每日单个索引大小在二三百G&#xff0c;当前索引保留15天&#xff0c;如果拉取一个…

初入Node.js必备知识

Node.js因什么而生&#xff0c;作用是干什么&#xff1f; Node.js是一个用c和c打造的一个引擎&#xff0c;他能够读懂JavaScript&#xff0c;并且让JavaScript能够和操作系统打交道的能力 JavaScript 原本只能在浏览器中运行,但随着Web应用程序越来越复杂,仅靠客户端JavaScri…

零基础入门怎么学习老挝语字母表?《老挝语翻译通》App真人发音教学,学习老挝语字母发音和词汇句子!

这段老挝文字翻译成中文是什么意思&#xff1f;有什么好用的老挝语翻译工具推荐吗&#xff1f; 快速翻译&#xff1a;中老语言无缝转换&#xff0c;实时翻译&#xff0c;让沟通更流畅。 学习工具&#xff1a;零基础入门到流利对话&#xff0c;老挝语真人发音&#xff0c;让你的…

MacOS 安装 mtr 网络检测工具

Install sudo brew install mtr sudo chown root $(which mtr) sudo chmod us $(which mtr) sudo chown root $(which mtr-packet) sudo chmod us $(which mtr-packet) Test mtr google.com

Build a Large Language Model (From Scratch)附录E(gpt-4o翻译版)

来源&#xff1a;https://github.com/rasbt/LLMs-from-scratch?tabreadme-ov-file https://www.manning.com/books/build-a-large-language-model-from-scratch

VTK学习日志:基于VTK9.3.0+Visual Studio c++实现DICOM影像MPR多平面重建+V R体绘制4个视图展示功能的实现(二)

前段时间对VTK9.3.0进行了编译&#xff0c;开发了MPRVR实现的demo,显示效果不是很理想&#xff0c;正好趁着周末有时间&#xff0c;再度对之前的程序进行优化和完善&#xff0c;先展示下效果&#xff1a; VTK实现MPRVR四视图 再次讲解下基于VTK的MPRVR实现的简单项目创建过程&a…

Kamailio-命令行指令kamctl与kamcmd

前文也有提到几种指令的用处&#xff0c;与web页面相比&#xff0c;它就是更原始、面向运维的&#xff0c;正常如果有管理页面也需要使用到&#xff1a; kamailio - SIP 服务器脚本kamdbctl - 创建和管理数据库的脚本&#xff0c;比如你使用MySQL作为其存储时就需要使用到这个…