目录
TcpEngine是什么?
在网络通信协议中,主要有两类数据,一类是字符串数据类型,如http协议;另一类是根据业务需求,自定义格式的数字流类型,比如游戏协议等。目前主流的网络数据分析工具主要有两类,一类是对字符串数据类型的分析,如Charles,Fiddler等;另一类截取网络底层数据包,对网络底层行为的分析,如Wireshark。TcpEngine补充没有针对数字流协议分析的空白,提供了一套分析数字流协议分析方案,网官地址:http://www.tcpengine.cn
TcpEngine有什么用?
当您的网络应用在开发和测试阶段,如果发生网络数据错误,可用TcpEngine监听拷贝现场网络数据,再根据您的协议格式编写解析规则解析网络数据,还原网络现场。
当您的网络应用已经交布到客户现场,当发生网络数据错误时,也可使用TcpEngine监听拷贝现场网络数据,保存到文件,再拿回给开发人员解析,还原网络现场。
如果您的网络数据已经加密,可以按照规范封装解密库,解密数据成正常数据后再解析。
运行软件
这个版本仅在win10 64开发测试,建议在WIN10 64平台下运行,运行需要WFP内核模支持,因此第一次运行需要安装WFP内核模块(对WFP内核模块源代码感兴趣可到官网下载)。运行软件前需要对系统做一些准备工作,详细说明请访问:http://www.tcpengine.cn/tcp_engine/1_1_x_docs.html
TcpEngine的功能
编程式解析规则
数字流协议的特点是不同的应用定义的格式不同,具有千变万化的特点, 面对这样的特点,TcpEngine提供的解决方案是编程式的解析规则,比如有一款协议格式如下图所示。
对应的解析规则如下。
int32 id; // 四个字节int型消息ID
int32 msgLen; // 四个字节int型消息体长度
byte[msgLen] body; // 长度可变的消息体....
如果所有的协议都是相同的格式,可以使用while循环以相同格式解析所有网络数据,如下所示。
while(1 == 1){
int32 id; // 四个字节int型消息ID
int32 msgLen; // 四个字节int型消息体长度
byte[msgLen] body; // 长度可变的消息体....
}
如果有一个id=1000消息的消息体如下图所示。
对应的完整解析规则如下。
set endian = big; // 设置网络数据字节序
set encoding = utf-8; // 设置字符串编码
while(1 == 1){
int32 id; // 四个字节int型消息ID
int32 msgLen; // 四个字节int型消息体长度
byte[msgLen] body; // 长度可变的消息体....
if(1000 == id) {
int32 userId = body.split();
text[msgLen-userId.size()] = body.split();
}
}
解析网络数据前如下图所示。
解析网络数据后如下图所示。
支持算术表达式
一、有的使用场景需要算术表达式支持,如有的网络协议需要简单的算述运算。比如有的协议长度变量值是:协议头 + 协议体,那么我们在解析协议体时需要减去协议头长度,使用示例如下。
int32 id; // 四个字节int型消息ID
int32 msgLen; // 四个字节int型消息体长度
byte[msgLen - 8] body; // 协议体长度 = 长度变量 - 协议头长度
二、另外一种是解析规则本身需要,比如前三条的协议格式一样,后面的协议格式是另外的格式,那么解析规则如下。
int32 loop = 0;
while(loop < 3){ //循环三次,解析前面三条协议
loop++;
int32 id; // 四个字节int型消息ID
int32 msgLen; // 四个字节int型消息体长度
byte[msgLen] body; // 长度可变的消息体....
if(1000 == id) {
int32 userId = body.split();
text[msgLen-userId.size()] = body.split();
}
}
// 接着后续的协议
支持tcp和websocket(第13版)网络协议
websocket是H5解决长连接的标准,在tcp长连接的基础上加上协议头和加密算法形成的公开标准,越来越多的项目都使用这种协议。
TcpEngine默认是自动检测网络数据是否带有websocket协议特征,如果发现满足websocket特征,则自动采用websocket协议解密成正常数据,解使用解析规则解析。
参数set protocol 用户设置网络协议,共有三个可选值,分别如下。
tcp :强制原始tcp协议。也就是不做任何处理就交给解析规则。
websocket :强制先websocket协议解密,再交给解析规则,解密失败如下图所示。
auto :让工具根据网络数据特征自动选择网络协议,这个参数不设置默认设置这个值。
网络现场和分析现场可相互独立
这个特点大多数网络分析工具都具备,就是把网络数据保存到文件,再交给技术人员重新打开,通过解析规则分析,重现网络错误现场,当然如果是开发人员在现场,也可以在网络现场边接收数据边分析。
TcpEngne用户可见和操作的文件是tcpd文件,在开始监听网络或打开tcpd文件时,会在文件目录下生成一个临时文件tcpt。tcpt文件默认预分配4G空间,接收的网络数据不能超过这个大小,当监听结束或正常退出工具,会自动删除这个文件,异常退出不会删除,需要您人工删除。
按下面步骤监听网络数据
一、在“面板”窗口点击“新建”如下图所示。
二、点击“开始”>> 填入要监听的网络信息 >> 再点击“接收不解析”,如下图所示。
成功监听网络数据,在“本地日志”窗口出现如下图所示日志。
三、此时,您可以正常使用您的应用正常网络通信了,TcpEngine会把您应用的数据拷贝一份到这里来,如果没有解析规则就显示十六进制原始数据,如下图所示。
四、此进您可以点击“保存”按钮或按 ctrl + s 保存数据到文件,如下图所示,这时,您可以把这个文件发给技术人员重新打开解析了。
加密数据的支持
在实际应用场景中,多数应用都会对通信数据进行加密,以保证数据的安全。TcpEngine对加密数据的解决方案是,由您按TcpEngine的规范,把解密算法封装到动态链接库里,在解析时,设置网络参数指向您的解密库,在解析时先由您的解密库解密网络数据成正常数据,再由解析规则解析。
设置解密库的参数是 set decode 一个典型的解析库设置如下图所示,指定解密库是D:\work\TcpEngineDecode\x64\Debug\TcpEngineDecode,发送数据解密参数是para。
为什么提供解密参数?解密算法是您的核心机密,在您封装解密库时,可以在解密算法中加入密码,在解析规则中动态传入,如本例的para,这样,即使别人得到您的数据和您的解密库,也无法分析您的数据。
解密库的开发
解密库开发规范分两类接口,一类是由解密库实现,提供给TcpEngne的接口,另一类已由TcpEngine实现,提供给解密库的接口。
由解密库实现的接口有五个,分别如下所示,本段建议结合示例源代码(FlamingoDecode.zip)阅读,下载链接:https://pan.baidu.com/s/1s-QfEnRkpo1Sx8tttUA1uw 提取码:pmt1
extern "C" _declspec(dllexport) int initDecode(void* pTcpEngineObj, funInform informFun)
extern "C" _declspec(dllexport) int initSend(const char* pszPara)
extern "C" _declspec(dllexport) int initRecv(const char* pszPara)
extern "C" _declspec(dllexport) int freeDecode(void)
extern "C" _declspec(dllexport) int decodeSend(const char* pszInBuf, int iInSize, IDecodeBuf * pDecodeBuf)
extern "C" _declspec(dllexport) int decodeRecv(const char* pszInBuf, int iInSize, IDecodeBuf* pDecodeBuf)
TcpEngine调用过程
一、如果发送解析窗口设置了set decode 或接收窗口设置 set decode 就加载解密库,并调用 initDecode 接口。传入参数 pTcpEngineObj 指向TcpEngine;informFun 由TcpEngine提供给解密库调用的参数。
二、如果发送解析规则窗口设置了 set decode 则调用 initSend 传入参数指向传入参数,如上例中的 para 字符串,没有则是nullptr。
三、如果接收解析规则窗口设置了 set decode 则调用initRecv 。
四、解密发送数据调用 decodeSend 参数说明pszInBuf 指向解密前原始数据,iInSize 解密前数据大上,pDecodeBuf 回传解密后的数据接口。
五、解密接收数据调用 decodeRecv 接口。
当停止解析网络数据时,会卸载解密库,卸载前会调用 freeDecode 您可以这里释放您分配的资源。
由TcpEngine给解密库调用的接口两个,分别是上面 decodeSend 和 decodeRecv 的输出参数 IDecodeBuf * pDecodeBuf,当您的数据解密成正常数据后,调用这个接口回传给TcpEngine,每回传一次,在TcpEngine就生成一行新的数据。接口参数有两个 pszBuf 指向解密后的数据,iBufSize 解密后数据的大小。
另一个接口是向TcpEngne打印日志 sendMessage("开始解包", strlen("开始解包"), ERR_LEVEL_TEXT); 这个接口的效果如下图所示。
解密库开发及使用示例
这里以开源的IM软件flamingo,源码托管地址 https://gitee.com/balloonwj/flamingo,演示说明如何对加密数据进行解码和解析。
本例对应的解码库代码FlamingoDecode.zip,原始的解码库代码TcpEngineDecode.zip,示例的tcpd文件flamingo.tcpd, 示例的解密库TcpEngineDecode.dll
下载链接:https://pan.baidu.com/s/1s-QfEnRkpo1Sx8tttUA1uw 提取码:pmt1
解析前网络数据显示如下图所示,加密的原始网络数据几乎不能阅读。
经过解密库解密并使用解析规则分析后变成可阅读数据如下图所示。