- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
本文围绕 Zeek 为 SMB/CIFS 版本 1 协议暴露的事件smb1_transaction_secondary_request展开,说明其事件签名、SMB1::Trans_Sec_Args参数结构、与 SMB Transaction 子协议(Transaction Subprotocol)的关系,并结合仓库中对应的 BIF 声明与 binpac 语法解析实现,梳理该事件从报文解析到 Zeek 脚本层投递的完整链路。读完本文,你将能够在 Zeek 脚本中正确挂接该事件,读懂parameters/data载荷的语义,并理解它与smb1_transaction_request如何协同还原大事务的完整数据。
事件概览:签名、命名空间与触发条件
smb1_transaction_secondary_request是 Zeek 的 SMB 分析器(位于src/analyzer/protocol/smb/)在解析 SMB/CIFS 版本 1 的transaction_secondary类型请求时生成的脚本层事件,定义在 GLOBAL 命名空间中。其完整签名如下:
event smb1_transaction_secondary_request(c: connection, hdr: SMB1::Header, args: SMB1::Trans_Sec_Args, parameters: string, data: string)依据官方生成的接口文档(Zeek_SMB.smb1_com_transaction_secondary.bif.zeek.rst),该事件:
- 为 SMB(Server Message Block)/ CIFS(Common Internet File System)版本 1的
transaction_secondary类型请求而生成; - 充当Transaction Subprotocol Commands(由 transaction 请求承载)的附加请求数据容器,即用于续传主
transaction请求未能一次携带完的参数与数据; - 对应的协议规范参考为 MS-CIFS 2.2.4.34(即
SMB_COM_TRANSACTION_SECONDARY请求结构)。
事件声明位于 smb1_com_transaction_secondary.bif,其中除了事件本身外,还声明了配套的记录类型type SMB1::Trans_Sec_Args: record;,作为args参数的承载类型。
背景:SMB1 Transaction 子协议为什么需要 secondary 请求
SMB1 的 Transaction 子协议允许客户端发起一个“事务”(如命名管道 I/O、邮件槽广播、RAP 远程管理调用等),其语义由请求中的 Setup/Parameters/Data 三部分描述。由于单个 SMB 报文存在长度上限,较大的事务数据无法一次装下。MS-CIFS 定义了两种续传机制:
SMB_COM_TRANSACTION_SECONDARY:本事件对应的报文,用于在主transaction请求之后继续追加 Parameters 与 Data 片段;- 与之对应的还有
SMB_COM_TRANSACTION2_SECONDARY(Zeek 中以smb1_com_transaction2_secondary事件族呈现,见 src/analyzer/protocol/smb 目录下同名.bif与.pac文件),面向 Transaction2 子协议。
因此smb1_transaction_secondary_request本身不携带事务的“发起信息”(如事务名称、子命令号),这些信息由先行到达的smb1_transaction_request提供;secondary 请求只负责把剩余的参数与数据“接力”送达,这也是文档中称其为“additional request data container(附加请求数据容器)”的原因。
事件参数详解
该事件的五个参数语义如下(依据官方文档与 smb1_com_transaction_secondary.bif 中的注释):
| 参数 | 类型 | 含义 |
|---|---|---|
c | connection | 产生该请求的连接对象 |
hdr | SMB1::Header | 该 SMB 版本 1 报文的解析后头部 |
args | SMB1::Trans_Sec_Args | 记录类型,携带本次续传的字节计数与位移等结构化信息(详见下文) |
parameters | string | SMB_Data.Trans_Parameters字段内容,即续传的参数块 |
data | string | SMB_Data.Trans_Data字段内容,即续传的数据块 |
args:SMB1::Trans_Sec_Args 的结构字段
Trans_Sec_Args的具体字段由 binpac 解析器在投递事件时逐项填充,字段顺序与赋值索引可从 smb1-com-transaction-secondary.pac 的proc_smb1_transaction_secondary_request函数中确认:
| 索引 | 字段 | 说明 |
|---|---|---|
| 0 | total_param_count | 整个事务的参数总字节数(跨多个报文累计) |
| 1 | total_data_count | 整个事务的数据总字节数 |
| 2 | param_count | 本报文中参数块的字节数 |
| 3 | param_offset | 本报文参数块相对 SMB 头的偏移 |
| 4 | param_displacement | 本报文参数块在事务总参数序列中的起始位移 |
| 5 | data_count | 本报文中数据块的字节数 |
| 6 | data_offset | 本报文数据块相对 SMB 头的偏移 |
| 7 | data_displacement | 本报文数据块在事务总数据序列中的起始位移 |
从字段可以看出,secondary 报文的关键信息是*_displacement(位移):分析器或脚本可以据此把各续传片段按位移拼接,还原完整的事务参数与数据序列。这也是smb1_transaction_secondary_request事件最有价值的字段组。
源码级实现:从报文到事件投递
1. binpac 语法定义报文字段布局
smb1-com-transaction-secondary.pac 用 binpac 语法定义了SMB1_transaction_secondary_request记录的完整报文布局:
type SMB1_transaction_secondary_request(header: SMB_Header) = record { word_count : uint8; total_param_count : uint16; total_data_count : uint16; param_count : uint16; param_offset : uint16; param_displacement : uint16; data_count : uint16; data_offset : uint16; data_displacement : uint16; byte_count : uint16; pad1 : padding to param_offset - SMB_Header_length; parameters : bytestring &length = param_count; pad2 : padding to data_offset - SMB_Header_length; data : SMB1_transaction_data(header, true, data_count, 0, SMB_UNKNOWN, false); } &let { proc : bool = $context.connection.proc_smb1_transaction_secondary_request(header, this); };布局要点:
- 头部是固定的计数/位移字段组(
total_*为总量,param_*/data_*为本次片段的计数、偏移与位移); parameters按param_count精确截取;data字段复用SMB1_transaction_data联合类型(定义于 smb1-com-transaction.pac),其case分支会按传输类型(如SMB_PIPE、SMB_UNKNOWN等)解析出对应的字节内容;- 记录末尾通过
&let的proc钩子调用连接对象上的处理函数proc_smb1_transaction_secondary_request,把解析结果投递为 Zeek 事件。
2. C++ 侧:填充 args、构造字符串并投递事件
同一文件中的proc_smb1_transaction_secondary_request函数(C++ 代码块)完成事件投递前的全部准备工作:
- 快速失败检查:若脚本层未注册
smb1_transaction_secondary_request事件处理器,函数直接返回false,避免无谓开销; - 构造
Trans_Sec_Args记录:通过zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::Trans_Sec_Args)创建记录,并依次将total_param_count、total_data_count、param_count、param_offset、param_displacement、data_count、data_offset、data_displacement八个字段赋值到索引 0–7; - 构造参数串:把
parameters字节序列转为zeek::StringVal; - 构造数据串:当
data_count > 0时,调用transaction_data_to_val()(定义于 smb1-com-transaction.pac,按传输类型返回管道数据或未知数据);当data_count == 0时,直接使用空字符串zeek::val_mgr->EmptyString(); - 投递事件:调用
zeek::BifEvent::enqueue_smb1_transaction_secondary_request(...),把连接、SMB 头、args、parameters、data 一并入队,最终由事件调度器回调 Zeek 脚本层。
3. 与 transaction 请求的协作:子命令信息的来源
由于 secondary 报文本身不携带事务名称与子命令号,相关上下文来自主请求。仓库中的脚本 smb1-main.zeek 给出了smb1_transaction_request事件的官方处理示例:
event smb1_transaction_request(c: connection, hdr: SMB1::Header, name: string, sub_cmd: count, parameters: string, data: string) { c$smb_state$current_cmd$sub_command = SMB1::trans_sub_commands[sub_cmd]; }也就是说,事务的“身份”(如name指向的管道/邮件槽名称、sub_cmd对应的子命令)在smb1_transaction_request中即可确定,而后续到达的多个smb1_transaction_secondary_request事件则持续补充分片数据——脚本层若需要拼装完整事务,可依据args$param_displacement/args$data_displacement将多个片段的parameters与data按序归位。
Zeek 脚本使用示例
在 Zeek 脚本中挂接该事件与挂接其他 SMB1 事件一致,例如:
event smb1_transaction_secondary_request(c: connection, hdr: SMB1::Header, args: SMB1::Trans_Sec_Args, parameters: string, data: string) { if ( args$data_count > 0 ) print fmt("%s transaction_secondary data fragment: %d bytes at displacement %d", c$id, args$data_count, args$data_displacement); }实践要点:
- 事件仅在
transaction_secondary类型请求到达时触发,无需额外注册即可生效(前提是 SMB 分析器已加载,scripts/base/protocols/smb/下的脚本随默认策略加载); - 若要完整还原事务内容,应与
smb1_transaction_request事件联合使用,以connection为纽带聚合多个续传片段; data为空串是正常情况(data_count == 0时解析器显式投递空字符串),判断时应以args$data_count为准而非字符串是否为空。
相关文件索引
以下仓库文件可供进一步深入研究:
- 事件接口文档:doc/scripts/base/bif/plugins/Zeek_SMB.smb1_com_transaction_secondary.bif.zeek.rst
- BIF 事件与类型声明:src/analyzer/protocol/smb/smb1_com_transaction_secondary.bif
- binpac 报文解析与 C++ 投递实现:src/analyzer/protocol/smb/smb1-com-transaction-secondary.pac
- 事务数据联合类型与
transaction_data_to_val:src/analyzer/protocol/smb/smb1-com-transaction.pac - 脚本层状态维护示例(
smb1_transaction_request处理器):scripts/base/protocols/smb/smb1-main.zeek - SMB 分析器目录(含 transaction2-secondary 等相关事件族):src/analyzer/protocol/smb
本文所述协议字段布局与事件语义均可在上述源码与文档中逐项对照验证;SMB1::Trans_Sec_Args的字段顺序则从smb1-com-transaction-secondary.pac的赋值代码推断得出,可作为编写依赖该记录结构脚本时的依据。
- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
相关推荐
用 GetQzonehistory 导出全部 QQ 空间历史说说:一次扫码,拿到 6 张 Excel 和一个网页相册
用 GetQzonehistory 导出全部 QQ 空间历史说说:一次扫码,拿到 6 张 Excel 和一个网页相册 GetQzonehistory 是一个在本
网络安全网络IDSOpen SWE:基于 Deep Agents 与 LangGraph 的开源软件工厂实战指南
Open SWE:基于 Deep Agents 与 LangGraph 的开源软件工厂实战指南 Open SWE(Open Source Software Fa
网络安全网络IDSZeek SMB 分析器实战:`smb1_nt_cancel_request` 事件与 SMB1 NT_CANCEL 命令的解析原理
Zeek SMB 分析器实战: smb1_nt_cancel_request 事件与 SMB1 NT_CANCEL 命令的解析原理 Zeek 内置的 SMB(S
网络安全网络IDS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考