阅读:1621回复:2
谁能看下我的代码(ndishook)怎么没法在win2003上工作
;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 ;接收副本大小 ;常量定义区 .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 pushad invoke CopyPktTOLocBuf,_lpPacket,addr szSendBuffer mov dwSendSize,eax invoke NdisSetEvent,lpSend3Event ;放行RING3的WaitForSingleObject(),通知RING3用ReadFile来读数据包内容(重要) popad leave jmp lpOldSend ;转到系统原来的Send例程执行 _mySend endp ;*************************************************************************************** ;*************************************************************************************** ;这是我们HOOK tcpip协议的接收函数 _myRecvP proc _lpAdapt,_lpPacket pushad invoke CopyPktTOLocBuf,_lpPacket,addr szRecvBuffer mov dwRecvSize,eax invoke NdisSetEvent,lpRecv3Event ;放行RING3的WaitForSingleObject(),通知RING3用ReadFile来读数据包内容(重要) popad leave jmp lpOldRecvP ;转到系统原来的Recv例程执行 _myRecvP endp _myRecv proc _PBC,_MRC,_HeaderBuffer,_HBSize,_LAB,_LABSize,_PacketSize pushad mov esi,_HeaderBuffer mov edi,offset szRecvBuffer mov ecx,_PacketSize mov dwRecvSize,ecx rep movsb invoke NdisSetEvent,lpRecv3Event ;放行RING3的WaitForSingleObject(),通知RING3用ReadFile来读数据包内容(重要) popad leave jmp lpOldRecv ;转到系统原来的Recv例程执行 _myRecv endp ;这是我们HOOK tcpip协议的发送完成函数 _mySendComplete proc _PBC,_Packet,_Status pushad .if szMyPacketLen ;我们自己的构造的包长度 invoke CopyPktTOLocBuf,_Packet,addr szTempBuffer mov esi,offset szTempBuffer mov edi,offset szMyPacketBuffer mov ecx,szMyPacketLen repz cmpsb ;比较包的内容 .if !ecx ;是我们的包 mov szMyPacketLen,0 ;设置包的长度 popad leave xor eax,eax ret ;是我们的包直接返回 .endif .endif popad ;不是我们的包转到系统原来例程 leave jmp lpOldSendComplete ;转到系统原来的SendComplete例程执行 _mySendComplete endp ;********************************************************************************************* ;********************************************************************************************* ;MySendPacket: 发送自已构造的数据帧(注意:包是直接交给网卡发送) ;入口: BindingHandle=NDIS_PROTOCOL_BLOCK->_NDIS_OPEN_BLOCK ; MyPacket=数据帧缓冲首址,PacketLen=数据帧长度 ;出口: dwStatus=返回状态 MySendPacket proc BindingHandle:dword,MyPacket:dword,PacketLen:dword local PacketPoolHandle:dword local PacketHandle:dword local BufferHandle:dword invoke NdisAllocatePacketPool,addr dwStatus,addr PacketPoolHandle,0FFFh,10h invoke NdisAllocateBuffer,addr dwStatus,addr BufferHandle,0,MyPacket,PacketLen invoke NdisAllocatePacket,addr dwStatus,addr PacketHandle,PacketPoolHandle invoke NdisChainBufferAtFront,PacketHandle,BufferHandle invoke NdisSend,Addr dwStatus,BindingHandle,PacketHandle .if eax!=103h ;NDIS_STATUS_PENDING=103h invoke NdisFreePacketPool,PacketPoolHandle invoke NdisFreePacket,PacketHandle invoke NdisFreeBuffer,BufferHandle .endif ret ;发送完成返回dwStatus MySendPacket endp ;********************************************************************* ;看NTDDK中的Ndis.h中有定义. NdisChainBufferAtFront proc uses ecx Packet:dword,Buffer:dword mov eax,Buffer .while 1 mov ecx,[eax] .break .if ecx==0 mov eax,ecx ;MDL.Next .endw ;eax=Tail mov ecx,Packet .if dword ptr [ecx+08h]==0 ;Packet->Private.Head mov [ecx+0ch],eax ;Packet->Private.Tail .endif mov ecx,[ecx+08h] mov [eax],ecx ;MDL.Next mov eax,Packet mov ecx,Buffer mov [eax+08h],ecx and byte ptr [eax+1ch],0 ;Packet->Private.ValidCounts ret NdisChainBufferAtFront endp ;*************************************************************************************************** ;*************************************************************************************************** ;以下空函数是为了填充NDIS_PROTOCOL_CHARACTERISTIC结构而设置的,实际下基本不会被系统调用,没有又不行。 PtBindAdapter proc Status,BindContext,DeviceName,SystemSpecific1,SystemSpecific2 xor eax,eax ret PtBindAdapter endp PtUnbindAdapter proc Status,pAdapt,UnbindContext xor eax,eax ret PtUnbindAdapter endp ;我们HOOK协议的及相关要用的函数在这里结束 ;****************************************************************************************************** end start :make set drv=ndisdrv d:\masm32\bin\ml /c /coff /Cp %drv%.bat d:\masm32\bin\link /subsystem:native /driver:wdm /release /align:16 /base:0x10000 /out:%drv%.sys %drv%.obj ;del %drv%.obj pause |
|
|
沙发#
发布于:2007-07-18 21:53
高手啊,用汇编写
看得晕 5.0下可以工作么 |
|
板凳#
发布于:2007-07-19 01:07
驱动不都是建议用c/c++写嘛?怎么用汇编?移植和兼容性能保证嘛?
|
|