本人写的一个ARP防火墙源代码奉献(1)
作者:cheng5103
发表时间:2007-7-31 13:21:00
作者:成松林
QQ:179641795
转贴请不要改变作者信息!
为了简单、速度代码在以前研究驱动基础上改写。
驱动层源代码:
;goto make
.586p
.model flat,stdcall
option casemap:none
includelib D:\masm32\LIB\w2k\ntoskrnl.lib
includelib D:\masm32\LIB\w2k\hal.lib
includelib D:\masm32\LIB\w2k\ndis.lib
;***************************************************************
;没有INC文件,要使用的NDIS函数定义
NdisChainBufferAtFront proto :DWORD,:DWORD
CopyPktTOLocBuf proto :DWORD,:DWORD
NdisAllocatePacketPool PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
NdisAllocateBuffer PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
NdisAllocatePacket PROTO STDCALL :DWORD,:DWORD,:DWORD
NdisSend PROTO STDCALL :DWORD,:DWORD,:DWORD
MySendPacket proto :dword,:dword,:dword
NdisQueryBufferSafe proto :dword,:dword,:dword,:dword
NdisInitializeEvent proto :dword
NdisSetEvent proto :dword
NdisResetEvent proto :dword
NdisFreePacketPool proto :dword
NdisFreePacket proto :dword
NdisFreeBuffer proto :dword
NdisWaitEvent proto :dword,:dword
NdisRegisterProtocol proto :dword,:dword,:dword,:dword
NdisDeregisterProtocol proto :dword,:dword
IoCreateDevice proto :dword,:dword,:dword,:dword,:dword,:dword,:dword
IoDeleteDevice proto :dword
IoCreateSymbolicLink proto :dword,:dword
IoDeleteSymbolicLink proto :dword
IoCompleteRequest proto :dword,:dword
IoCreateNotificationEvent proto :dword,:dword
RtlCompareUnicodeString proto :dword,:dword,:dword
ZwClose proto :dword
;***************************************************************
;公共数据定义区
.data
lpProtocolHandle dd 0 ;协议句柄的指针
lpDeviceObject dd 0 ;设备对象的指针
;*********************************
lpOldSend dd 0 ;保存TCPIP协议驱动的OPEN_BLOCK里的SendHandler派发函数地址
lpOldRecv dd 0 ;保存TCPIP协议驱动的OPEN_BLOCK里的ReceiveHandler派发函数地址
lpOldRecvP dd 0 ;保存TCPIP协议驱动的OPEN_BLOCK里的ReceivePacketHandler派发函数地址
lpOldSendComplete dd 0 ;保存TCPIP协议驱动的OPEN_BLOCK里的SendCompleteHandler派发函数地址
;*******************************
lpSend3Event dd 0 ;RING3发送事件在本驱动的指针
hSend3Event dd 0 ;RING3发送事件在本驱动的句柄
lpRecv3Event dd 0 ;RING3接收事件在本驱动的指针
hRecv3Event dd 0 ;RING3接收事件在本驱动的句柄
dwStatus dd 0
dwTempVar dd 0
obSendEvent db 16 dup(0) ;RING0 SEND对象
obRecvEvent db 16 dup(0) ;RING0 RECV对象
stProtocolChar db 70h dup(0) ;NdisRegisterProtocol()要使用的NDIS_PROTOCOL_CHARACTERISTIC结构
szSendBuffer db 800h dup(0) ;系统将要发送的数据包的副本
szRecvBuffer db 800h dup(0) ;系统将要接收的数据包的副本
szTempBuffer db 800h dup(0)
szMyPacketBuffer db 800h dup(0)
szMyPacketLen dd 0
dwSendSize dd 0 ;发送副本大小
dwRecvSize dd 0 ;接收副本大小
GateWay db 10 dup (0) ;网关IP和MAC
;常量定义区
.const
stTcpip dw 5*2,6*2
dd offset szTcpip
szTcpip dw 'T','c','p','i','p',0
stDeviceName dw 15*2,16*2
dd offset szDeviceName
szDeviceName dw '\','D','e','v','i','c','e','\','N','d','i','s','D','r','v',0
stSymbolicLinkName dw 19*2,20*2
dd offset szSymbolicLinkName
szSymbolicLinkName dw '\','D','o','s','D','e','v','i','c','e','s','\','N','D','I','S','D','R','V',0
stSend3Event dw 28*2,29*2
dd offset szSend3Event
szSend3Event dw '\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\','S','e','n','d','3','E','v','e','n','t',0
stRecv3Event dw 28*2,29*2
dd offset szRecv3Event
szRecv3Event dw '\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s','\','R','e','c','v','3','E','v','e','n','t',0
;**************************************************************************************
;*************************************************************************************
;驱动主程序代码从这里开始
.code
start proc DriverObject,RegisterPath ;安装驱动上层传下来两个参数
pushad ;保存堆栈
; 这里开始是关于协议操作的代码
;注册假协议返回lpProtocolHandle指向的NDIS_PROTOCOL_BLOCK链表首地址
;NDIS_PROTOCOL_BLOCK(协议表)是NDIS维护所有系统中已注册协议的单向链接表
mov dword ptr stProtocolChar,5
mov dword ptr stProtocolChar+3ch,offset PtBindAdapter
mov dword ptr stProtocolChar+40h,offset PtUnbindAdapter
;以上是填充NDIS_PROTOCOL_CHARACTERISTIC结构
invoke NdisRegisterProtocol,offset dwStatus,offset lpProtocolHandle,offset stProtocolChar,6ch
cmp dwStatus,0
jnz _exit ;注册假协议失败退出驱动
;********************************
mov ebx,lpProtocolHandle
mov ebx,[ebx+10h] ;去掉我们注册的假协议.
;我们注册的假协议已经没有用了,注销掉.
invoke NdisDeregisterProtocol,offset dwStatus,lpProtocolHandle
mov lpProtocolHandle,ebx ;保存真正的系统协议链表的首地址
;这个循环是在系统协议链表搜索TCPIP协议的PROTOCOL_HANDLE,ebx->NDIS_PROTOCOL_BLOCK链表首
mov esi,offset stTcpip ;esi->Unicode格式(NTDDK中IFSDDK.INC)定义的协议名
.repeat
lea edi,[ebx+44h] ;当前协议名(Unicode格式)
invoke RtlCompareUnicodeString,edi,esi,1 ;进行与我们查找的进行比较
.break .if eax==0 ;查找到退出循环
mov ebx,[ebx+10h] ;ebx->下一个协议
.until ebx==0 ;查找到表尾
cmp eax,0
jnz _exit ;协议没找到退出驱动
;************************************************************************************
;正常的协议工作流程:1、调用NdisRegisterProtocol注册协议,2、下层协议(或系统管理层协议)
;会调用协议链表里的所有协议的BindAdapterHandler派发函数,这是注册协议的回调过程.
;3、BindAdapterHandler派发函数里会调用NdisOpenAdapter来绑定自己到合适网络设备.
;4、最后NdisOpenAdapter函数返回BindingHandle,BindingHandle指向NDIS_OPEN_BLOCK链表.
;勾挂NDIS_OPEN_BLOCK链表:1、接收数据ReceiveHandle、ReceivePacketHandler函数
;2、发送数据SendHandler、SendPacketsHandler函数.
mov ebx,[ebx] ;ebx->tcpip的NDIS_OPEN_BLOCK链表系统不同版本不同
mov lpProtocolHandle,ebx ;保存TCPIP协议的OPEN_BLOCK(BINDING_HANDLE)
mov eax,[ebx+30h]
mov lpOldSend,eax ;保存TCPIP协议驱动的OPEN_BLOCK里的SendHandler派发函数地址
mov eax,[ebx+40h]
mov lpOldRecv,eax ;保存TCPIP协议驱动的OPEN_BLOCK里的ReceiveHandler派发函数地址
mov eax,[ebx+50h]
mov lpOldRecvP,eax ;保存TCPIP协议驱动的OPEN_BLOCK里的ReceivePacketHandler派发函数地址
mov eax,[ebx+38h]
mov lpOldSendComplete,eax ;保存TCPIP协议驱动的OPEN_BLOCK里的SendCompleteHandler派发函数地址
; 协议操作代码在这里结束HOOK函数代码在后面.
;*************************************************************************************
;*******************************************************************************************************************
; 这里开始是建立一个可以让应用程序(ring3)访问的驱动.以事件方式建立,数据传送方式为DIRECT_IO.
;建立设备以备应用程序访问,DeviceExtension size=18h, type= device_transfer
invoke IoCreateDevice,DriverObject,18h,offset stDeviceName,21h,0,0,offset lpDeviceObject
invoke IoCreateSymbolicLink,offset stSymbolicLinkName,offset stDeviceName
mov eax,lpDeviceObject
or dword ptr [eax+1ch],10h ;把device.flag设置为DO_DIRECT_IO,使驱动程序的READ、WRITE例程直接映射用户缓冲区到本驱动
mov edi,DriverObject
add edi,38h
mov ecx,1ch
mov eax,offset _CommonIoControl
rep stosd ;填充共用例程,必须,否则CreateFile()不能打开本驱动
;***********************
mov eax,DriverObject
mov dword ptr [eax+34h],offset _Unload
mov dword ptr [eax+44h],offset _Read
mov dword ptr [eax+48h],offset _Write ;注册驱动例程
mov byte ptr [eax+8],2 ;强行修改Driver.flag为legacy driver,否则DriverEntry返回时系统就会卸载本驱动(因为本驱动默认编译为WDM drvier)
;建立RING0事件
invoke NdisInitializeEvent,offset obSendEvent
invoke NdisInitializeEvent,offset obRecvEvent
invoke NdisResetEvent,offset obSendEvent
invoke NdisResetEvent,offset obRecvEvent
;建立RING3事件,在RING3用OpenEvent()打开
invoke IoCreateNotificationEvent,offset stSend3Event,offset hSend3Event
mov lpSend3Event,eax
invoke NdisResetEvent,eax
invoke IoCreateNotificationEvent,offset stRecv3Event,offset hRecv3Event
mov lpRecv3Event,eax
invoke NdisResetEvent,eax
; 建立可让应用程序访问的驱动代码在这里结束.
;***************************************************************************************
;***************************************************************************************
; 这里是设置HOOK TCPIP协议的函数
mov ebx,lpProtocolHandle ;ebx->NDIS_OPEN_BLOCK
mov dword ptr [ebx+30h],offset _mySend ;HOOK TCPIP协议的Send
mov dword ptr [ebx+40h],offset _myRecv ;HOOK TCPIP协议的Recv
mov dword ptr [ebx+50h],offset _myRecvP ;HOOK TCPIP协议的RecvPacket
mov dword ptr [ebx+38h],offset _mySendComplete ;HOOK TCPIP协议的SendComplete
;*****************************************************************************************
_exit:
popad
xor eax,eax
ret
start endp
;驱动主程序在这里结束..
;****************************************************************************************
;*****************************************************************************************
;这里开始是驱动程序的分派函数
;卸载驱动程序函数
_Unload proc DriverObject
mov edx,lpProtocolHandle
mov eax,lpOldSend
mov [edx+30h],eax
mov eax,lpOldRecv
mov [edx+40h],eax
mov eax,lpOldRecvP
mov [edx+50h],eax
mov eax,lpOldSendComplete
mov [edx+38h],eax
;恢复TCPIP协议的OPEN_BLOCK里原来的派发例程
invoke ZwClose,hSend3Event
invoke ZwClose,hRecv3Event
invoke NdisSetEvent,offset obSendEvent
invoke NdisSetEvent,offset obRecvEvent
invoke IoDeleteSymbolicLink,offset stSymbolicLinkName
invoke IoDeleteDevice,lpDeviceObject
xor eax,eax
ret
_Unload endp
;******************************************************************************************
;***************************************************************************************
;驱动程序公共控制函数
_CommonIoControl proc DeviceObject,pIrp
mov eax,pIrp
mov dword ptr [eax+18h],0
mov dword ptr [eax+1ch],0
invoke IoCompleteRequest,pIrp,0
xor eax,eax
ret
_CommonIoControl endp
;***************************************************************************************
;***************************************************************************************
;驱动程序传给应用程序数据函数.应用程序用ReadFile()调用
_Read proc DeviceObject,pIrp
pushad
mov ebx,pIrp
mov edi,[ebx+4]
mov ecx,[edi+18h]
mov edi,[edi+10h]
add edi,ecx ;EDI=用户缓冲区
mov ecx,lpSend3Event
mov edx,lpRecv3Event
.if dword ptr [ecx+4]
invoke NdisResetEvent,lpSend3Event ;RING3事件复位,防止再次放行
mov esi,offset szSendBuffer
mov ecx,dwSendSize
mov eax,[ebx+60h]
.if ecx>[eax+4]
mov ecx,[eax+4]
.endif
.else
invoke NdisResetEvent,lpRecv3Event
mov esi,offset szRecvBuffer
mov ecx,dwRecvSize
mov eax,[ebx+60h]
.if ecx>[eax+4]
mov ecx,[eax+4]
.endif
.endif
mov dword ptr [ebx+18h],0
mov dword ptr [ebx+1ch],ecx ;设置ReadFile()的读取字节数
rep movsb ;把数据包复制到ReadFile()提供的缓冲区
invoke IoCompleteRequest,pIrp,0
popad
xor eax,eax
ret
_Read endp
;***************************************************************************************
;***************************************************************************************
;***************************************************************************************
;应用程序传给驱动程序数据函数.应用程序用WriteFile()调用
_Write proc DeviceObject,pIrp
mov eax,pIrp
mov dword ptr [eax+18h],0
mov dword ptr [eax+1ch],0
mov edx,[eax+4]
mov ecx,[eax+60h]
mov ecx,[ecx+4] ;ECX=数据长度
mov eax,[edx+18h]
mov edx,[edx+10h]
add edx,eax ;EDX=用户缓冲区
mov szMyPacketLen,ecx ;我们自己构造的包长度
mov edi,offset szMyPacketBuffer
mov esi,edx
rep movsb ;拷贝包到本驱动
;发送应用程序传下来的数据包
invoke MySendPacket,lpProtocolHandle,addr szMyPacketBuffer,szMyPacketLen
invoke IoCompleteRequest,pIrp,0
xor eax,eax
ret
_Write endp
;驱动程序的分派函数在这里结束
;***************************************************************************************
;***************************************************************************************
;这里开始是我们HOOK协议的及相关要用的函数
;将发送和接收的包拷到本地缓冲区
CopyPktTOLocBuf proc uses ebx ecx edi esi _lpPacket:dword,_lpBuffer:dword
local PacketVa:dword
local PacketSize:dword
mov ebx,_lpPacket
mov ebx,[ebx+8]
;循环复制协议数据包到指定缓冲区里
mov edi,_lpBuffer
.repeat
invoke NdisQueryBufferSafe,ebx,addr PacketVa,addr PacketSize,20h
mov esi,PacketVa
mov ecx,PacketSize
rep movsb
mov ebx,[ebx]
.until ebx==0
sub edi,_lpBuffer
mov eax,edi
ret
CopyPktTOLocBuf endp
;这是我们HOOK tcpip协议的发送函数
_mySend proc _lpAdapt,_lpPacket
local PacketVa:dword
local PacketSize:dword
pushad
invoke CopyPktTOLocBuf,_lpPacket,addr szRecvBuffer
mov dwSendSize,eax
invoke NdisSetEvent,lpSend3Event ;放行RING3的WaitForSingleObject(),通知RING3用ReadFile来读数据包内容(重要)
popad
leave
jmp lpOldSend ;转到系统原来的Send例程执行
_mySend endp
;***************************************************************************************
;***************************************************************************************
;这是我们HOOK tcpip协议的接收函数
_myRecvP proc _lpAdapt,_lpPacket
local PacketVa:dword
local PacketSize:dword
pushad
invoke CopyPktTOLocBuf,_lpPacket,addr szRecvBuffer
mov dwRecvSize,eax
invoke NdisSetEvent,lpRecv3Event ;放行RING3的WaitForSingleObject(),通知RING3用ReadFile来读数据包内容(重要)
;*************************************************************************************