魔术方法是反序列化的基础,而且在CTF中,序列化题目,你说我有什么理由不学习反序列化呢!!! ![1](https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3296012127,32476798&fm=26&gp=0.jpg) 魔术方法是在php中,以两条下划线开头的函数称为魔术方法!!! 学习反序列化的前提就是要对常见的魔术方法有一个了解,魔术方法目前包括16个:
```php
__construct():构造函数
__destruct():析构函数
__call():当调用了一个不存在的方法时被调用
__callStatic():当使用静态方式调用不可用方法时被调用
__get():当访问了
__set():
__isset():
__unset():
__sleep():
__wakeup():
__toString():
__invoke():
__set_state():
__clone():
__autoload():
__debuginfo():
```
__construct(): 构造函数 构造函数主要是用于执行初始化的作用,如例子所示:
```php
class Fun{
public $vula;
public $vulb;
public function __construct($vula){
$this->vulc=$vula;
}
public function get(){
echo $this->vulc;
}
}
$fun = new Fun('asd');
echo $fun->get();
```
```php
现在我传给了$vula
```
在__construct()中已经构造好了,构造好了之后,即可全局使用,看了看这个函数,像极了python中的__init__,如码所示👇
```python
class Fun:
def __init__(self,name,age):
self.name = name
self.age = age
def echo(self):
print('大家好,我是'+self.name+',今年已经'+self.age+'岁了')
fun = Fun('vFREE','19')
fun.echo()
# 大家好,我是vFREE,今年已经19岁了
```
#__destruct():析构函数
析构函数相反与构造函数,构造函数是初始化,那么析构函数就是销毁而存在的一个函数
```php
class Fun{
public $vula;
public $vulb;
public function __construct($vula){
$this->vulc=$vula;
}
public function __destruct(){
echo '执行完成,该类已被销毁啦~';
}
}
$fun = new Fun('现在我传给了$vula');
$fun;
```
```php
执行完成,该类已被销毁啦~
```
#__call():
当在外部调用了一个不存在的类中的函数时,就会抛出错误,__call就很好解决了这个问题,只需要在类中定义一个__call即可,但是__call要带两个参数,一个是不存在的函数,一个是不存在的函数的内容
```php
class Fun{
public $vula;
public $vulb;
public function __construct($vula){
$this->vulc=$vula;
}
public function __call($value_a,$value_b){
echo "你所调用的函数".$value_a.'不存在,参数:';
print_r($value_b);
echo '也不存在\n';
}
}
$fun = new Fun('现在我传给了$vula');
$fun->asd(1,2);
```
#__callStatic()
但是用静态方法调用一个不存在的函数时,就会被调用
```php
class Fun{
public $vula;
public $vulb;
public function __construct($vula){
$this->vulc=$vula;
}
static function __callStatic($value_a,$value_b){
echo "你所调用的函数".$value_a.'不存在,参数:';
print_r($value_b);
echo '也不存在\n';
}
}
$fun = new Fun('现在我传给了$vula');
$fun::asd(1,2);
```
使用 类名::函数名 则代表着用静态方法调用,类中的__callStatic()要用static修饰,否则会报错警告(*BI WARGING)
#__get
当外部调用类中一个不存在的变量时,将会被调用,其中包含一个参数,即__get($value)
```php
class Fun{
public $vula;
public $vulb;
public function __construct($vula){
$this->vulc=$vula;
}
public function __get($values_c){
print($values_c.'不存在');
}
}
$fun = new Fun('现在我传给了$vula');
$fun->vuld;
```
```php
vuld不存在
```
#__set()
当外部要更改类里面的私有属性时,就会被调用,__set($values_a,$values_b)
$values_a是属性名
$values_b是属性值
```php
class Fun{
public $vula;
public $vulb;
private $vuld;
public function __construct(){
print('');
}
public function __set($values_c,$values_d){
print($values_c.'是不可变的,所以');
print($values_d.'是无法设置到'.$values_c);
}
}
$fun = new Fun();
print($fun->vuld=123);
```
```php
vuld是不可变的,所以123是无法设置到vuld123
```