最近分析软件的时候经常会遇到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()