⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _rule.asm

📁 linux ip fiter source
💻 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 + -