FMS RTMP协议

来源:互联网 发布:python rest api 编辑:程序博客网 时间:2024/06/06 02:18

一、握手

FMS就是Flahs Media Server的缩写

要准备的一些工具有IDA、SoftIce、抓包工具(WSocket Expert)

IDA主要是用来做静态分析的,SoftIce主要是做动态分析,用抓包工具来抓收到和发送的网络数据

参考的代码有一个开源的FMS的代码,Java写的Red5

以上都准备好了就可以开始分析FMS的协议了,过程最好是先看看代码,然后静态分析,最后再用SoftIce做动态跟踪这样研究的速度就快多了。

(一)关于Flash Player和服务器端的握手

握手的过程是客户端向服务器端发送一个长度为600h长的数字签名的字符串到服务器端,然后服务器回应一个600h长的服务器端的数字签名字符串,连同客户端的数字签名一起回传给客户端,完成第一步的连接过程

客户端发送消息描述

struct connect_message{

byte header;//0×03

dword systemtime;//系统时间是用getsystemtime取到的

dword reserver;//都是零

byte* pcsign;//长度为600h的数字签名

} ;

服务器端发送消息描述

struct connect_message{

byte header;//0×03

dword systemtime;//系统时间是用getsystemtime取到的

dword reserver;//都是零

byte* pssign;//长度为600h的数字签名

byte* pcsign;//长度为600h的

} ;

这里通过分析发现生成数字签名的算法是用系统时间做一个种子,然后通过下面的运算计算出来的一个长度为600h的数字签名串运算的python脚本如下

def test():
const = 0xB8CD75
al = 0×87
for i in range(0,300):
if al > 127:
al = 256-al
al = -al
al = al*const
al += 1
else:
al = al*const
al += 1
if( al < 0 ):
al -= 1
al = al | 0xFFFFFF00
al += 1
al = al & 0xFF
print '%x' % (al & 0xFF)
else:
al = al & 0xFF
print '%x' % (al & 0xFF)

注意的是生成的一个字节添充到2*i的内存中所以这里一共要做300次循环就可以了

(二)客户端发起连接

用收到的服务器端的数字签名生成一个连接消息,然后把客户端的一些基本的消息发送给服务器端用来连接
struct connect_message{

byte* pssign;//长度为600h的数字签名

byte* message;//发送的消息数据
} ;

发送的消息数据参考red5中的消息代码(RTMPProtocolDecoder.java)

消息体大概的结构如下

struct message{

byte headsize : 2;//第一个字节的头两位

byte channelid : 6;//第一个字节的后6位

dword timer : 24; //三个字节表示的时间信息

dword long : 24;//三个字节表示的长度

byte datatype ://数据类型

dword streamid;//流标识

byte* data;//消息数据体

}

(三)服务器返回状态消息

服务器返回连接状态,连接握手结束

二、关于视频捕捉的协议

(一)概述
握手完成后下面要按照RTMP协议进行数据的传输,跟一般的协议相同一般数据流都由下以下的数据结构,[协议头][协议数据][消息数据]。
(二)协议头
协议头主要有两个结构组成
type : 2 (主要跟协议数据有关)
channel : 6 (参考red5表示channel)
(三)协议数据
type协议数据0(Protocol newstrean)timestamp : 24 (时间戳)bodysize : 24 (消息体长度)
datatype : 8 (数据类型)
stream_id : 32 (数据流标识)
1(Protocol samestream)timestamp : 24(时间戳)bodysize : 24 (消息体长度)
datatype : 8 (数据类型)
2(Protocol timechage)timestamp : 24(时间戳)3(Protocol continue)没有多余的数据(四)datatype的类型
主要参考red5中的类型说明
类型说明CHUNK_SIZE(0×01)
UNKNOW(0×02)
BYTES_READ(0×03)
PING(0×04)
SERVER_BANDWIDTH(0×05)服务器带宽(4字节)125000(125k)CLIENT_BANDWIDTH(0×06)客户端带宽(服务器端:5字节,最后一个应该是channel的值,客户端:4个字节)125000(125k)UNKNOW(0×07)
AUDIO_DATA(0×08)音频流数据VIDEO_DATA(0×09)视频流数据一般是一帧UNKNOW(0×0A)
UNKNOW(0×0B)
UNKNOW(0×0C)
UNKNOW(0×0D)
UNKNOW(0×0E)
UNKNOW(0×0F)
UNKNOW(0×10)
UNKNOW(0×11)
METADATA(0×12)
SHARED_OBJECT(0×13)
INVOKE(0×14)调用的脚本数据,包括一些参数和调用的AS脚本(五)视频捕捉协议流
首先参考上一篇技术文档,完成握手并发送相关的Invoke脚本后客户端(C),服务器端Server(S)
(1)(C)Recv以下几组数据
SERVER_BANDWIDTH(0×05)<=>CLIENT_BANDWIDTH(0×06)<=>PING(0×04)
(2)(C)Recv
PING(0×04)<=>还有上一步发送的Invoke数据的回调Invoke脚本确认成功后发送下面数据
(3)(C)Send
CLIENT_BANDWIDTH(0×06)一般直接返回服务器的建议值
(4)(C)Send
Invoke脚本(创建视频流对象)
(5)(C)Recv
Invoke脚本(创建视频流对象结果)
(6)(C)Send
Invoke脚本(创建视频流对象结果)
(7)C(Send)
Invoke脚本(Netstream的方法)
(8)C(Recv)
PING(0×04)<=>Invoke脚本(Netstream的方法调用的结果)(收到两个一个是Public.Start,一个是Record.Start)
(9)C(Send)
VIDEO_DATA(0×09)

三、Invoke数据流

(一)概述

invoke中使用大量的ActionScript中的数据类型或做为参数,或作为变量

(二)类型说明(参考Red5)

(1)String(字符串类型)=0×02

length : 2字节

string : length

(2)object(对像类型)=0×03

嵌套定义的基本类型

end : 1字节(0×09)