无源protobuf二进制流反序列化学习

      最近分析软件的时候经常会遇到protobuf相关的数据结构,但是逆向的时候,没办法找到相关的proto文件,只能直接通过二进制流来找到相关含义,其实逆向正常也不需要那些,能够解析出数据就行了,数据名称无所谓。所以有了这篇文章。

       首先找个protobuf的结构来看一下,这里就以微信发送文本消息为例:

protobuf的二进制流格式是key :long:value的格式。符合tlv标准,(type,long,value)key包含了两个部分,一个是标签号部分,一个是类型部分,通过如下运算得到:

 key = tag<<3|type

  type可能如下:

所以type和tag可以通过反推得到:

type = key&0x7

tag = key>>3 - type

那么key = 0x08可得:type = 0x08|0x07 = 0,tag = 0x08>>3 - 0 = 0x01;即第1个参数的值为varint,varint通常为1个字节,所以不用携带long数据了,直接可得value为:

注意这里的key长度不一定为一个字节,如果tag小于16占一位,否则占两位,即判断当前key小于7时,说明key占两个字节,需要连接下一个key一起计算。

Google提供了官方的直接解析工具,可以在没有proto的情况下解析:

https://github.com/protocolbuffers/protobuf/releases/

下载响应版本就行,我下载的windows版本的,而后参考网上的一篇python脚本把需要反序列化的文件反序列化就行,参考链接如下:

https://blog.csdn.net/lwanttowin/article/details/77229000

# -*- coding: utf-8 -*-
"""
Created on Mon Dec  9 14:27:41 2019

@author: liuti
"""
import subprocess
def decode(data):
    process = subprocess.Popen([r'C:\Users\liuti\Downloads\protoc-3.11.1-win64\bin\protoc', '--decode_raw'],
    stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
 
    output = error = None
    try:
        output, error = process.communicate(data)
    except OSError:
        pass
    finally:
        if process.poll() != 0:
            process.wait()
    return output
 
f = open("writebuff.txt", "rb")
data = f.read()
print (decode(data))
f.close()

这里因为经常都是用Android studio 调试的,里面会有buffer数组,我都是直接把需要分析的数组拷到一个文件中,然后用个脚本把他转换成二进制文件就行,脚本如下:

# -*- coding: utf-8 -*-
"""
Created on Tue Sep 10 14:58:46 2019

@author: liuti
"""
import re
import struct
pattern = '0x[A-Za-z0-9_]*'
f = open('aa.txt') #input
fb = open('binary.bin','wb') #output

contents = f.readlines()
for line in contents:
    #print(line)
    s1 = re.search(pattern,line)   
    
    print(s1.group())
    char = int(s1.group(),16)
    if char>127:
        char = char - 256
    bi = struct.pack('b',char)
    fb.write(bi)
    
f.close()
fb.close()

发布了40 篇原创文章 · 获赞 22 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/liutianheng654/article/details/103458724