cheng_5103
驱动牛犊
驱动牛犊
  • 注册日期2003-10-06
  • 最后登录2012-03-21
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望228点
  • 贡献值0点
  • 好评度45点
  • 原创分0分
  • 专家分0分
阅读:1621回复:2

谁能看下我的代码(ndishook)怎么没法在win2003上工作

楼主#
更多 发布于:2007-07-13 10:57
;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

cheng
rangzh
驱动小牛
驱动小牛
  • 注册日期2005-04-24
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望150点
  • 贡献值0点
  • 好评度115点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-07-18 21:53
高手啊,用汇编写

看得晕

5.0下可以工作么
zhou_shuang
驱动牛犊
驱动牛犊
  • 注册日期2007-06-13
  • 最后登录2008-01-05
  • 粉丝0
  • 关注0
  • 积分70分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-07-19 01:07
驱动不都是建议用c/c++写嘛?怎么用汇编?移植和兼容性能保证嘛?
游客

返回顶部