介绍
5Greplay 是一款 5G 网络流量模糊器,可通过重放和修改 5G 网络流量来评估 5G 组件,方法是创建网络场景并将其注入目标,目标可以是 5G 核心服务(如 AMF、SMF)或 RAN 网络(如 gNodeB)。该工具能够以非常灵活的方式在线或离线更改控制平面和数据平面中的网络数据包。
github地址:https://github.com/Montimage/5Greplay
官方使用文档:https://5greplay.org/docs.html
截止到2023年7月,已更新到0.0.7版本
本文运行环境:Ubuntu22.04
安装
1.直接下载安装
#Install wget to be able to download 5Greplay
sudo apt update && sudo apt install -y wget
# Download 5Greplay
wget https://github.com/Montimage/5Greplay/releases/download/v0.0.7/5greplay-0.0.7_Linux_x86_64.tar.gz
tar -xzf 5greplay-0.0.7_Linux_x86_64.tar.gz
cd 5greplay-0.0.7
./5greplay -h
0.0.1版本正常运行,
目前发现0.0.7版本运行会出现问题,
./5greplay: error while loading shared libraries: libmmt_tcpip.so: cannot open shared object file: No such file or directory
可能作者在编译链接程序时没有将./plugins路径携带引入
导致找不到libmmt_tcpip.so
可以执行以下命令来解决
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./plugins
#我的路径为/home/ubuntu22/5greplay-0.0.7/plugins
但是每次执行shell时都要输一遍命令来修改环境变量$LD_LIBRARY_PATH的值,如果要持久化生效,可以在/etc/profile或~/.bashrc等shell初始化文件中做永久性设置。
也可以通过编译链接程序时,将rpath携带引入,进行硬编码设置。
采用编译安装和docker安装方法可以参考官方文档
2.编译源代码安装
https://5greplay.org/docs/guide/building-from-source/
3.docker
https://5greplay.org/docs/guide/docker/
命令
5Greplay命令使用以下形式:command [option]
- command命令有以下几种:compile, info, list, extract, replay
- option选项:运行”./5greplay command -h“以获取帮助,展示命令所有的选项
(一)compile
此命令分析xml文件,然后编译成插件。即用户可以根据自己的需要编辑xml格式文件,生成自己的插件
该命令有3个参数:
1.输出位置:应该以结束.so或者.c当分别生成二进制或代码C时
2.包含要编译的规则的输入xml文件
3.可选择的-c以生成代码C或任何将被转移到gcc编译字符串。
为了能够编译规则,应该安装gcc:sudo apt install gcc
#to generate .so file
./5greplay compile rules/forward-localhost.so rules/forward-localhost.xml
#to generate code c (for debug)
./5greplay compile rules/forward-localhost.c rules/forward-localhost.xml -c
(二)info
该命令打印编译好的.so
文件的规则信息
该命令有一个可选参数。用于查看特定文件中的规则,不输入则默认输出rules文件夹下的所有规则。
#print information of all available plugins
./5greplay info
#print information of rules encoded in `rules/nas-smc-replay-attack.so`
./5greplay info rules/4.nas-smc-replay-attack.so
0.0.7版本内置了16种规则,不再一一列举,最初的0.0.1版本仅有3种
(三)list
该命令列出了5Greplay支持的所有协议及其属性。该命令没有参数。
可支持的协议特别多
(四)extract
该命令在0.0.2及之后的版本中可用。
它用于从pcap文件或网卡中提取给定协议的属性值。当我们想要查看pcap文件包中的内容时,可以使用该命令。
ubuntu22@ubuntu22-virtual-machine:~/5greplay-0.0.7$ ./5greplay extract -h
mmt-5greplay: 5Greplay v0.0.7-77dda18 using DPI v1.7.9 (8694eaa6) is running on pid 69299
extract [<option>]
Option:
-t <trace file>: Gives the trace file to analyse.
-i <interface> : Gives the interface name for live traffic analysis. Either -i or -t can be used but not both.
-p : Protocol's name to be extracted. Default: ethernet
-a : Attribute's attribute to be extracted. Default: src
-d : Index of protocol to extract. For example: ETH.IP.UDP.GTP.IP, if d=3 (or ignored) IP after ETH, d=6 represent IP after GTP. Default: 0
-r : ID of protocol stack. Default: 1
-h : Prints this help then exit
(五)extract
该命令可以重放
通过捕获来自给定网卡的流量来提供实时流量,
或者保存在pcap文件中的流量。
ubuntu22@ubuntu22-virtual-machine:~/5greplay-0.0.7$ ./5greplay replay -h
mmt-5greplay: 5Greplay v0.0.7-77dda18 using DPI v1.7.9 (8694eaa6) is running on pid 69358
replay [<Option>]
Option:
-v : Print version information, then exits.
-c <config file> : Gives the path to the configuration file (default: ./mmt-5greplay.conf).
-t <trace file> : Gives the trace file for offline analyse.
-i <interface> : Gives the interface name for live traffic analysis.
-X attr=value : Override configuration attributes.
For example "-X output.enable=true -Xoutput.output-dir=/tmp/" will enable output to file and change output directory to /tmp.
This parameter can appear several times.
-x : Prints list of configuration attributes being able to be used with -X, then exits.
-h : Prints this help, then exits.
#Note: you may want to change parameters inside mmt-5greplay.conf
#replay online traffic comming from eth0
sudo ./5greplay replay -i eth0
#replay offline traffic being stored inside a pcap file
sudo ./5greplay replay -t ~/pcap/5G-traffic.pcap
配置参数
(一)示例
5greplay工具中,rules目录下有规则示例文件,为xml文件,0.0.7版本提供了16个规则示例
(二)嵌入函数
嵌入式函数是允许实现计算功能的函数,如果在仅使用安全规则布尔表达式中的经典运算符来定义的话太过复杂。可以使用现有的嵌入式函数或实现新函数。在这两种情况下,它们都可以通过使用以下语法在布尔表达式中使用:
#<name_of_function>(<list of parameters>)
例如:
(#em_is_search_engine( http.user_agent ) == true)
其中http是协议名称,user_agent是属性名称(即数据包元数据)。
请参阅此处获取协议和属性的完整列表。(注释:这里非常类似wireshark里面的过滤器语法规则)
xml规则中使用的协议和属性名称区分大小写。它们通常是小写的。
为了避免混淆,新的嵌入函数名应该以前缀em_开头。
1. 特殊条款
true将被数字1代替。
例如:
#em_check(tcp.src_port)== true
false将替换为数字0。
例如:
#em_check(tcp.src_port)== false
2.实现一个新的嵌入式函数
在每个规则文件中,都有一个允许用户添加嵌入式功能的部分。
<embedded_functions><![CDATA[
//code C
static inline bool em_check( double port ){
if( port == 80 || port == 8080 )
return true;
return false;
}
]]></embedded_functions>
除了这个标签之外,还可以实现如下两个其他功能:
(1)void on_load(){ … }当xml文件中的规则被加载到5Greplay时被调用
(2)void on_unload(){ … }退出5Greplay时被调用
3.预安装嵌入式函数
在规则的布尔表达式中,可以使用一个或多个嵌入函数
(1)is_exist( proto.att ) 检查一个事件是否具有协议属性,例如is_exist( http.method ) 如果当前事件包含协议HTTP并且属性方法具有非空值,将会返回true,否则返回false
通常情况下,5Greplay 有一个过滤器,只有在其布尔表达式中使用的任何 proto.att 包含值时,才允许验证规则中的事件。如果其中一个不包含值,则不会验证该规则。这样可以减少布尔表达式的验证次数,从而提高性能。
例如,给定的事件具有以下布尔表达式:
((ip.src != ip.dst) && (#em_check_URI(http.uri) == 1))
只有当 ip.src 和 ip.dst 以及 http.uri 不为空时,才会验证该事件,因此只验证 HTTP 数据包(不会验证每个 IP 数据包)。
但是,如果使用下面的表达式,则与前一个表达式的含义完全相同:
((ip.src != ip.dst) && ((#is_exist(http.uri) == true ) && (#em_check_URI(http.uri) == 1)))
5Greplay 需要针对任何 IP 数据包验证该表达式, is_exist 会告诉 5Greplay 从其过滤器中排除 http.uri。
(2)is_null( proto.att ), 例如,#is_null(http.uri) 检查 http.uri 的值是否存在
(3)is_empty( proto.att ), 例如,#is_empty(http.uri) 检查值是否为空或字符串值是否为空,即长度是否为零。
(4)is_same_ipv4(const uint32_t*, const char *),例如,#is_same_ipv4(ip.src, “10.0.0.1”) 检查 ip.src 的值是否为 “10.0.0.1”。
(5)我们可以使用任何标准 C 函数作为嵌入函数,例如,(#strstr( http.user_agent, ‘robot’) != 0) 检查 http.user_agent 是否包含子字符串 “robot”。
请注意,在使用 C 语言函数之前,必须包含包含该嵌入函数的库。以下库已被预包含:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "mmt_lib.h"
#include "pre_embedded_functions.h"
因此,在使用未在这些库中定义的函数时,我们需要包含其库。例如
<embedded_functions><![CDATA[
#include <math.h>
static inline bool function em_check( double port ){
double x = sqrt( port );
return x >= 5;
}
]]></embedded_functions>
(三)反应函数
反应函数允许我们在满足某个规则时执行某些操作。每次满足规则时,这些函数都会被调用。
要实现和使用反应式函数,我们需要:
在 <embedded_functions> 标签内实现一个 C 函数。
函数名称的前缀应为 em_,以避免与 5Greplay 内部已有的函数混淆。
函数的格式如下:
typedef void (*mmt_rule_satisfied_callback)(
const rule_t *rule, //rule being validated被验证的规则
int verdict, //DETECTED, NOT_RESPECTED
uint64_t timestamp, //moment (by time) the rule is validated验证规则的时刻(按时间计算
uint64_t counter, //moment (by order of message) the rule is validated验证规则的时刻(按报文顺序排列
const mmt_array_t * const trace //historic of messages that validates the rule验证规则的消息历史记录
);
将函数名放入要反应的规则的 if_satisfied 属性中。例如:if_satisfied=“em_print_out”
<beginning>
<embedded_functions><![CDATA[
static void em_print_out(
const rule_info_t *rule, int verdict, uint64_t timestamp,
uint64_t counter, const mmt_array_t * const trace ){
const char* trace_str = mmt_convert_execution_trace_to_json_string( trace, rule );
printf( "detect rule %d\n%s\n", rule->id, trace_str );
//you can call a system command, for example:您可以调用系统命令,例如
//char command[1001];
//snprintf( command, 1000, "echo rule %d is validated by %s", rule->id, trace_str );
//system( command );
}
]]></embedded_functions>
<!-- Property 10: HTTP using a port different from 80 and 8080.-->
<property value="THEN" delay_units="s" delay_min="0" delay_max="0" property_id="10" type_property="EVASION"
description="HTTP using a port different from 80 and 8080." if_satisfied="em_print_out">
<event value="COMPUTE" event_id="1"
description="HTTP packet using a port different from 80 and 8080"
boolean_expression="((http.method != '')&&((tcp.dest_port != 80)&&(tcp.dest_port != 8080)))"/>
<event value="COMPUTE" event_id="2"
description="HTTP packet"
boolean_expression="(ip.src != ip.dst)"/>
</property>
</beginning>
3.1 支持的功能
我们实现了多个功能,以支持修改协议属性值、丢弃数据包、转发数据包或将其复制到输出网卡。新函数将逐次实现和添加。
以下函数必须在反应函数内部调用。
1.get_numeric_value( proto_id, att_id, event_id, trace)
从满足条件的跟踪中返回事件 ID 的 proto_id.att_id 字段的 uint64_t 值。
2.set_numeric_value( proto_id, att_id, uin64_t )
标记用于将 proto_id.att_id 改为 uint64_t 值。只有在发送数据包时,例如通过显式调用 forward_packet 时,才会应用该更改。
3.forward_packet()
立即转发当前数据包
4.drop_packet()
不转发当前数据包
5.update_sctp_param( uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive )
更新 sctp_sendmsg 函数中的参数,该函数用于在 5Grepay 与目标之间创建 SCTP 通信通道。
3.2预定义的反应式函数
以下函数已被定义
#drop() 用于丢弃当前数据包
#update( proto_id.att_id, expression ) 用于更改当前数据包,然后将其转发给发出的网卡。
proto_id 和 att_id 分别表示要更改的协议和属性
expression 为表达式格式,用于获取要分配给协议属性的值
示例
#update(ngap.ran_ue_id, (ngap.ran_ue_id + 100) 将使 ran_ue_id 增加 100
#update(ngap.ran_ue_id,(ngap.ran_ue_id.1 * 2) 将把当前数据包的 ran_ue_id 替换为 event_id=1 的数据包的 ran_ue_id 的两倍。
#fuzz(proto.att, proto.att, …)会更改当前数据包,然后将其副本转发到发出的网卡。
目前(2022 年 2 月 10 日)只支持数值
每个 proto.att 都将设置一个由 C random 函数生成的新随机值。请参阅 rules/7.fuzz-ngap.xml 中的示例,了解如何覆盖随机函数。
3.3示例
以下XML文件定义了3条规则:
<beginning>
<embedded_functions><![CDATA[
static void em_modif_then_forward(
const rule_info_t *rule, int verdict, uint64_t timestamp,
uint64_t counter, const mmt_array_t * const trace ){
const char* trace_str = mmt_convert_execution_trace_to_json_string( trace, rule );
//forward the original packet (without any modification)
forward_packet();
//get old value ran_ue_id
uint64_t ran_ue_id = get_numeric_value( PROTO_NGAP, NGAP_ATT_RAN_UE_ID, 2, trace );
//clone 9 times the current packet
for( int i=1; i<10; i++ ){
//increase ran_ue_id
set_numeric_value( PROTO_NGAP, NGAP_ATT_RAN_UE_ID, ran_ue_id + i );
//forward the packet having the modified ran_ue_id
forward_packet();
}
}
]]></embedded_functions>
<property value="THEN" delay_units="s" delay_min="0+" delay_max="1" property_id="100"
description="Forwarding NAS security mode COMPLETE that answers to NAS security mode COMMAND "
if_satisfied="em_modif_then_forward">
<event value="COMPUTE" event_id="1" description="NAS Security mode COMMAND"
boolean_expression="(nas_5g.message_type == 93)"/>
<event value="COMPUTE" event_id="2" description="NAS Security mode COMPLETE"
boolean_expression="(nas_5g.security_type == 4)"/>
</property>
<property property_id="101" if_satisfied="#drop()"
description="Do not forward any UDP packets having dest_port other than 2152">
<event event_id="1" description="From UE and GTP packets"
boolean_expression="( (udp.dest_port != 2152 ) )"/>
</property>
<property property_id="102" description="" if_satisfied="#update(ngap.procedure_code, (ngap.procedure_code.1 + 100))">
<event event_id="1" description="having RAN UE ID"
boolean_expression="(ngap.ran_ue_id != 0)"/>
</property>
规则 100 将匹配 2 个不同的数据包(因为它有 2 个事件和 delay_min=“0+”):
第一个数据包是 NAS 安全模式 COMMAND(nas_5g.message_type == 93)
第二个数据包是 NAS 安全模式 COMPLETE(nas_5g.message_type == 4)
在获取第二个数据包时,会调用 em_modif_then_forward 函数。在该函数中,我们可以修改第二个数据包的内容,然后将其注入到发出的网络中。该函数首先通过调用 forward_packet()转发第二个数据包,不做任何修改。然后调用 get_numeric_value 获取第二个数据包中 NGAP 协议 NGAP_ATT_RAN_UE 属性的当前值。然后通过调用 set_numeric_value 来标记该值的增加,并将变化范围内的数据包转发到网络。
注意:如果调用函数 set_numeric_value 两次来修改协议的同一属性,则只执行第二次调用。
规则 101 通过明确调用 drop() 函数,不转发 dest_port 不是 2152 的 UDP 数据包。
规则 102 检查数据包中是否包含不为零的 ngap ran_ue_id。如果是,则将 procedure_code 值增加 100。(默认情况下,它会将修改后的数据包转发到输出网卡)。
(四)编译规则
5Greplay 规则是以 XML 格式的纯文本指定的。这些规则需要编码成合适的格式,即动态 C 库,然后才能供 5Greplay 使用。
编译后的规则必须放在 ./rules 文件夹中。
5Greplay 提供了一个编译器来完成这样的任务。为此,我们需要事先安装 gcc,例如 sudo apt install gcc。
使用编译器编译 XML 文件中的规则。例如
./5greplay compile rules/1.so rules/1.xml
程序使用 3 个参数,格式为: output_file property_file [gcc 参数]
其中
output_file:是包含编译结果的文件路径,可以是 .c 文件或 .so 文件。
property_file:是可以找到属性文件的路径。
选项:
-c:只生成 C 代码。该选项允许在编译前手动修改生成的代码。生成 C 代码后,工具会打印出编译时需要执行的命令。
gcc 参数:用于生成 C 代码并编译以获得 .so 文件。这些参数将直接传送给 gcc 编译器,例如:-I /tmp -lmath
要获取编译规则的一些基本信息(如 ID、描述),我们可以使用 info 命令。默认情况下,工具会打印出所有规则的信息,例如
./5greplay info
mmt-5greplay: 5Greplay v0.0.1-5c9a333 using DPI v1.7.0.0 (a8ad3c2) is running on pid 24680
mmt-5greplay: Ignore duplicated rule id 103 (Inject only packet from UE -> Core but not inversed direction)
Found 3 rules.
1 - Rule id: 103
- type : DROP
- events_count : 2
- variables_count : 2
- variables : sctp.ch_type (304.5), sctp.dest_port (304.2)
- description : Inject only SCTP packets from UE -> Core but not inversed direction
- if_satisfied : 0x7f84c2d95db5
- version : 0.0.1 (5c9a333 - 2021-9-9 11:36:44), dpi version 1.7.0.0 (a8ad3c2)
…
也可以使用该工具检查特定的编译规则,方法是将规则路径作为参数,例如
./5greplay info rules/forward-localhost.so
mmt-5greplay: 5Greplay v0.0.1-5c9a333 using DPI v1.7.0.0 (a8ad3c2) is running on pid 21983
Found 2 rules.
1 - Rule id: 103
- type : DROP
- events_count : 2
- variables_count : 2
- variables : sctp.ch_type (304.5), sctp.dest_port (304.2)
- description : Inject only SCTP packets from UE -> Core but not inversed direction
- if_satisfied : 0x7f2925125db5
- version : 0.0.1 (5c9a333 - 2021-9-9 11:36:44), dpi version 1.7.0.0 (a8ad3c2)
与之前介绍命令章节中的info命令一致
(五)默认值
在规则的 XML 文件中,如果没有 XML 标记的属性,则默认设置其值:
- property, operator:
- type_property: FORWARD
- value : COMPUTE (=> only one is required. Thus delay_min and delay_max must be 0)
- delay_units: s
- delay_min: 0
- delay_max: 0
XML 规则描述的语义
5Greplay 规则用于正式指定网络上的事件,这些事件表示要转发、丢弃或修改的数据包。这些规则依赖于 LTL(线性时态逻辑),并以 XML 格式编写。这样做的好处是结构简单明了,便于工具进行验证和处理。在本文档中,我们交替使用属性和规则这两个术语。
定义规则时,用户必须在规则中指明
将处理哪个数据包(过滤)
使用哪种操作(丢弃、转发或修改)
如何修改数据包(如果要采取的操作是修改,则定义要更改的值)
…(未完待续)
转发数据包
介绍 5Greplay 如何转发数据包
5Greplay 可以使用 libpcap 或 DPDK(如果工具使用 DPDK 编译)将原始数据包原封不动地转发到输出网卡。
实现方法在 src/forward 文件夹中。
为了避免数据包被认为是重复的,从而被端点协议拒绝,5Greplay 支持在它和端点之间创建一个新的数据流,然后使用该数据流注入数据包的有效载荷。
目前,它支持 SCTP 和 UDP 流。端点信息通过配置文件提供,使用的参数如下:
- forward.target-protocols: list of stream protocols, for example, {SCTP,UDP}
- forward.target-hosts: IPs of the targets corresponding to each protocol
- forward.target-ports: Port numbers of the targets corresponding to each protocol.
例如:
如果我们想使用新的 SCTP 连接来转发 SCTP 数据包的有效载荷,而其他数据包(包括 UDP 数据包)则按原样转发,那么我们可以使用以下配置:
forward
{
enable = true
output-nic = "lo"
nb-copies = 1
snap-len = 0
promisc = 1
default = DROP
target-protocols = { SCTP }
target-hosts = { "127.0.0.5" }
target-ports = { 38412 }
}
使用这些配置参数,所有 SCTP 数据包的有效载荷都将发送到端口 38412 的 127.0.0.5。其他数据包(不包括包含 SCTP 协议的数据包)将被注入 lo 网卡接口。
支持的协议及其属性
协议及其属性列表载于 protocols-attributes-list.txt。
我们也可以通过运行 ./5greplay list 来获取该列表。
例如
Protocol id 904 Name nas_5g
- Attribute id 1, Name protocol_discriminator
- Attribute id 2, Name message_type
- Attribute id 3, Name security_type
- Attribute id 4, Name procedure_transaction_id
- Attribute id 5, Name message_authentication_code
- Attribute id 6, Name sequence_number
- Attribute id 4096, Name p_hdr
- Attribute id 4097, Name p_data
- Attribute id 4098, Name p_payload
- Attribute id 4099, Name packet_count
- Attribute id 4100, Name data_count
- Attribute id 4101, Name payload_count
- Attribute id 4102, Name first_packet_time
- Attribute id 4103, Name last_packet_time
- Attribute id 4104, Name stats
协议 nas_5g 有 6 个主要属性和 9 个元数据属性,这些属性被 5Greplay 的 DPI 引擎内部使用。我们可以在规则中使用 nas_5g.sequence_number 来引用 NAS 协议的序列号属性。
以上内容摘自5Greplay官方文档,图片来自Ubuntu22.04运行结果,如有错误或问题敬请指正,欢迎私信交流!