JS逆向-Protobuf逆向解析

35 篇文章 0 订阅

目录

一、python快的解析Protobuf方式
  • 注意:目录二、三、四、五可以作为了解,实际上目录一就可以解决了,比后面的解决方式更便捷,后面介绍的解决方式的前提是还原.proto文件。如果解决不了的话,再看二、三、四、五也可
  • 1、问题案例:请求参数和响应参数都是序列化的数据结构,不易读。两个名词序列化(将正常可读数据转为protobuf的数据结构,看似是乱码的形式),非序列化反之
    在这里插入图片描述
    在这里插入图片描述
  • 2、解决方案:
    • 依赖安装:pip install blackboxprotobuf

    • 如果要将数据转为序列化数据,则需先确认message_type(Type information including field number, field name and field type),如何确认message_type,我们可以将非序列化的数据复制下来,如下赋值给a变量,然后可以得到消息类型message_type;如果下面代码无法运行,a变量的这个数据换成你自己的

      import blackboxprotobuf
      a = "?2???2?? ·??".encode()
      deserialize_data , message_type =blackboxprotobuf.protobuf_to_json(a)
      print(deserialize_data )  # 非序列化的原始数据
      print(message_type)  # 消息类型结构
      
    • 将数据序列化样例如下,有了消息类型message_type,我们就可以将数据转为序列化数据了,如下

      import blackboxprotobuf
      message_type = {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}, '3': {'type': 'int', 'name': ''}, '4': {'type': 'int', 'name': ''}}
      before_data = {'1': 1, '2': 312312312442, '3': 8709708978, '4': 78971987}
      form_data = blackboxprotobuf.encode_message(before_data, message_type)
      print(form_data)
      
    • 将数据非序列化样例如下,直接传入字节content,即可输出json

      import blackboxprotobuf
      content = b'??)?) ?(?#0?(8?"@tBHò:Pí'
      print(blackboxprotobuf.protobuf_to_json(content))  
      # ('{
        "1": "3231",
        "2": "5308",
        "3": "5289",
        "4": "3231",
        "5": "4486",
        "6": "5191",
        "7": "4385",
        "8": "8574",
        "9": "7506",
        "10": "461"
      }', {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}, '3': {'type': 'int', 'name': ''}, '4': {'type': 'int', 'name': ''}, '5': {'type': 'int', 'name': ''}, '6': {'type': 'int', 'name': ''}, '7': {'type': 'int', 'name': ''}, '8': {'type': 'int', 'name': ''}, '9': {'type': 'int', 'name': ''}, '10': {'type': 'int', 'name': ''}})
      
    • 最终解决如下:
      在这里插入图片描述

二、什么是Protobuf
  • 1、protocol buffers介绍:是一种语言无关、平台无关、可扩展的序列化结构数据的方法。严格说不算是加密,只能是叫序列化结构数据,让可读变为疑似的乱码,那反序列化即让疑似的乱码变为可读

  • 2、protobuf使用流程的前提是有一个.proto文件,对逆向而言就是还原.proto文件,选择编译成相应的编程语言包,然后调用包进行序列化和反序列化

    • 比如编程语言选择python,则我们会将.proto文件先编译成python要用的python模块包(与requests等包类似)
    • 接着就是用python调用已编译的模块包进行数据的序列化和反序列化
      在这里插入图片描述
  • 3、一个网站应用了Protobuf实例

    • 如下图不管是请求参数还是响应参数,都返回了序列化的数据,虽然看似是乱码,实际上只是用Protobuf将原始数据进行了序列化,变得不可读了,我们将响应内容保存为test.bin文件
    • 当然有的会直接在headers头指明媒体类型content-type: application/grpc-web+proto,也可通过此类方法判断
      在这里插入图片描述
      在这里插入图片描述
    • 执行cmd命令protoc --decode_raw < test.bin(执行该命令,需下载解压protoc-3.19.1-win64.zip并添加bin目录为环境变量),如图结果已还原,和网站上的数据一致
      在这里插入图片描述
      在这里插入图片描述
三、Protobuf环境配置
  • 1、点击链接下载protobuf,如图下载protobuf-python-3.19.1.zipprotoc-3.19.1-win64.zip
    在这里插入图片描述
  • 2、protoc编译器安装
    • ① 解压protoc-3.19.1-win64.zip压缩包,并将该文件夹的bin目录D:Softwareprotoc-3.19.1-win64in添加到环境变量
      在这里插入图片描述
      在这里插入图片描述
    • ② 打开cmd输入protoc --version显示出版本号,则代表protoc编译器安装成功
      在这里插入图片描述
  • 3、python依赖protoc模块安装
    • ① 解压protobuf-python-3.19.1.zip压缩包,然后切换到D:Softwareprotobuf-3.19.1python目录下,打开cmd,执行如下两条命令:python setup.py buildpython setup.py install
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • ② 打开python解释器,导入import google.protobuf 可以检测protobuf模块是否安装成功,未报错即成功
      在这里插入图片描述
  • 4、vscode安装vscode-proto3插件,可以选择性安装,只是为了打开.proto文件好看点
    在这里插入图片描述
  • 5、如果报错AttributeError: 'NoneType' object has no attribute 'message_types_by_name',解决方法pip install --upgrade protobuf
    在这里插入图片描述
四、Protobuf实例序列化与反序列化

Created with Raphal 2.3.0 1、新建yrx_example.proto文件 2.0、编译yrx_example.proto文件:执行下面cmd命令生成yrx_example_pb2.py文件 2.1、cmd命令编译文件:protoc -–python_out=. yrx_example.proto 3、python代码生成序列化文件:yrx_example_person.bin文件 4.0、python代码反序列化解析文件:将yrx_example_person.bin文件输出原始的可读结果 4.1、或者cmd命令输出.bin文件可读结果:protoc --decode_raw < yrx_example_person.bin 5、逆向还原.proto文件:已知bin文件执行如上cmd命令,根据反序列化结果过可逆向还原出yrx_example.proto文件

  • 新建yrx_example.proto文件:按上数据格式用proto3语法新建yrx_example.proto文件,内容如下:如下数据有message消息类型,enum枚举类型, string字符串类型,int32整型;在消息定义中,每个字段都有唯一的一个数字标识符,也就是下面当中的1,2,3
    在这里插入图片描述

    syntax = "proto3"; // 指定使用proto3的语法, 在一个.proto文件中可以定义多个message消息类型
    
    message Person {
    
        string name = 1;   // string类型 :姓名, 标识符1
        int32 id = 2;      // 整型       :id, 标识符2
        string email = 3;  // string类型 :邮箱, 标识符3
    
        message PhoneNumber {
            string telnumber = 1;  // 电话号码
            // enum枚举类型,自定义一个PhoneType类型,每个枚举类型必须将其第一个类型映射为0(必须有有一个0值,我们可以用这个0值作为默认值)
            enum PhoneType {
                MOBILE = 0;  // 手机电话类
                HOME = 1;   // 家庭电话类
                WORK = 2;  // 工作电话类
            }
            PhoneType type = 2;
        }
    
        repeated PhoneNumber phones = 4;  // 将其他消息类型如PhoneNumber当作字段类型,如Person消息中包含PhoneNumber消息
    }
    
    message AddressBook{
        repeated Person person = 1;  // 将其他消息类型如Person当作字段类型,如希望AddressBook消息中包含Person消息
    }
    
  • 编译yrx_example.proto文件:在cmd里面输入protoc -–python_out=. yrx_example.proto,此时会在当前目录下生成yrx_example_pb2.py文件
    在这里插入图片描述

  • python代码序列化yrx_example.proto文件,并将序列化内容存到yrx_example_person.bin文件中,此时数据完全不可读即看不懂

    import yrx_example_pb2
    
    
    address_book = yrx_example_pb2.AddressBook()
    person = address_book.person.add()
    person.id = 11
    person.name = "shirmay"
    person.email = "110120119.@qq.com"
    
    phone = person.phones.add()
    phone.telnumber = "133110120**"
    phone.type = 2
    
    with open("yrx_example_person.bin", "wb") as f:
    	print(address_book.SerializeToString())  # b'
    /
    shirmay110120119.@qq.com"
    133110120**'
        f.write(address_book.SerializeToString())
    
  • python代码反序列化yrx_example_person.bin文件,还原为可读数据

    import yrx_example_pb2
    
    
    def list_people(addr_book):
        for person in addr_book.person:
            print(f"id: {person.id}")
            print(f"name: {person.name}")
            print(f"email: {person.email}")
            for num in person.phones:
                print(f"phone_num: {num.telnumber}")
                print(f"phone type: {num.type}")
    
    
    address_book = yrx_example_pb2.AddressBook()
    with open("yrx_example_person.bin", "rb") as f:
        address_book.ParseFromString(f.read())
        list_people(address_book)
    
  • 逆向分析还原.proto文件:通过上面的步骤,我们发现不管序列化和反序列化,我们首先得有.proto文件,只要有了.proto文件,我们就可以编译成python的proto模块,然后就可以正常序列化和反序列化了;所以逆向解析Protobuf的过程就是还原.proto文件

    • 已知我们有了yrx_example_person.bin文件,通过cmd执行命令protoc --decode_raw < yrx_example_person.bin即可反序列化看到左图第一版的结果,然后我们还原成中间第二版.proto文件的样子,再多次调整即可。有了.proto文件就可以正常的序列化和反序列化了
      在这里插入图片描述
五、逆向解析 Protobuf案例
1、python序列化
  • ① 如图,将序列化请求数据保存为challenge_23_post.bin文件,请求参数内容复制如下保存为.bin文件即可

    ????Y??? ?y?
    

在这里插入图片描述

  • ② 然后输入cmd命令protoc --decode_raw < challenge_23_post.bin查看反序列结果
    在这里插入图片描述

  • ③ 根据反编译结果理解,直接编写challenge_23_post.proto文件如下
    在这里插入图片描述

  • ④ 执行cmd命令protoc -–python_out=. challenge_23_post.protochallenge_23_post.proto编译生成python包challenge_23_post_pb2.py
    在这里插入图片描述

  • ⑤ 编写python代码生成序列化数据

    import challenge_23_post_pb2
    
    
    post_serialize = challenge_23_post_pb2.Ms1()
    post_serialize.filed1 = 2
    post_serialize.filed2 = 219841801546160835
    post_serialize.filed3 = 219841801546157763
    post_serialize.filed4 = 36782765818179
    print(post_serialize.SerializeToString())
    with open(r"challenge_23_post.bin", "wb") as f:
        f.write(post_serialize.SerializeToString())
    
2、python反序列化
  • ① 如图,将序列化响应数据保存为challenge_23_resp.bin文件,响应内容样例复制如下保存为.bin文件即可

    ??0?G N(? 0?8?;@?LH?"P?"
    

    在这里插入图片描述

  • ② 然后输入cmd命令protoc --decode_raw < challenge_23_resp.bin查看反序列结果
    在这里插入图片描述

  • ③ 根据反编译结果理解,直接编写challenge_23_resp.proto文件如下
    在这里插入图片描述

  • ④ 执行cmd命令protoc -–python_out=. challenge_23_resp.protochallenge_23_resp.proto编译生成python包challenge_23_resp_pb2.py
    在这里插入图片描述

  • ⑤ 编写python代码反序列化结果

    import challenge_23_resp_pb2
    
    
    resp_deserialize = challenge_23_resp_pb2.Ms2()
    with open("challenge_23_resp.bin", "rb") as f:
        resp_deserialize.ParseFromString(f.read())
        count = resp_deserialize.filed1 + resp_deserialize.filed2 + resp_deserialize.filed3 + resp_deserialize.filed4 + resp_deserialize.filed5 + resp_deserialize.filed6 + resp_deserialize.filed7 + resp_deserialize.filed8 + resp_deserialize.filed9 + resp_deserialize.filed10
        print(count)  # 47662
    
你可以使用以下命令安装 google-protobuf: npm install --save google-protobuf 这个命令会将 google-protobuf 模块安装到你的项目中,并将其保存为依赖项。 然后,你可以使用以下路径引入 empty_pb.js 模块: google-protobuf/google/protobuf/empty_pb.js 这将允许你在代码中使用 empty_pb.js 模块。请确保在你的代码中正确引入这个路径。 需要注意的是,确保你已经在安装 google-protobuf 之前完成了 protobufjs 的安装,以便确保这两个模块之间的依赖关系正确。如果你遇到了安装问题或错误提示,你可以使用 --force 选项来强制执行安装命令,以解决已存在的文件问题。 希望这些信息对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [protobuf.js的使用](https://blog.csdn.net/qq_27868061/article/details/114038738)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [npm install -g protobufjs](https://blog.csdn.net/qifenzhisanjin/article/details/124952503)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值