我们知道现在各大语言都有其序列化数据和反序列的方式,
比如php的serialize和unserialize函数
Python当然也有,官方库里提供了一个叫做pickle的库
字符串的序列化解释
import pickle
x = "yuaneuro"
y = pickle.dumps(x) # 序列化
print(y)
上面例子中pickle序列化python的一个字符串
运行结果:
b'\x80\x03X\x08\x00\x00\x00yuaneuroq\x00.'
解释:
最前面的b' ' 表示这是一个 bytes 对象
第一个字符\x80是一个操作码,是识别pickle协议
\x03就代表了pickle版本为第三版(python3实现的版本是第三版)
\x08\x00\x00\x00,值为8,表示后面的utf8编码的字符串的长度为8,即yuaneuro的长度为8
在后面接yuaneuro
再往后是q\x00,给参数做索引用
最后的.代表结束
元组(tuple)的序列化解释
import pickle
x = ('bar','foo')
y = pickle.dumps(x) # 序列化
print(y)
上面例子中pickle序列化python的一个元组
运行结果:
b'\x80\x03X\x03\x00\x00\x00barq\x00X\x03\x00\x00\x00fooq\x01\x86q\x02.''
解释:
前面的字符串的序列化一样
在两个字符串的结尾加了\x86操作码,意思是"利用栈顶的两个元素(即bar和foo)建立一个元组
q\x02标识该元组在memo的索引
列表(list)的序列化解释
import pickle
x = ['bar','foo']
y = pickle.dumps(x) # 序列化
print(y)
上面例子中pickle序列化python的一个列表
运行结果:
b'\x80\x03]q\x00(X\x03\x00\x00\x00barq\x01X\x03\x00\x00\x00fooq\x02e.'
解释:
在\x03的后面是一个]
操作符,意思是在栈上建立一个空list
q\x00是这个列表在memo的索引
从(
开始到e
操作符前面的内容用来构建list
字典(dict)的序列化解释
import pickle
x = {'name':'yuaneuro', 'age':'20'}
y = pickle.dumps(x) # 序列化
print(y)
上面例子中pickle序列化python的一个字典
运行结果:
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x08\x00\x00\x00yuaneuroq\x02X\x03\x00\x00\x00ageq\x03X\x02\x00\x00\x0020q\x04u.'
解释:
在\x03的后面是一个}
操作符,意思是在栈上建立一个空dict
q\x00表明了这个dict在memo区的索引
从}
开始到u
操作符前面的内容用来构建dict
类(class)的序列化解释
import pickle
class Student(object):
name = 'yuaneuro'
age = '20'
y = pickle.dumps(Student())
print(y)
上面例子中pickle序列化python的一个类
运行结果:
b'\x80\x03c__main__\nStudent\nq\x00)\x81q\x01.'
解释:
c
操作符,用来导入模块中的标识符,模块和标识符之间用\n
隔开
那么这里的意思就是导入了main模块中的Student
类
q\x00代表了Student类在memo的索引
随后是)
在栈上建立一个新的元组,这个元组存储的是新建对象时需要提供的参数,因为本例中不需要参数,所以这个元组为空
\x81操作符,该操作符调用cls.__new__
方法来建立对象,该方法接受前面元组中的参数
介绍完这些,我将在下一篇博客中介绍反序列化漏洞
及其任意代码执行