Windows 防火墙设计

Preview:

DESCRIPTION

Windows 防火墙设计. 教学目的. 随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注。防火墙作为一种网络安全工具,早已普遍应用,成为广大网络用户的安全保护者。 本课程设计的目的是学习 Windows 下防火墙设计技术,并实现一个简单的 Windows 下的防火墙软件。. 教学内容. 学习 Windows 下 SPI 的数据报过滤原理 读懂一个简单的 SPI 过滤程序 设计和实现一个简单的 Windows 应用层防火墙. 基础知识. 了解 Windows API 程序的一般结构 掌握 Windows 下 Socket 编程 - PowerPoint PPT Presentation

Citation preview

Windows防火墙设计

教学目的

随着网络安全问题日益严重,广大用户对网络安全产品也越来越关注。防火墙作为一种网络安全工具,早已普遍应用,成为广大网络用户的安全保护者。

本课程设计的目的是学习 Windows 下防火墙设计技术,并实现一个简单的 Windows 下的防火墙软件。

教学内容

1. 学习 Windows 下 SPI 的数据报过滤原理2. 读懂一个简单的 SPI 过滤程序3. 设计和实现一个简单的 Windows 应用层

防火墙

基础知识1. 了解 Windows API 程序的一般结构2. 掌握 Windows 下 Socket 编程3. 了解 Windows 下 DLL 的概念 ( 重要 )

4. 了解 Windows 下访问注册表函数

参考书目Windows 防火墙与网络封包截获技术

电子工业出版社,朱雁辉

Programming Windows 程式开发设计指南 作 者: Charles Petzold

Windows 95 程式设计指南作 者:侯捷

WINDOWS 网络编程技术

MSDN 相关资料

讲课内容讲课时间 4 学时,实验 16 学时 Windows 下 Hook 技术 Windows 下报文截获技术 Windows 下 SPI 原理 介绍一个简单的 SPI 截获程序 课程设计要求

开发环境

操作系统为 Windows XP 编程工具为 VC++ 6.0 提供虚拟机文件,以及例子代

码和相关工具。

1.Windows的 Hook技术Hook 分为两种Hook 消息

Windows 是消息驱动的运行模式,所以 Hook 消息可以进行很多特殊的处理。这里不详细介绍。参见 SetWindowsHookEx 函数。( Windows 95 程式设计指南)

Hook 函数调用Hook 函数调用是指截获特定进程或者系统对某个 API函数的调用,使得 API 的执行流程转向特定的代码,后者称为注入代码,注入代码一般保存在注入 DLL 中。

1.Windows的 Hook技术Hook 函数调用技术1. 利用 Hook 消息技术,会自动将注入 DLL 装入,

修改目标程序的导入表,替换为注入函数。2. 使用注册表注入 DLL ,主要是某些特定注册表

项会被 Windows 自动调用。3. 使用远程线程注入 DLL ,利用 LoadLibrary 伪

装为线程函数,装载注入 DLL 。4. 通过覆盖代码进行 Hook ,即修改一个函数在

内存中的映像,嵌入汇编代码,使该函数一执行就转跳到注入函数执行,最霸道的方法。

1.我们学习的 Hook技术比较简单的 Hook 技术使用注册表,修改注册表项,安排注入 DLL 。在 DLL 中,利用函数指针来实现 Hook 。

2.Windows应用层报文截获技术1 、原始套结字 (Raw Socket) 。 Winsock2 以后提供了原始套结字功能,可以在用户态用

Winsock 函数接收所有流经 Winsock 的 IP 包。这种方法在 MSDN 里面有叙述,是 MS 官方支持的方法,在网上也有很多资料。但是这种方法只能监听但是不能拦截数据报,所以可以作为网络监视器的选择技术,但是不能实现防火墙等更高要求的功能。另外最致命的缺点就是只能在 Winsock 层次上进行,而对于网络协议栈中底层协议的数据包例如 TDI无法进行处理。对于一些木马和病毒来说很容易避开这个层次的监听。

2 、替换系统自带的 WINSOCK 动态连接库。这种方法可以在很多文章里面找到详细的实现细节。 通过替换系统 Winsock库的部分导出函数,实现数据报的监听和拦截。

2.Windows应用层报文截获技术3 、 Winsock服务提供者 (SPI) 。 SPI 是 Winsock 的另一

面,是 Winsock2 的一个新特性。起初的 Winsock 是围绕着 TCP/IP协议运行的,但是在 Winsock 2 中却增加了对更多传输协议的支持。 Winsock2 不仅提供了一个供应用程序访问网络服务的 Windows socket 应用程序编程接口( API ),还包含了由传输服务提供者和名字解析服务提供者实现的 Winsock服务提供者接口( SPI )和 ws2_32.dll 。

4 、 Windows2000 包过滤接口。由于过滤规则限制太多不灵活而应用不多。

5 、网络监视器 SDK 。 MS 官方的实时监视分析网络数据的方法。但是由于封装的太复杂使用起来不灵活。

2.Windows核心层报文截获技术1 、 TDI 接口

2 、 firewall filter 接口

5 、 NDIS 接口

2.Windows报文截获技术我们重点学习应用层报文截获的第三种方法,这种方法简单、稳定、可靠、功能也比较强大。

3.Windows SPI原理在 Microsoft Windows环境下

的网络编程接口就是 Windows 套接字( Windows Socket ,简称 Winsock )。 Winsock 提供了包括 TCP/IP 、 IPX 等多种通信协议下的编程接口。 indows98 、 Windows NT4.0 、 Windows 2000则直接支持 Winsock2.0 ( 32位)。

Winsock2.0引入的一个功能就是允许开发者可以编写自己的服务提供者接口程序,即 SPI 程序。 SPI 以 DLL方式存在,工作在应用层,为上层程序提供结构函数。

3.Windows SPI原理

即用户程序是通过 WS2_32.dll 来调用实际的 Winsock 函数,这些函数都由服务提供者来提供。

管理者

3.Windows SPI原理

服务提供者又有两种方式,一种是基础服务提供者( Base Service Provider ),另外一种是分层服务提供者( Layer Service Provider )。两者功能相同,但是插入 Winsock体系的方式不同。基础服务者在最底层,而分层服务提供者在一个链式结构中。

3.Windows SPI原理

无论那种服务提供者,其信息都保存在注册表的分支: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Winsock2\Parameters\Protocol_Catalog9\Catalog_entries 中。

3.Windows SPI原理上图中 PackedCatalogItem 中到底保存的是什么呢?

由于我们可以看到是以 REG_BINARY 表示二进制方式保存,而 REG_SZ 表示以 0 结尾的字符串。保存的是一个结构:

typedef struct _WSAPROTOCOL_INFOW { DWORD dwServiceFlags1; DWORD dwServiceFlags2; DWORD dwServiceFlags3; DWORD dwServiceFlags4; DWORD dwProviderFlags; GUID ProviderId; DWORD dwCatalogEntryId; WSAPROTOCOLCHAIN ProtocolChain; //这个结构中的域决定是否 LSP int iVersion; int iAddressFamily; int iMaxSockAddr; int iMinSockAddr; int iSocketType; int iProtocol; int iProtocolMaxOffset; int iNetworkByteOrder; int iSecurityScheme; DWORD dwMessageSize; DWORD dwProviderReserved; WCHAR szProtocol[WSAPROTOCOL_LEN+1];} WSAPROTOCOL_INFOW, FAR * LPWSAPROTOCOL_INFOW;

typedef struct _PACKEDCATALOGITEM { Char sSpiPathName[MAX_PATH]; WSAPROTOCOL_INFOW ProtocolInfo;} PACKETCATALOGITEM;

结构中每个字段含义在MSDN中可以找到

typedef struct _WSAPROTOCOLCHAIN { int ChainLen; /* the length of the chain, */ /* length = 0 means layered protocol, */ /* length = 1 means base protocol, /* length > 1 means protocol chain */ DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; /* a list of dwCatalogEntryIds */} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;

3.Windows SPI原理

由于 SPI 程序可以截获所有通过的报文,所以反倒成为很多木马监视用户流量或者进行进程保护的地方,例如 ccnic 就会在此增加一个自己的LSP 。所以反木马软件也有监控该注册表项的功能,图中为一个反木马软件对注册表项的监控。通过工具 DumpSPI 也可以查看详细信息。

3.Windows SPI原理

另外一个监视所有可能自动启动程序的安全工具界面,也将SPI列为监视对象。

3.Windows SPI原理 我们重点学习如何设计一个 Win

dows 防火墙,该防火墙替换掉 TCP协议的基础服务提供者,然后运行安全功能,当安全功能运行完成后,再运行原有的 Winsock 功能。

对于如何编写一个分层服务提供者,MSDN 有例子文档,可以参考,原理接近。

4.介绍一个简单的防火墙程序工程名: MiniSPI 演示效果 实现流程介绍

4. IP_Moniter.dll具体代码效果演示:

4.介绍一个简单的防火墙程序 程序分为两个部分:1.install 程序,为命令行程序,负责修改注册表,替换掉 TCP基础服务提供者的某些信息,使得 WS2_32.dll启动的是注入 DLL 。

2. 一个 DLL 即注入 DLL ,名称为 IP_Moniter.dll完成安全功能,同时遵守 SPI 接口。

4.介绍一个简单的防火墙程序 install 程序流程:1.从命令行中参数判断是安装还是卸载 IP_M

oniter.dll

2.如果为安装,调用 CInstall类的 InstallPriovider ()方法,该方法负责修改注册表,达到注入新的 SPI DLL 目的。

3.如果为卸载,调用 CInstall类的 RemoveProvider ()方法,该方法恢复原来的注册表。

4. CInstall类方法介绍InstallPriovider ()流程:1. IsInstalled ()方法判断是否已经修改注册表,如果已

经生成了新的注册表项: SYSTEM\\CurrentControlSet\\Services\\WinSock2\\MiniSpi 就认为已经安装,那么退出。

2. 调用 EnumHookKey(FALSE) ,该方法遍历 SYSTEM\\CurrentControlSet\\Services\\WinSock2\\Parameters\\Protocol_Catalog9\\Catalog_Entries 下所有的基础服务提供者,判断是否 TCP/IP协议,如果是,则替换调注册表中 DLL名字为 IP_Moniter.dll ,并将原来的 DLL名字,保存到 SYSTEM\\CurrentControlSet\\Services\\WinSock2\\MiniSpi 下和 dwCatalogEntryId对应的值中。

4. CInstall类方法介绍RemovePriovider ()流程:基本是 InstallProvider 的逆过程,负责将原来的基础服务

提供者的 DLL名字恢复。

注意 install 程序仅仅修改了注册表,将原基础服务提供者的DLL 指向 IP_Moniter.dll ,没有完成任何安全功能。

4. 效果演示没有 Install之前的注册表:

4. 效果演示Install之后的注册表:

4. IP_Moniter.dll功能IP_Moniter.dll 功能:1.按照要求,输出 WSPStartup 函数,该函数负责初试化,该函数也是所有使用 Winsock 程序首先调用的程序。

2.WSPStartup ()调用 GetHookProvider ()得到原来的基础服务者的 DLL位置,然后装载,并调用其WSPStartup (),然后得到 Winsock的 lpProcTable ,该 table 指向所有的 Winsock函数。

3. 替换 lpProcStartup 中的 WSPSocket 函数,并打印调试信息,即截获了 WSPSocket 函数的调用。

4. IP_Moniter.dll具体代码int WSPAPI WSPStartup( WORD wVersionRequested, LPWSPDATA lpWSPData,

LPWSAPROTOCOL_INFOW lpProtocolInfo, WSPUPCALLTABLE upcallTable, LPWSPPROC_TABLE lpProcTable)

{OutputDebugString(_T("WSPStartup"));

TCHAR sLibraryPath[512];LPWSPSTARTUP WSPStartupFunc = NULL;HMODULE hLibraryHandle = NULL;INT ErrorCode = 0;

if(!GetHookProvider(lpProtocolInfo, sLibraryPath) //得到系统的 DLL路径 || (hLibraryHandle = LoadLibrary(sLibraryPath))== NULL //装载系统的 DLL || (WSPStartupFunc = (LPWSPSTARTUP)GetProcAddress(hLibraryHandle, “WSPStartup”))==NULL) //得到系统的启动函数

return WSAEPROVIDERFAILEDINIT;

//调用系统的启动函数,得到 winsock方法表if((ErrorCode = WSPStartupFunc(wVersionRequested, lpWSPData, lpProtocolInfo, upcallTable, lpProcTable))!= ERROR_SUCCESS)

return ErrorCode;

NextProcTable = *lpProcTable;

//将系统的 winsock方法表中WSPSocket函数替换成为自己的函数lpProcTable->lpWSPSocket = WSPSocket;

return 0;}

4. IP_Moniter.dll具体代码SOCKET WSPAPI WSPSocket(

int af,int type,int protocol,LPWSAPROTOCOL_INFOW lpProtocolInfo,GROUP g,DWORD dwFlags,LPINT lpErrno

){

MessageBox(NULL, _T("IP_MONITER:WSPSocket run"), "hint", MB_OK);

return NextProcTable.lpWSPSocket(af,type,protocol,lpProtocolInfo,g,dwFlags,lpErrno);}

4. 进一步增加功能工程名: SimpleFW 前一个程序功能过于简单,仅仅实现了一个基本的 SPI 截获过程,没有实现有价值的防火墙功能。所以对该程序进行进一步的修改,增加以下功能:

1. install 改为图形界面程序,不仅完成安装和卸载SPI 程序,而且记录下截获所有程序的状态。并在一个应用程序访问 Winsock 的时候,询问用户是否允许该程序使用 Winsock 功能。

2. IP_Moniter.dll 监视所有应用程序对 Winsock 的访问,一旦发现用户拒绝的程序,禁止其访问 Winsock 。

4.演示效果一旦安装以后,会询问是否允许特定

程序访问网络。

4.演示效果同时显示访问控制规则:

4.SimpleFW基本技术( 1) Windows 程序设计中消息占到了非常重要的地位,几乎所有的动作都是利用消息来触发。 但是消息是和窗口绑定在一起的,一般拥有窗口才能接收消息。在特殊情况下,线程也可以接收消息。 用户定制消息:

4.SimpleFW基本技术( 1)在 SimpleFW 中,当一个程序访问 Winsock 会弹出对话框,让用户选择是否允许访问。这个过程通过 IP_Moniter.dll 发送给 UI 一个用户自定义消息来实现。

在 IP_Moniter.h 中定义如下:#define WM_QUERY_FW_NOTIFY WM_USER+15

在 IP_Moniter.cpp 中异步发送消息如下:::PostMessage(UIHandle, WM_QUERY_FW_NOTIFY, NULL, NULL);

4.SimpleFW基本技术( 1)在 UI.cpp 中通过如下方式来处理自定义消息:

case WM_QUERY_FW_NOTIFY:

// 得到应用程序路径TCHAR * pApp = GetAppPath();if(MessageBox(hDlg, pApp, _T(" 是否允许该程序访问网络 "),

MB_YESNO|MB_ICONQUESTION|MB_TOPMOST)==IDYES)

{ SetAppControl(TRUE, pApp);

}else{

SetAppControl(FALSE, pApp);}

4.SimpleFW基本技术( 1)所以我们学习用户自定义消息,是为

了掌握 DLL 和应用程序通信时,如何由 DLL 通知一个窗口应用程序某个特殊事件,这个时候可以通过得到窗口句柄来发送用户自定义消息。

4.SimpleFW基本技术( 2)动态加载 DLL :即应用程序通过动态加载一个 DLL 来访问 DLL 的功能,通信方向是从应用程序 --->DLL 。动态加载一个 DLL 的方法,在 UI.cpp 中代码如下:

int LoadDLL(){

if ((hDll = LoadLibrary(sProvider)) == NULL){

_sntprintf(errorInfo, ERROR_INFO_LEN, "%s%s",_T("Can't load dll:"), sProvider);

MessageBox(NULL, _T(errorInfo), NULL, MB_OK);return -1;

}

IoControl = (XF_IO_CONTROL)GetProcAddress(hDll, _T("IOCtrl"));

if (IoControl == NULL){

MessageBox(NULL, _T("Can't find IoCtrl function"), NULL, MB_OK);

return -1;}return 0;

}

4.SimpleFW基本技术( 2) 为什么需要动态加载 DLL ,而不是在编译应用程序的时候,在链接的时候指定呢?最大的好处是实现了应用程序和访问的 DLL之间的松耦合关系。 在写应用程序的时候不需要 DLL 的导入库,只需要知道 DLL 的名字和导出的函数就可以访问其动能了。 从这里,我们也可以看出为什么任何应用程序可以调用 IP_Moniter.dll 的功能。

4.SimpleFW基本技术( 3)DLL中的共享内存:Windows应用程序从Windows2000开始,当多个应用程序都访问同一个DLL的时候,每个应用程序都会有该DLL一个独立的拷贝,如图

DLL代码段DLL数据段

DLL代码段DLL数据段

应用程序 1

DLL代码段DLL数据段

应用程序 2

映射 映射

拷贝拷贝

4.SimpleFW基本技术( 3)

但是 DLL 中的某些变量希望所有应用程序都共享,即指向同一变量,在 SimpleFW 中,例如:

记录界面的窗口句柄:HWND UIHandle=0;

例如记录访问控制规则的数组:XFW_RULE rules[XFW_RULE_LEN];

都希望在所有应用程序中共享

4.SimpleFW基本技术( 3)这个时候采取的方法是,将这些变量放到共享的数据段中,强制为所有应用程序共享:#pragma data_seg(".uniData")HWND UIHandle=0;#pragma data_seg()

#pragma bss_seg(".uni2Data")XFW_RULE rules[XFW_RULE_LEN];#pragma bss_seg()

另外还要在一个 IP_Moniter.def 文件中提醒链接程序,设置共享段:SECTIONS .uniData READ WRITE SHARED .uni2Data READ WRITE SHARED

4.调试技巧( 1)由于改变了注册表,所以如果程序崩溃,注册表

需要恢复到原来状态。方法一:备份注册表,然后恢复。方法二:调用 MiniSPI 工程中的 install –remov

e

4.调试技巧( 2)记住MessageBox 函数,该函数就像 C语言中

的 printf 函数,打印各种调试信息。

5.课程设计要求根据前面的要求,理解两个 SPI 程序,并自己进行扩展,增加新的功能,例如:

1. 对防火墙规则记录到文件,避免每次都需要用户确认。2. 对数据进行截获,打印出发送报文的内容。3. 对数据进行匹配,发现数据中包含特定字符,立刻报警。4. 增加日志功能。5. 访问控制的时候,为串行化,可以改为并行化。6. 对报文内容进行匹配,发现木马或者蠕虫。

7. 美化界面。

5.课程设计要求1.填写实验报告,并打印,班长上交。实验报告填写说明,参见实验报告

5.课程设计要求2. 将代码用 e-mail按照规定格式发送到指定邮箱 lwmemail@gmail.com 。代码用 VC++6.0 编写,在 XP 操作系统下运行减小体积,先 clean 。代码文件放到一个压缩包,文件名为:名字 .ra

r邮件标题为:防火墙作业 -班级 - 学号

Recommended