📄 _rule.asm
字号:
;__________________________________________________________________
;
; Hook函数,这个函数里面,我们可以加入所有我们需要过滤的数据包!
;
; 这里需要注意的是这种Hook防火墙不能拦截ARP/RARP和各种广播数据包!
; 只能拦截具有IP头的数据包,对应的底层协议有:ICMP/IGMP/TCP/UDP
; 不能拦截没有IP头的数据包,对应的底层协议有:ARP/RARP
;
; 这里的packet指针开始的地方就直接是数据(这里的数据只有对应的头部)
; 如:Packet[13]>>0x2就是TCP中SYN的标志
;__________________________________________________________________
; PF_DROP 直接将该数据包丢弃
; PF_PASS 直接让该数据包通过
; PF_FORWARD 把该数据包交下个过滤驱动
;__________________________________________________________________
IPfilterProc proc uses edi esi ebx PacketHeader,Packet,PacketLength,\
RecvInterfaceIndex,SendInterfaceIndex,RecvLinkNextHop,SendLinkNextHop
; 数据包处理函数 用 EDI 指向缓冲区结构 ESI 指向 PacketHeader
; 用 ECX 保存当前规则条数 用 EDX 来保存匹配情况
;------------------------------------------------------------------
lea edi,szBuffer
xor ecx,ecx
; int 3
.while ecx < sizeof szBuffer/sizeof st_packet
xor edx,edx ; 清匹配计数
mov esi,PacketHeader ; ESI->PacketHeader
; 和防火墙规则比较来源地址 0 代表任何地址
mov ebx,(IPHeader ptr [esi]).iph_src
mov eax,(st_packet ptr [edi]).ip_src
.if eax == 0 || eax == ebx
inc edx
.endif
; 和防火墙规则比较目的地址 0 代表任何地址
mov ebx,(IPHeader ptr [esi]).iph_dest
mov eax,(st_packet ptr [edi]).ip_dest
.if eax == 0 || eax == ebx
inc edx
.endif
; 和防火墙规则比较数据包方向 0 代表任何方向
.if SendInterfaceIndex == INVALID_PF_IF_INDEX
mov ebx,1 ; 是接收到数据包
.else
mov ebx,2 ; 是发送要数据包
.endif
movzx eax,(st_packet ptr [edi]).ip_direction
.if eax == 0 || eax == ebx
inc edx
.endif
mov al,(IPHeader ptr [esi]).iph_protocol
; 和防火墙规则比较协议 0 代表任何协议
mov ah,(st_packet ptr [edi]).ip_protocol
.if ah == 0 || al == ah
inc edx
.endif
; 如果是 ICMP 和 IGMP 则直接处理
.if al == IPPROTO_ICMP || al == IPPROTO_IGMP
.if edx > 3 ; == 4
movzx eax,(st_packet ptr [edi]).ip_operation
ret
.endif
.endif
mov esi,Packet ; ESI->Packet
; 和防火墙规则比较来源端口 0 代表任何端口
mov bx,(TCPHead ptr [esi]).src_port
xchg bh,bl ; 调整直接顺序
mov ax,(st_packet ptr [edi]).src_port
.if ax == 0 || ax == bx
inc edx
.endif
; 和防火墙规则比较目的端口 0 代表任何端口
mov bx,(TCPHead ptr [esi]).dest_port
xchg bh,bl ; 调整直接顺序
mov ax,(st_packet ptr [edi]).dest_port
.if ax == 0 || ax == bx
inc edx
.endif
; 和防火墙规则比较TCP标志 如果不是TCP协议这里为 0
mov bl,(TCPHead ptr [esi]).flags
mov al,(st_packet ptr [edi]).tcp_sign
.if al == 0 || al == bl
inc edx
.endif
; 全部为符合的话则返回该规则的操作
.if edx > 6 ; == 7
movzx eax,(st_packet ptr [edi]).ip_operation
ret
.else
; 如果不符合则继续检查
add edi,sizeof st_packet
inc ecx
.endif
.endw
; 全部规则都不符合则返回默认的操作 PF_PASS (通过)
mov eax,PF_PASS
ret
IPfilterProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_LoadRule proc OpRead ; OpRead == 0 读 OpRead == 1 写
local h_rules,@Ret
local oa:OBJECT_ATTRIBUTES
local iostatus:IO_STATUS_BLOCK
local _offset:LARGE_INTEGER
local FileName:UNICODE_STRING
local TempName:UNICODE_STRING
;------------------------------------------------------------------
; 驱动启动的时候加载原来的规则
mov @Ret,0FFFFFFFFh
invoke RtlInitAnsiString,addr TempName,offset szRuleFile
invoke RtlAnsiStringToUnicodeString,addr FileName,addr TempName,TRUE
lea ecx,oa ; 这里用 ECX 和 EAX 可以优化
lea eax,FileName
mov (OBJECT_ATTRIBUTES ptr [ecx]).dwLength,sizeof OBJECT_ATTRIBUTES
mov (OBJECT_ATTRIBUTES ptr [ecx]).RootDirectory,0
mov (OBJECT_ATTRIBUTES ptr [ecx]).ObjectName,eax
mov (OBJECT_ATTRIBUTES ptr [ecx]).Attributes,OBJ_CASE_INSENSITIVE
mov (OBJECT_ATTRIBUTES ptr [ecx]).SecurityDescriptor,0
mov (OBJECT_ATTRIBUTES ptr [ecx]).SecurityQualityOfService,0
; 下面这个宏有问题
; InitializeObjectAttributes ecx,eax,OBJ_CASE_INSENSITIVE,0,0
; 如果文件不存在则创建
invoke ZwCreateFile,addr h_rules,100001h,addr oa,addr iostatus,0,0,1,FILE_OPEN_IF,0,0,0
.if eax == STATUS_SUCCESS ; 打开文件成功
xor eax,eax
mov _offset.LowPart,eax
mov _offset.HighPart,eax
.if OpRead == 0
invoke ZwReadFile,h_rules,0,0,0,addr iostatus,offset szBuffer,\
sizeof szBuffer,addr _offset,0
.else
invoke ZwWriteFile,h_rules,0,0,0,addr iostatus,offset szBuffer,\
sizeof szBuffer,addr _offset,0
.endif
.if eax == STATUS_PENDING ; 阻塞则等待
invoke ZwWaitForSingleObject,h_rules,0,0
mov eax,iostatus.Status
.endif
.if eax == STATUS_SUCCESS || eax == STATUS_END_OF_FILE ; 读取成功
mov @Ret,eax
.endif
invoke ZwClose,h_rules ; 关闭已经打开的文件
.endif
invoke RtlFreeUnicodeString,addr FileName
mov eax,@Ret ; 设置返回值
ret
_LoadRule endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -