前言:
这里主要是介绍PHP序列化和PHP反序列化的基础知识,绝对可以说是基础中的基础,后期等我变强了,我再来完善。
前置知识:
PHP类与对象:如何用C语言的思维学PHP
类是定义一系列属性和操作的模板,而对象,就是把属性进行实例化,完事交给类里面的方法,进行处理。
这段文字是我在别的博客里看到的,说实话,很抽象,或者说,压根就看不懂。而在经过了多天的学习之后,我也有了自己的理解。因为没有学过PHP语言,但是我觉得无论是PHP序列化还是PHP反序列化,其实都跟c语言中结构体与共用体再加上函数的用法很像。
我们先来看一看一个基本的PHP反序列化代码
<?php
class CTFer{
//class 类名,就是用来定义一个类
public $name = 'xiawei'; //public表示所有人可见(公共),当然还有别的知识点,比如Protected表示外部不可引用;Private表示仅内部可以使用;name是CTFer这个类的属性。
public function nb(){
//定义类方法(类似函数),这里真的就跟函数一毛一样,比如我们c语言中的void f()
echo $this->name." very nb\n"; //这里面要写的就是方法的内容
}
}
$a = new CTFer(); //根据CTFer类实例化对象,其实也跟c语言的函数很像,不就是在函数编写完之后int a; int b之类的创造一个新的变量。
$a->nb();//这里就是让类来使用这个类方法,应该是那么说的吧,不够专业,但是意思差不多。
?>
输出:xiawei very nb
看到这里的时候,其实我第一时间就想到了c语言里的两个东西
#include<stdio.h>
#include<string.h>
struct student //这个命令就相当于class,创造了一个类名
{
char name; //这就相当于定义类的属性
int age;
char sex;
}
void f()
{
//这就是相当于定义了一个方法,等于public function 方法名(),跟函数的定义是类似的
}
$a = new 类名();// 实例化对象
//成员属性赋值
$a -> name = "伟子";
$a -> sex = "男";
$a -> age = 20;
//访问对象中的成员方法
$a->方法名();
正文:PHP序列化及PHP反序列化简述
首先什么是序列化呢?
将一个对象转换为字符串
那么什么又是反序列化呢?
将一个字符串恢复成对象
下面是一些魔术方法(虽然我只会看_sleep和_wakeup)
__construct: 在创建对象时候初始化对象,一般用于对变量赋初值。
__destruct: 和构造函数相反,当对象所在函数调用完毕后执行。
__toString:当对象被当做一个字符串使用时调用。
__sleep:序列化对象之前就调用此方法,当在类的外部调用serialize()时会自动被调用(其返回需要一个数组)
__wakeup:反序列化恢复对象之前调用该方法,当执行unserialize()方法时会被自动调用 // __wakeup绕过的方法最简单,就是直接修改属性长度大于原长度
__call:当调用对象中不存在的方法会自动调用该方法。
__get:在调用私有属性的时候会自动执行
__isset():在不可访问的属性上调用isset()或empty()触发
__unset() :在不可访问的属性上使用unset()时触发
__invoke():当脚本尝试将对象调用为函数时触发
__callStatic():在静态上下文中调用不可访问的方法时触发
PHP反序列化
要讲到PHP的序列化和反序列化,还得用到我这次在攻防世界里做到的一道题目
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
这道题目呢看到_wakeup的时候,就已经想到了PHP反序列化,这是因为unserilize()对应的魔术方法就是_wakeup,因此这道题我们要将xctf这个类反序列化
<?php
class xctf{
public $flag= '111';
public function __wakeup(){
exit('bad requests');
}
}
$a=new xctf;
echo serialize($a);
?>
输出为
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
绕过__wakeup的方法也很简单,只要将属性个数修改成大于原值即可。
serilize()方法是将一个对象转化成字符串,对应的魔术方法是__sleep
unserilize()方法是将字符串转化成对象。独影的魔术方法是__wakeup
PHP序列化
<?php
class CTFer{
public $team = "GOGOGO";
private $team_name = "nbnbnb";
protected $team_group = "lalala";
function hahaha(){
echo $this->$team_name ."奥力给";
}
}
$CTFer = new CTFer();
echo serialize($CTFer);
?>
输出结果为
O:5:"CTFer":3:{s:4:"team";s:6:"GOGOGO";s:16:"CTFerteam_name";s:6:"nbnbnb";s:13:"*team_group";s:6:"lalala";}
O:表示对象(object)
5:对象名称的长度
CTFer:对象名称
3:表示对象里属性的个数
s:属性名类型
4:属性名长度
team:属性的名称
s:属性值的类型
6:属性值的长度
GOGOGO:属性值
s:属性名类型
16:属性名长度
CTFerteam_name:属性的名称
s:属性值的类型
6:属性值的长度
nbnbnb:属性值
s:属性名类型
13:属性名长度
*team_group:属性的名称
s:属性值的类型
6:属性值的长度
lalala:属性值
需要注意的是变量受到不同修饰符(public,private,protected)修饰进行序列化时,序列化后变量的长度和名称会发生变化。
- 使用public修饰进行序列化后,变量$team的长度为4,正常输出。
- 使用private修饰进行序列化后,会在变量$team_name前面加上类的名称,在这里是CTFer,并且长度会比正常大小多2个字节,也就是14+2=16。
- 使用protected修饰进行序列化后,会在变量$team_group前面加上*,并且长度会比正常大小多3个字节,也就是10+3=13
总结:
以上只是最原始和基础的PHP序列化和反序列化的入门,等我变强了,我再回来接着写。