我是靠谱客的博主 热心发带,这篇文章主要介绍基于开源tdifw的Windows传输层防火墙实现(实现用户态与内核态交互)基于开源tfifw的Windows传输层防火墙实现(实现用户态与内核态交互),现在分享给大家,希望可以做个参考。

基于开源tfifw的Windows传输层防火墙实现(实现用户态与内核态交互)

目录

  • 基于开源tfifw的Windows传输层防火墙实现(实现用户态与内核态交互)
    • 实验要求
    • 实验参考
    • 实验资料
    • 实验原理
      • 规则匹配流程图
    • 具体代码
      • 静态添加规则
      • 用户态与内核态交互添加
    • 实验结果
      • 静态添加
      • 用户态与内核态交互动态添加
    • 总结

实验要求

  1. 基于开源的tdifw防火墙代码,实现一个基本的、能够在Windows XP环境下运行的传输层过滤防火墙功能,能够在DbgView等调试软件下看到调试效果。
  2. 基本要求:tdifw能够正确编译、安装、运行,基本理解tdifw的功能框架,能够使用DbgView等调试软件正确定位tdifw代码中的TCP数据传输。
  3. 功能要求:在满足基本要求的前提下,能够改写tdifw中关于TCP connect部分的代码,能够读取不同的目标/源IP地址(如:网站)、端口(不同的服务、应用),能够在DbgView中显示这些信息;更进一步,试着根据目标IP地址的不同,对特定IP地址、端口进行拦截;
  4. 测试网络连接时,可采用自主配置服务器(如web,ssh,ftp等)。
  5. 拔高:设计并编写一个用户态交互配置程序

实验参考

tdifw实验所需的环境工具,及注意事项

  1. 参考资料《寒江独钓》,以下简称《寒》;
  2. 可进阶阅读《寒》第二章内容,了解内核程序的基本特点;
  3. 学习《寒》第十章内容,了解TDI驱动程序的基本构建,主要学习tdifw的编译方法和程序结构(可重点关注10.4,10.5);
  4. 基于《寒》第十章的tdifw代码(在tdi-noChinese目录下),编译tdifw驱动;注意,按照《寒》中的简化方法,绝大部分tdifw已经被封装到一个lib库里了(代码位于tdi_fw子目录),另一个子目录tdifw_smpl用来使用这个lib,生成最终的防火墙内核;
  5. 实验中所需的绝大部分功能位于disp_conn.c文件中,其中函数tdi_connect值得重点关注,这是实现TCP连接的功能函数,本实验所需的各类要求均可在该函数中完成。
  6. 实验时,也可以自行下载tdifw公开的源代码,而不采用《寒》中的lib封装代码,其原理、方法是一样的;
  7. 对于代码的阅读、改写、编辑,软件可根据自己的习惯自选用,WDK编译器一律采用命令行编译模式;
  8. 实验需要的工具:
    必需工具:虚拟机工具(含XP镜像)、驱动开发包WDK、调试工具DbgView等(目录中均已包);
    可选工具:内核服务开启工具、驱动加载工具等(目录中均已包含)
  9. 需要自行学习WDK的编译方式(在本机上安装WDK开发包并进行编译、生成sys防火墙程序;在虚拟机上测试所生成的sys防火墙程序)、DbgView的调试方式(对于初学者,这是一个相对简单的工具)。
    注意:WDK命令行环境下编译驱动程序,全路径名中不允许出现中文字符和空格

实验资料

https://download.csdn.net/download/PlanetRT/20234142.

实验原理

基于开源的tdifw防火墙代码,实现一个基本的、在windowsXP环境下运行的传输层过滤防火墙功能。主要通过对tdifw防火墙代码中的disp_conn.cfilter.c等文件进行修改。
Tdifw过滤的主要原理是通过获取连接的请求(request),并将连接的各个属性加入到请求(request)中。通过调用过滤器过滤(quick_filter(&request, &rule)),将请求的各个属性放到过滤器(filter)的规则链(rule chain) 中进行匹配,当匹配成功时,返回匹配成功的规则的结果(result)。根据返回的结果(result)对该连接请求做出相应的操作(允许连接:FILTER_ALLOW,拒绝连接:FILTER_DENY)。
添加过滤规则的主要原理是通过向过滤器中添加规则来实现过滤。首先在filter.c文件中创建新的规则(声明一个规则结构体:struct flt_rule rlues),并将规则中的属性(例如:proto(协议)、result(结果)、direction(方向)、addr_from(源IP地址)、mask_from(源地址掩码)、port_from(源端口号)、port2_from(源端口范围)等)设定为想要过滤的连接的对应属性。然后将新的规则(rules)加入到过滤器(filter)的规则链中(add_flt_rule(chain,& flt_rule)),并将该规则链进行激活(activate_flt_chain(chain)),即可对目标连接进行过滤。当不需要过滤某一连接时,可将过滤器中对应的规则删除(clear_flt_chain(chain))。
过滤规则匹配的主要原理是首先判断请求(request)的IP地址是否合法,再判断过滤器(filter)的规则链(rule chain)是否激活。然后依次循环规则链(rule chain)中的规则。

内核驱动程序的编译安装此处不做演示。

规则匹配流程图

如下:
在这里插入图片描述

具体代码

静态添加规则

部分可能用到的宏定义:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//方向 #define DIRECTION_IN 0 #define DIRECTION_OUT 1 #define DIRECTION_ANY -1 #define RULE_LOG_NOLOG 0 #define RULE_LOG_LOG 1 #define RULE_LOG_COUNT 2 //协议 #define IPPROTO_ANY -1 #define IPPROTO_IP 0 /* dummy for IP */ #define IPPROTO_ICMP 1 /* control message protocol */ #define IPPROTO_TCP 6 /* tcp */ #define IPPROTO_UDP 17 /* user datagram protocol */ /* filter result */ enum { FILTER_ALLOW = 1, FILTER_DENY, FILTER_PACKET_LOG, FILTER_PACKET_BAD, FILTER_DISCONNECT }; //端口检查 #define CHECK_ADDR_PORT(r_addr_from, r_mask_from, r_port_from, r_port2_from, r_addr_to, r_mask_to, r_port_to, r_port2_to) ((r_addr_from & r_mask_from) == (from->sin_addr.s_addr & r_mask_from) && (r_addr_to & r_mask_to) == (to->sin_addr.s_addr & r_mask_to) && (r_port_from == 0 || ((r_port2_from == 0) ? (r_port_from == from->sin_port) : (ntohs(from->sin_port) >= ntohs(r_port_from) && ntohs(from->sin_port) <= ntohs(r_port2_from)))) && (r_port_to == 0 || ((r_port2_to == 0) ? (r_port_to == to->sin_port) : (ntohs(to->sin_port) >= ntohs(r_port_to) && ntohs(to->sin_port) <= ntohs(r_port2_to)))))

规则结构体(ipc.c):

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//规则结构体 struct flt_rule { union { struct flt_rule *next; // for internal use int chain; // useful for IOCTL_CMD_APPENDRULE }; int result; //匹配结果 int proto; //协议 int direction; //方向 ULONG addr_from; //源地址 注意:均使用网络字节顺序,而不是主机字节顺序!!!转换后使用十进制即可。 ULONG mask_from; //源掩码 USHORT port_from; //源端口 USHORT port2_from; //源端口范围 ULONG addr_to; //目的地址 ULONG mask_to; //目的掩码 USHORT port_to; //目的端口 USHORT port2_to; //目的端口范围额 int log; // see RULE_LOG_xxx UCHAR sid_mask[MAX_SIDS_COUNT / 8]; // SIDs bitmask char rule_id[RULE_ID_SIZE]; }; //一个Web的例子 struct flt_rule rlues1 = { {0}, FILTER_DENY, IPPROTO_TCP, DIRECTION_OUT, 0, 65535, 0, 0, 18095020, 65535, 20480, 0, RULE_LOG_LOG, "1111111111111111", // setup mask before using it! "startup" // rule for startup only* };

规则匹配(disp_conn.c):

复制代码
1
2
3
4
5
6
//quick_filter就是将request里的地址和端口和rule规则进行匹配 返回结果 result = quick_filter(&request, &rule); if(result == FILTER_ALLOW){ KdPrint(("fuck %x n",((const struct sockaddr_in *)&request.addr.from)->sin_addr.s_addr)); }

添加规则(filter.c):

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 添加规则函数 将rule添加到chain链中 NTSTATUS add_flt_rule(int chain, const struct flt_rule *rule) { NTSTATUS status; struct flt_rule *new_rule; KIRQL irql; // sanity check if (chain < 0 || chain >= MAX_CHAINS_COUNT) return STATUS_INVALID_PARAMETER_1; KeAcquireSpinLock(&g_rules.guard, &irql); new_rule = (struct flt_rule *)malloc_np(sizeof(struct flt_rule)); if (new_rule == NULL) { KdPrint(("[tdi_fw] add_flt_rule: malloc_npn")); status = STATUS_INSUFFICIENT_RESOURCES; goto done; } memcpy(new_rule, rule, sizeof(*new_rule)); // append new_rule->next = NULL; if (g_rules.chain[chain].tail == NULL) { g_rules.chain[chain].head = new_rule; g_rules.chain[chain].tail = new_rule; } else { g_rules.chain[chain].tail->next = new_rule; g_rules.chain[chain].tail = new_rule; } status = STATUS_SUCCESS; KdPrint(("YESn")); done: KeReleaseSpinLock(&g_rules.guard, irql); return status; } //几个实例 //添加 web add_flt_rule(0,&rlues1); //添加 ftp add_flt_rule(0,&rlues2); //激活函数 添加规则后均需要激活规则链,但一般0链是默认激活的,其他链默认关闭 activate_flt_chain(0);

如果不需要通过用户态与内核态通信添加,则只需在filter.c中的过滤器初始化函数filter_init中添加即可。
但这种方法比较固定,如果需要更新规则,则只能在代码中添新规则后重新编译安装。通过用户态与内核态的交互会在下边实现。

用户态与内核态交互添加

上边已经实现了静态添加规则的方法,这部分主要实现用户态与内核态交互的动态添加方式。
首先需要实现的是用户态与内核态的通信,具体原理及实现网上教程很多,此处不一一赘述。主要是通信后,内核态对用户态传入数据的处理和规则的添加。
本实验没有实现用户态的可视化界面,如果有需要可自行添加。
进程通信:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//用户调程序 include <windows.h> #include <stdio.h> #include <winioctl.h> #define MY_DVC_IN_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0xa01,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA)//设备的宏定义 #define MY_DVC_OUT_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,0xa00,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA)//设备的宏定义 int main() { HANDLE device=CreateFile("\\.\tdifw", GENERIC_READ|GENERIC_WRITE,0,0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0); if(device==INVALID_HANDLE_VALUE) { printf("CreateFile Failn"); } else { printf("CreateFile Successn"); } char in_buffer[1000]; int in_buffer_len=strlen(in_buffer); char out_buffer[1000]; int out_buffer_len=1000; DWORD length=0; //输出提示信息 printf("***********< Welcome to use XR's TDI_FW >***********n"); //输入的规则 一定要按这个顺序输入,避免内核态读取错误 printf("Tips:Input rules in the roder of whether allowed,protocol,n"); printf("direction,source IP,source mask,source port,source port range,n"); printf("destination IP,destination mask,destination port,destination port range.n"); printf("Please input '*' after input an attributen"); scanf("%s",in_buffer); //输入你需要添加的规则 in_buffer_len=strlen(in_buffer); while(DeviceIoControl(device, MY_DVC_IN_CODE, in_buffer, in_buffer_len, out_buffer, out_buffer_len, &length, NULL)) { printf("Please input '*' after input an attributen"); scanf("%s",in_buffer); in_buffer_len=strlen(in_buffer); //printf("Get from driver %d %sn",out_buffer_len,out_buffer); //printf("to driver:"); } CloseHandle(device); while(1) {} return 0; }

内核态处理(tdi_fw.c):

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//内核态通讯及处理函数 NTSTATUS MyDeviceIoControl(PDEVICE_OBJECT dev, PIRP irp ) { INT ret; PIO_STACK_LOCATION irpsp=IoGetCurrentIrpStackLocation(irp); ULONG code=irpsp->Parameters.DeviceIoControl.IoControlCode; ULONG in_len=irpsp->Parameters.DeviceIoControl.InputBufferLength; ULONG out_len=irpsp->Parameters.DeviceIoControl.OutputBufferLength; PVOID in_buffer=irp->AssociatedIrp.SystemBuffer; PVOID out_buffer=irp->AssociatedIrp.SystemBuffer; //KdPrint(("in_buffer %sn",in_buffer)); char *inbuffder=(char *)in_buffer; if(irp->MdlAddress) { out_buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); } if(code==MY_DVC_IN_CODE) { temp=0; num=0; KdPrint(("in_buffer %sn",in_buffer)); while(*inbuffder){ //传入信息的处理 按*划分 if(*inbuffder!='*'){ str[num] = *inbuffder; nnum=(str[num]-'0')+nnum*10; num++; } else if(*inbuffder=='*'){ temp++; sum=nnum; nnum=0; KdPrint(("sum: %dn",sum)); //添加规则属性 switch(temp){ case 1:rlues.result=sum;break; case 2:rlues.proto=sum;break; case 3:rlues.direction=sum;break; case 4:rlues.addr_from=sum;break; case 5:rlues.mask_from=sum;break; case 6:rlues.port_from=sum;break; case 7:rlues.port2_from=sum;break; case 8:rlues.addr_to=sum;break; case 9:rlues.mask_to=sum;break; case 10:rlues.port_to=sum;break; case 11:rlues.port2_to=sum;break; } num=0; } inbuffder++; } //添加规则 add_flt_rule(0,&rlues); KdPrint(("add rlue successful! by XR n")); if(in_buffer&&out_buffer) { RtlCopyMemory(out_buffer, in_buffer, out_len); } KdPrint(("out_buffer %sn",out_buffer)); irp->IoStatus.Information=out_len; irp->IoStatus.Status=STATUS_SUCCESS; } else { irp->IoStatus.Information=0; irp->IoStatus.Status=STATUS_SUCCESS; //irp->IoStatus.Status=STATUS_INVALID_PARAMETER; } IoCompleteRequest(irp,IO_NO_INCREMENT); return irp->IoStatus.Status; }

至此,所有有关代码均已贴出,如有兴趣,可查看实验资料中上传的全部代码(部分主要文件我加了详细注释)。

实验结果

静态添加

未启动驱动程序时,XP虚拟机(IP:10.0.2.15)对web服务器和ftp服务器的访问情况:
在这里插入图片描述
在这里插入图片描述

驱动程序启动后,XP虚拟机(IP:10.0.2.15)对web服务器和ftp服务器的访问情况:
在这里插入图片描述
在这里插入图片描述

用户态与内核态交互动态添加

加入规则前:
在这里插入图片描述

添加规则:
在这里插入图片描述

DbgView查看通信结果:

在这里插入图片描述

加入规则后:
在这里插入图片描述

总结

本实验为本人课内实验,如有错误,欢迎指正!

最后

以上就是热心发带最近收集整理的关于基于开源tdifw的Windows传输层防火墙实现(实现用户态与内核态交互)基于开源tfifw的Windows传输层防火墙实现(实现用户态与内核态交互)的全部内容,更多相关基于开源tdifw内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部