NDIS HOOK 防火墙实现关键技术

DLL远程卸载chrome的防火墙模块 DLL远程卸载模块 大体流程如下: 主要函数为CreateRemoteThread,调用kernel32.dll下的FreeLibrary模块卸载函数,对目标进程下的对应运行线程的dll模块进行卸载,从而达到目的 利用CE工具打开进程,查找目标模块的基地址 找到FreeLibrary的基地址,调用kernel32下的卸载函数 找到卸载的目标模块的基地址,本次是卸载Fire... 阅读详情
到网络安全不能不提到防火墙。目前国内防火墙多数是采用 TDI 技术, NDIS 可以算是较先进的技术了(如果您认为不是的话, 只能说明我落伍了, 呵呵) 网上缺少 NDIS 防火墙实现的技术细节说明.  经过2天的查找资料和分析已有的源代码再加上以前 NDIS 编程的基础很快对该技术有了初步的了解。


该技术细节分析只涉及到怎样 Hook 到 Ndis.sys 中导出的内核函数。至于在 Hook 函数中要进行怎样的处理就要取决于具体功能要求了. 希望下面的技术细节分析可以解决您入手难的问题.


实现思路:
(1) 类似于 User-Mode Application, 我们需要得到被挂钩函数所在文件的内存基地址。

(2) 判断该基地址开始前2个字节是否是 'MZ', 然后通过 DOS 头部结构的最后成员 e_lfanew. 进一步得到 PIMAGE_NT_HEADERS, 然后得到
    函数导出目录的地址.

(3) 在 ndis.sys 的导出目录中查找要替换的目标函数 NdisRegisterProtocol, 找到目标函数后得到目标函数地址. 然后保存原先函数地址并    用我们自己的 New_NdisRegisterProtocol 替换原函数地址。

(4) 根据具体的功能需求进行不同的过滤实现.


没有什么讲解方法比展示实现代码更丰富更吸引人的, 下面就给出实现代码.


(1)
例如: 通过 depends.exe 工具查看 ndis.sys 导出的函数, 可以发现其中包括 NdisRegisterProtocol, 我们就挂钩该函数

首先需要得到 ndis.sys 的内存基地址
这里使用 Native API  ZwQuerySystemInformation 来获得系统已经加载内核模块的信息。

系统模块信息结构体如下:

typedef struct _SYSTEM_MODULE_INFORMATION {
 ULONG Reserved[2];
 PVOID Base;
 ULONG Size;
 ULONG Flags;
 USHORT Index;
 USHORT Unknown;
 USHORT LoadCount;
 USHORT ModuleNameOffset;
 CHAR ImageName[255];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;


查找指定模块的内存基址函数如下:

void * find_system_dll(const char *name)
{
 ULONG i, n, *q;
 PSYSTEM_MODULE_INFORMATION p;
 void *base;
 
 /*
         * 得到系统模块信息需要的内存数量
         */
 ZwQuerySystemInformation( SystemModuleInformation, &n, 0, &n);
 q = (ULONG *)ExAllocatePool(PagedPool, n);
 ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof (*q), 0);

 
        /*
         * ZwQuerySystemInformation 在改内存中返回模块数量和每个模块的信息.
  * 模块数量是内存的前4个字节, 后面是所有模块信息的排列
         */
 p = (PSYSTEM_MODULE_INFORMATION)(q + 1);

 base = NULL;
 for (i = 0; i < *q; i++)
 {               
  /*
                 * 例如: ImageName: windows/system32/ndis.sys, 那么 ModuleNameOffset 就是 0x11
                 */
  if (_stricmp(p[i].ImageName + p[i].ModuleNameOffset, name) == 0)
  {
   /*
                         * 得到 ndis.sys 模块的内存基址
                         */
   base = p[i].Base;

   KdPrint(("[ndis_hk] find_system_dll: %s; base = 0x%x; size = 0x%x/n", name, base, p[i].Size));
   break;
  }
 }
  
 ExFreePool(q);

 return base;
} 


(2) 我们已经得到了ndis.sys 模块的内存基址, 下面就根据 PE 文件格式来得到导出函数目录的虚拟地址
 

(3) 查找目标函数 NdisRegisterProtocol, 得到目标函数的在系统内核中的地址, 保存并替换原地址

/*
 * base :  ndis.sys 模块的内存基地址
 * 
 * fn:     被 Hook 的函数名
 *
 * new_fn: 新的函数地址
 */

void * fix_export(char *base, const char *fn, void *new_fn)
{
 PIMAGE_DOS_HEADER dos_hdr;
 PIMAGE_NT_HEADERS nt_hdr;
 PIMAGE_EXPORT_DIRECTORY export_dir;
 ULONG *fn_name, *fn_addr, i;

 /*
         * 检查文件的有效性, 开始的2个字节是否是 'MZ', 按照 little-endian 顺序值是 0x5A4D.
         */
 dos_hdr = (PIMAGE_DOS_HEADER)base;

 if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE)
  return NULL;

 /*
         * 通过DOS头部的最后一个成员得到 NT 头部相对于文件的偏移, 然后计算出 NT 头部的虚拟地址
         */
 nt_hdr = (PIMAGE_NT_HEADERS)( base + dos_hdr->e_lfanew );

 export_dir = (PIMAGE_EXPORT_DIRECTORY)( base + nt_hdr->OptionalHeader.DataDirectory                                                    [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );
 
 
 /*
         * 得到导出函数名字地址数组的地址, 数组中的每个元素是导出函数名的地址(指向导出函数名的指针)
         */
 fn_name = (ULONG *)(base + export_dir->AddressOfNames);
 /*
         * fn_addr 数组中每个元素是导出函数地址的地址
         */
 fn_addr = (ULONG *)(base + export_dir->AddressOfFunctions);
 
 
 for ( i = 0;  i < export_dir->NumberOfNames;  i++, fn_name++, fn_addr++ )
 {
  if ( strcmp(fn, base + *fn_name) == 0 )
  {
   /*
                         * 取得该函数名对应的虚拟内存地址
                         */
   void *old_addr = base + *fn_addr;

   /*
                  *  用我们自己新的函数地址(相对于导出模块的基地址) 来代替原函数的地址
                         */
   replace_value_safe(fn_addr, (char *)new_fn - base);

   return old_addr;
  }
 }

 return NULL;
}


BOOLEAN replace_value_safe( ULONG *addr, ULONG value)
{
 MDL *mdl;
 ULONG *virt_addr;

 mdl = IoAllocateMdl(addr, sizeof(value), FALSE, FALSE, NULL);
 if ( mdl == NULL )
  return FALSE;
 
 /*
         * 检测指定的操作是否被支持, 锁定页面避免被换出从而造成缺页错误.
         * 如果检测的操作不被支持该函数会抛出异常, 因此必须用 try/except 异常处理.
         */
 __try
 {
  MmProbeAndLockPages( mdl, KernelMode, IoModifyAccess );
 
 } __except(EXCEPTION_EXECUTE_HANDLER)
 {
  KdPrint( ("[ndis_hk] replace_value_safe: MmProbeAndLockPages!/n") );
  return FALSE;
 }

 virt_addr = (ULONG *)MmGetSystemAddressForMdl(mdl);

 /*
         * 修改函数地址
         */
 *(ULONG *)virt_addr = value;


 MmUnlockPages(mdl);
 IoFreeMdl(mdl);
 return TRUE;
}

(4) 在新函数中进行过滤操作
 

 
简单分析用SPI实现防火墙                                        简单分析用SPI实现防火墙  作者:snsins如有转载,请注明并保持文章的完整2002.12.5-------------------------------------------------------------------------------------------------------- 阅读详情

相关推荐

c# 添加防火墙例外所需dll

和辅助类一块的 忘记上传了,现在补上。亲测可用的。。。。

用C#开发网络防火墙技术分析

N-Byte网络守望者是一款单机版网络安全工具,简言之,就是一个用.NET开发的个人版防火墙。在N-Byte网络守望者1.0版的开发中,使用了NDIS Hook Driver技术来实现网络封包过滤功能,这使N-Byte网络守望者能够在网络层过滤网络封包,从而实现强大的功能。   由于软件的主程序是用C#写的,C#中没有提供具有类似DeviceIoControl函数功能的驱动设备控制函数,而NDIS

lx6314415的专栏 673

NetWall防火墙简易版源代码包括文档

统内核(netwall.sys)是一个NDIS中间层驱动程序,用它来截获网络封包, 在安装前,系统中最好不要装有第三方NDIS中间层驱动程序。

Windows防火墙之NDIS HOOK和TDI HOOK

<br />1、TDI HOOK<br /> TDI Client利用TDI接口,向TDI Server发送IRP(I/O Request Packet)请求包,来获得TDI Server提供的服务。因此,可以利用分层驱动原理[5],在TDI Client和TDI Server驱动之间加一层过滤驱动-FilterDriver.sys。对于TCP/IP协议而言,在Windows网络协议体系结构中是由Tcpip.sys驱动实现的。Tcpip.sys创建了几个设备对象,/Device/RawIp,/Device/

深度技术安全 8550

基于Ndis Hook钩子技术开发的网络防火墙源代码

基于Ndis Hook技术开发的网络防火墙源代码

ndis驱动程序例子源代码,写防火墙的朋友可以参考

ndis网络驱动程序源代码,写防火墙的朋友可以参考

探索NDIS HOOK新的实现方法(1)

NDIS HOOK是专业级防火墙使用的一种拦截技术,NDIS HOOK的重点是如何获得特定协议对应NDIS_PROTOCOL_BLOCK指针,获得了该指针,接下来就可以替换该协议所注册的收发函数,而达到拦截网络数据的目的。 获 得NDIS_PROTOCOL_BLOCK指针的方法一般是用NdisRegisterProtocol注册一个新的协议,所获得的协议句柄实际上就是一...

aiyun1234的博客 127

NDIS源码 NDIS6

typedef struct _NDIS60_PROTOCOL_BLOCK { VOID* Header; /* _NDIS_OBJECT_HEADER */ VOID* ProtocolDriverContext; struct _NDIS60_PROTOCOL_BLOCK* NextProtocol; struct _NDIS_OPEN_BLOCK* OpenQueue; struct _REFERENCE Ref; unsigned char MajorNdisVersion; unsigned char MinorNdisVersion; unsigned char MajorDriverVersion; unsigned char MinorDriverVersion; UINT32 Reserved; UINT32 Flags; struct _UNICODE_STRING Name; } NDIS60_PROTOCOL_BLOCK, *PNDIS60_PROTOCOL_BLOCK;

探索NDIS HOOK新的实现方法

NDIS HOOK是专业级防火墙使用的一种拦截技术,NDIS HOOK的重点是如何获得特定协议对应NDIS_PROTOCOL_BLOCK指针,获得了该指针,接下来就可以替换该协议所注册的收发函数,而达到拦截网络数据的目的。获得NDIS_PROTOCOL_BLOCK指针的方法一般是用NdisRegisterProtocol注册一个新的协议,所获得的协议句柄实际上就是一个NDIS_PROTOCOL

jia_xiaoxin的专栏 794

大话西游2经典单机版V8:一键架设+GM全功能+仙玉自由修改

本文详细介绍大话西游2经典单机版V8的一键架设教程和GM全功能使用指南,包括仙玉自由修改技巧。该版本无需虚拟机,解压即玩,完美还原官服经典玩法,支持离线运行,是老玩家重温经典和新玩家体验游戏的理想选择。

weixin_27303545的博客 1133

Python量化入门:用pytdx获取800个交易日K线数据的完整指南(附代码)

本文为Python量化交易初学者提供了使用pytdx库免费获取股票日线级别K线数据的完整指南。文章详细介绍了从环境搭建、单只股票数据获取,到构建健壮的批量下载器、数据清洗与验证,再到基础分析与可视化的全流程,并附有可直接运行的代码示例,帮助读者快速建立本地股票数据库。

weixin_29050513的博客 1469

NDIS HOOK实现方法

转载探索NDIS HOOK新的实现方法(1) NDIS HOOK是专业级防火墙使用的一种拦截技术,NDIS HOOK的重点是如何获得特定协议对应NDIS_PROTOCOL_BLOCK指针,获得了该指针,接下来就可以替换该协议所注册的收发函数,而达到拦截网络数据的目的。 获 得NDIS_PROTOCOL_BLOCK指针的方法一般是用NdisRegisterProtocol注...

weixin_30417487的博客 248

离线安装ambari 更换spark版本 集成carbondate文档

1、Linux系统环境配置 1.1 配置IP地址 vim /etc/sysconfig/network-script/ifcfg-eth0 “DEVICE”:网卡对应的设备别名,如ifcfg-eth0第一块网卡; “HWADDR”:网卡物理地址; “BOOTPROTO”:网卡获得ip地址的方式,Static(静态 ip地址)dhcp(通过dhcp协议获取ip)bootip通过boot...

weixin_44742962的博客 3036
上一篇: ARP双向绑定
下一篇: 逆向RING0程序从这里
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值