|
[求助]在程序中汇编哪些语句,当执行到这里会调出OD????????
目的就是为了产生无效指令 |
|
|
|
|
|
[求助]在程序中汇编哪些语句,当执行到这里会调出OD????????
我想在程序中编写几个特别的语句,程序编译运行后,可以自动调出OD来调试程序。 |
|
[下载]asp服务器,网络验证必备工具
xiexie |
|
|
|
|
|
[讨论]请大家在此贴发表--破解网络验证的有用工具软件
下面是一本书里的源代码FilterTdiDriver,但它只是实现了截获IRP请求并把它直接转发到了底层,并未作任何处理。 PACKET.H #define DD_TCP_DEVICE_NAME L\"\\\\Device\\\\Tcp\" #define TDIH_TCP_DEVICE_NAME L\"\\\\Device\\\\TonyTcpFilter\" #define TDIH_DEV_EXT_ATTACHED (0x00000001) /************************************************************************** 每一个结构必须有一个唯一的“node type”或者一个联合签名 **************************************************************************/ #define TDIH_NODE_TYPE_TCP_FILTER_DEVICE (0xfdecba12) /* 输出调试信息 */ #define DBGPRINT(Fmt) \\ { \\ DbgPrint(\" ***FilterTdiDriver.sys*** \"); \\ DbgPrint (Fmt); \\ } /* 进行64位数值的处理,请参阅DDK帮助文档关于RtlLargeIntegerEqualToZero的解释 */ #define UTIL_IsLargeIntegerZero(ReturnValue, LargeIntegerOp, pSpinLock) \\ { \\ KIRQL OldIrql; \\ KeAcquireSpinLock(pSpinLock, &OldIrql); \\ ASSERT(RtlLargeIntegerGreaterOrEqualToZero((LargeIntegerOp))); \\ ReturnValue = RtlLargeIntegerEqualToZero((LargeIntegerOp)); \\ KeReleaseSpinLock(pSpinLock, OldIrql); \\ } //―――――――――――――――――――――――――――――――――――――― // 用来保存驱动程序相关信息的自定义结构类型,这个结构类型可以绑定到 // DEVICE_OBJECT对象的DeviceExtension成员变量之上,随着DEVICE_OBJECT对象在 // 不同的函数之间传递 // typedef struct _TDIH_DeviceExtension { ULONG NodeType; // 标识这个结构 ULONG NodeSize; // 这个结构的大小 PDEVICE_OBJECT pFilterDeviceObject; // 过滤设备对象 KSPIN_LOCK IoRequestsSpinLock; // 同时调用时的保护锁 KEVENT IoInProgressEvent; // 进程间同步处理 ULONG DeviceExtensionFlags; // 设备标志 PDEVICE_OBJECT TargetDeviceObject; // 绑定的设备对象 PFILE_OBJECT TargetFileObject; // 绑定设备的文件对象 PDEVICE_OBJECT LowerDeviceObject; // 绑定前底层设备对象 LARGE_INTEGER OutstandingIoRequests; } TDIH_DeviceExtension, *PTDIH_DeviceExtension; /////////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); VOID PacketUnload( IN PDRIVER_OBJECT DriverObject ); NTSTATUS PacketDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS PacketCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS TCPFilter_Attach( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS TCPFilter_InitDeviceExtension( IN PTDIH_DeviceExtension pTDIH_DeviceExtension, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PFILE_OBJECT pTargetFileObject, IN PDEVICE_OBJECT pLowerDeviceObject ); VOID TCPFilter_Detach( IN PDEVICE_OBJECT pDeviceObject ); Packet.c #include #include #include #include \"packet.h\" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status = 0; ULONG i; DBGPRINT(\"DriverEntry Loading...\\n\"); DriverObject->DriverUnload = PacketUnload; for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction = PacketDispatch; } status = TCPFilter_Attach(DriverObject,RegistryPath); return status; } VOID PacketUnload( IN PDRIVER_OBJECT DriverObject ) { PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT OldDeviceObject; PTDIH_DeviceExtension pTDIH_DeviceExtension; DBGPRINT(\"DriverEntry unLoading...\\n\"); DeviceObject = DriverObject->DeviceObject; while (DeviceObject != NULL) { OldDeviceObject = DeviceObject; pTDIH_DeviceExtension = (PTDIH_DeviceExtension )DeviceObject->DeviceExtension; if( pTDIH_DeviceExtension->NodeType == TDIH_NODE_TYPE_TCP_FILTER_DEVICE ) TCPFilter_Detach( DeviceObject ); // Calls IoDeleteDevice else IoDeleteDevice(OldDeviceObject); DeviceObject = DeviceObject->NextDevice; } } NTSTATUS PacketDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS RC = STATUS_SUCCESS; PTDIH_DeviceExtension pTDIH_DeviceExtension; PIO_STACK_LOCATION IrpStack; PIO_STACK_LOCATION NextIrpStack; pTDIH_DeviceExtension = (PTDIH_DeviceExtension )(DeviceObject->DeviceExtension); IrpStack = IoGetCurrentIrpStackLocation(Irp); switch(IrpStack->MajorFunction) { case IRP_MJ_CREATE: DBGPRINT(\"PacketDispatch(IRP_MJ_CREATE)...\\n\"); break; case IRP_MJ_CLOSE: DBGPRINT(\"PacketDispatch(IRP_MJ_CLOSE)...\\n\"); break; case IRP_MJ_CLEANUP: DBGPRINT(\"PacketDispatch(IRP_MJ_CLEANUP)...\\n\"); break; case IRP_MJ_INTERNAL_DEVICE_CONTROL: switch (IrpStack->MinorFunction) { case TDI_ACCEPT: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_ACCEPT])...\\n\"); break; case TDI_ACTION: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_ACTION])...\\n\"); break; case TDI_ASSOCIATE_ADDRESS: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_ASSOCIATE_ADDRESS])...\\n\"); break; case TDI_DISASSOCIATE_ADDRESS: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_DISASSOCIATE_ADDRESS])...\\n\"); break; case TDI_CONNECT: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_CONNECT])...\\n\"); break; case TDI_DISCONNECT: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_DISCONNECT])...\\n\"); break; case TDI_LISTEN: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_LISTEN])...\\n\"); break; case TDI_QUERY_INFORMATION: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_QUERY_INFORMATION])...\\n\"); break; case TDI_RECEIVE: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_RECEIVE])...\\n\"); break; case TDI_RECEIVE_DATAGRAM: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_RECEIVE_DATAGRAM])...\\n\"); break; case TDI_SEND: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_SEND])...\\n\"); break; case TDI_SEND_DATAGRAM: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_SEND_DATAGRAM])...\\n\"); break; case TDI_SET_EVENT_HANDLER: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_SET_EVENT_HANDLER])...\\n\"); break; case TDI_SET_INFORMATION: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [TDI_SET_INFORMATION])...\\n\"); break; default: DBGPRINT(\"PacketDispatch(IRP_MJ_INTERNAL_DEVICE_CONTROL\\ [INVALID_MINOR_FUNCTION])...\\n\"); break; } break; case IRP_MJ_DEVICE_CONTROL: DBGPRINT(\"PacketDispatch(IRP_MJ_DEVICE_CONTROL)...\\n\"); break; default: DBGPRINT(\"PacketDispatch(OTHER_MAJOR_FUNCTION)...\\n\"); break; } if (Irp->CurrentLocation == 1) { ULONG ReturnedInformation = 0; DBGPRINT((\"PacketDispatch encountered bogus current location\\n\")); RC = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = RC; Irp->IoStatus.Information = ReturnedInformation; IoCompleteRequest(Irp, IO_NO_INCREMENT); return( RC ); } NextIrpStack = IoGetNextIrpStackLocation(Irp); *NextIrpStack = *IrpStack; IoSetCompletionRoutine(Irp,PacketCompletion,NULL,TRUE,TRUE,TRUE); return IoCallDriver(pTDIH_DeviceExtension->LowerDeviceObject,Irp); } NTSTATUS PacketCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { if(Irp->PendingReturned) IoMarkIrpPending(Irp); return STATUS_SUCCESS; } NTSTATUS TCPFilter_Attach( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status = 0; UNICODE_STRING uniNtNameString; PTDIH_DeviceExtension pTDIH_DeviceExtension; PDEVICE_OBJECT pFilterDeviceObject = NULL; PDEVICE_OBJECT pTargetDeviceObject = NULL; PFILE_OBJECT pTargetFileObject = NULL; PDEVICE_OBJECT pLowerDeviceObject = NULL; DBGPRINT(\"TCPFilter_Attach.\\n\"); RtlInitUnicodeString( &uniNtNameString, DD_TCP_DEVICE_NAME ); status = IoGetDeviceObjectPointer( IN &uniNtNameString, IN FILE_READ_ATTRIBUTES, OUT &pTargetFileObject, OUT &pTargetDeviceObject ); if( !NT_SUCCESS(status) ) { DBGPRINT((\"TCPFilter_Attach: Couldn\'t get the TCP Device Object\\n\")); pTargetFileObject = NULL; pTargetDeviceObject = NULL; return( status ); } RtlInitUnicodeString( &uniNtNameString, TDIH_TCP_DEVICE_NAME ); status = IoCreateDevice( IN DriverObject, IN sizeof( TDIH_DeviceExtension ), IN &uniNtNameString, IN pTargetDeviceObject->DeviceType, IN pTargetDeviceObject->Characteristics, IN FALSE, OUT &pFilterDeviceObject ); if( !NT_SUCCESS(status) ) { DBGPRINT((\"TCPFilter_Attach: Couldn\'t create the TCP Filter Device Object\\n\")); ObDereferenceObject( pTargetFileObject ); pTargetFileObject = NULL; pTargetDeviceObject = NULL; return( status ); } pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject,pTargetDeviceObject); if( !pLowerDeviceObject ) { DBGPRINT((\"TCPFilter_Attach: Couldn\'t attach to TCP Device Object\\n\")); IoDeleteDevice( pFilterDeviceObject ); pFilterDeviceObject = NULL; ObDereferenceObject( pTargetFileObject ); pTargetFileObject = NULL; pTargetDeviceObject = NULL; return( status ); } pTDIH_DeviceExtension = (PTDIH_DeviceExtension )( pFilterDeviceObject->DeviceExtension ); TCPFilter_InitDeviceExtension( IN pTDIH_DeviceExtension, IN pFilterDeviceObject, IN pTargetDeviceObject, IN pTargetFileObject, IN pLowerDeviceObject ); pFilterDeviceObject->Flags |= pTargetDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO); return status; } NTSTATUS TCPFilter_InitDeviceExtension( IN PTDIH_DeviceExtension pTDIH_DeviceExtension, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PFILE_OBJECT pTargetFileObject, IN PDEVICE_OBJECT pLowerDeviceObject ) { NdisZeroMemory( pTDIH_DeviceExtension, sizeof( TDIH_DeviceExtension ) ); pTDIH_DeviceExtension->NodeType = TDIH_NODE_TYPE_TCP_FILTER_DEVICE; pTDIH_DeviceExtension->NodeSize = sizeof( TDIH_DeviceExtension ); pTDIH_DeviceExtension->pFilterDeviceObject = pFilterDeviceObject; KeInitializeSpinLock(&(pTDIH_DeviceExtension->IoRequestsSpinLock)); KeInitializeEvent(&(pTDIH_DeviceExtension->IoInProgressEvent) , NotificationEvent, FALSE); pTDIH_DeviceExtension->TargetDeviceObject = pTargetDeviceObject; pTDIH_DeviceExtension->TargetFileObject = pTargetFileObject; pTDIH_DeviceExtension->LowerDeviceObject = pLowerDeviceObject; pTDIH_DeviceExtension->DeviceExtensionFlags |= TDIH_DEV_EXT_ATTACHED; return( STATUS_SUCCESS ); } VOID TCPFilter_Detach( IN PDEVICE_OBJECT pDeviceObject ) { PTDIH_DeviceExtension pTDIH_DeviceExtension; BOOLEAN NoRequestsOutstanding = FALSE; pTDIH_DeviceExtension = (PTDIH_DeviceExtension )pDeviceObject->DeviceExtension; try { try { while (TRUE) { UTIL_IsLargeIntegerZero( NoRequestsOutstanding, pTDIH_DeviceExtension->OutstandingIoRequests, &(pTDIH_DeviceExtension->IoRequestsSpinLock) ); if( !NoRequestsOutstanding ) KeWaitForSingleObject( (void *)(&(pTDIH_DeviceExtension->IoInProgressEvent)), Executive, KernelMode, FALSE, NULL ); else break; } if( pTDIH_DeviceExtension->DeviceExtensionFlags & TDIH_DEV_EXT_ATTACHED) { IoDetachDevice( pTDIH_DeviceExtension->TargetDeviceObject ); pTDIH_DeviceExtension->DeviceExtensionFlags &= ~(TDIH_DEV_EXT_ATTACHED); } pTDIH_DeviceExtension->NodeType = 0; pTDIH_DeviceExtension->NodeSize = 0; if( pTDIH_DeviceExtension->TargetFileObject ) ObDereferenceObject( pTDIH_DeviceExtension->TargetFileObject ); pTDIH_DeviceExtension->TargetFileObject = NULL; IoDeleteDevice( pDeviceObject ); DBGPRINT((\"TCPFilter_Attach: TCPFilter_Detach Finished\\n\")); } except (EXCEPTION_EXECUTE_HANDLER){} } finally{} return; } |
|
[讨论]请大家在此贴发表--破解网络验证的有用工具软件
网络数据包拦截通用技术 所属类别:VC++ 文章作者:甘嘉平 (gjp) 推荐指数:★★☆ 文档人气:197 本周人气:7 发布日期:2007-5-24 看到很多仁兄提供的数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层 对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据包进行拦截。这是微软提供的一种技术 但编写该过滤程序拦截程序非常的复杂,安装也很麻烦。 本人简单的介绍一种更有效的基于NDIS包拦截技术。 大家都知道,NDIS协议驱动程序是通过填写一张NDIS_PROTOCOL_CHARACTERISTICS的表,并调用NDIS API 函数NdisRegisterProtocol进行注册。现在我们来关注一下NDIS_PROTOCOL_CHARACTERISTICS这张表, 这张表中存有所有协议驱动程序与底层的派发函数的入口。如SendHandler,ReceiveHandler,BindAdapterHandler等, 当网卡有数据包进入时,会通过表中ReceiveHandle 或ReceivePacketHandler通知协议驱动程序有一个该协议 的数据包进入,反之协议驱动程序是通过SendHandler或SendPacketsHandler函数向网卡驱动发送数据包到网络 上去的,有人会奇怪程序中明明不是调用NdisSend或NdisSendPackets函数发送的吗?没错,是这样的, 但是你可以看一下NDIS。H的头文件里对这两个函数的定义就知道了,他们都是一个 宏定义实际还是通过这表中SendHandler或SendPacketsHandler发送的。 现在我们所要做的事情应该很清楚了,只要我们能够将每一个协议程序所填写的NDIS_PROTOCOL_CHARACTERISTICS 表里的派发函数指向自己的函数,我们就能成功的对数据包进行拦截。那么每个协议驱动程序的这张表到底存放在 那里呢?太简单了,看一下下面的我对NdisRegisterProtocol重新给出的原型就很明白了。 struct _NDIS_PROTOCOL_BLOCK { PNDIS_OPEN_BLOCK OpenQueue; // queue of opens for this protocol REFERENCE Ref; // contains spinlock for OpenQueue UINT Length; // of this NDIS_PROTOCOL_BLOCK struct NDIS50_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;// handler addresses struct _NDIS_PROTOCOL_BLOCK * NextProtocol; // Link to next ULONG MaxPatternSize; #if defined(NDIS_WRAPPER) // // Protocol filters // struct _NDIS_PROTOCOL_FILTER * ProtocolFilter[NdisMediumMax+1]; WORK_QUEUE_ITEM WorkItem; // Used during NdisRegisterProtocol to // notify protocols of existing drivers. KMUTEX Mutex; // For serialization of Bind/Unbind requests PKEVENT DeregEvent; // Used by NdisDeregisterProtocol #endif }; typedef struct _NDIS_PROTOCOL_BLOCK NDIS_PROTOCOL_BLOCK, *PNDIS_PROTOCOL_BLOCK; EXPORT VOID NdisRegisterProtocol( OUT PNDIS_STATUS Status, OUT PNDIS_PROTOCOL_BLOCK NdisProtocolHandle, /*注意NDIS_HANDLE所指向的就是PNDIS_PROTOCOL_BLOCK的结构,不要有什么怀疑。*/ IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, IN UINT CharacteristicsLength ); NDIS_PROTOCOL_BLOCK(协议表) 是NDIS维护所有系统中已注册协义的单向链接表。字段NextProtocol指向下一个协议表。 庆幸的是,当我们注册一新的协议时,NDIS总是会把新注册的协义放在链表的头并返回这张表,所以只要我们注册一个新的协议 通过新协议注册返回的链表头就可以轻而易举的遍历系统中所有协议表.现在我们所希望得到的每个协议的 NDIS_PROTOCOL_CHARACTERISTICS表就放在我们面前了,如何勾挂表中的派发函数,我想不必多说了吧。顺便说一句 NDISREGISTERPROTOCOL为NDIS_PROTOCOL_BLOCK所分配的内存是NonPagedPool类型的。对于核心DRIVER来说,核心区内存 是一个线性的内存区,所有核心DRIVER是可以随便访问核心内存区的任意地址。所要注意的是不同IRQL级别下对分页 和非分页内存。 有人会问这样就行了吗?真的拦截下来了吗?如果有那位仁兄心急现在就写程序的话, 准会失望的,因为他会发现结果什么东西都没拦截到或偶而会拦截到一些数据包。为什么? 因为NDIS网卡驱动和协议驱动在发送和接收到数居时并不是调用PNDIS_OPEN_BLOCK->ProtocolCharacteristics 里的派发函数。怎么办? 有必要先介绍一下NDIS网卡驱动和协议驱动之间是如何BINDING 的吧, NdisRegisterProtocol在注册完一个协议后,不久NDIS会通过调用表中 BindAdapterHandler派发函数,通知协议对每一个网卡进行BINDING。或者当系统通PNP找到一块新的网卡时 也会调用BindAdapterHandler对协议进行BINDING。协议在BINDING 调用里,会根据自己的需要使用NdisOpenAdapter 将自身绑定到适合的网卡。并返回NdisBindingHandle.NdisBindingHandle是什么?NdisBindingHandl其实是 指向NDIS_OPEN_BLOCK表的一根指针,那么NDIS_OPEN_BLOCK表有什么用呢?当协议顺利的绑定后,每个绑定的网卡 和每一个协议之间建立了数据传输的通道,而NDIS_OPEN_BLOCK就是用来维护这一数据通道的表。 struct _NDIS_OPEN_BLOCK { PNDIS_MAC_BLOCK MacHandle; // pointer to our MAC NDIS_HANDLE MacBindingHandle; // context when calling MacXX funcs PNDIS_ADAPTER_BLOCK AdapterHandle; // pointer to our adapter PNDIS_PROTOCOL_BLOCK ProtocolHandle; // pointer to our protocol NDIS_HANDLE ProtocolBindingContext;// context when calling ProtXX funcs PNDIS_OPEN_BLOCK AdapterNextOpen; // used by adapter\'s OpenQueue PNDIS_OPEN_BLOCK ProtocolNextOpen; // used by protocol\'s OpenQueue PFILE_OBJECT FileObject; // created by operating system BOOLEAN Closing; // TRUE when removing this struct BOOLEAN Unloading; // TRUE when processing unload BOOLEAN NoProtRsvdOnRcvPkt; // Reflect the protocol_options NDIS_HANDLE CloseRequestHandle; // 0 indicates an internal close KSPIN_LOCK SpinLock; // guards Closing PNDIS_OPEN_BLOCK NextGlobalOpen; // // These are optimizations for getting to MAC routines. They are not // necessary, but are here to save a dereference through the MAC block. // SEND_HANDLER SendHandler; TRANSFER_DATA_HANDLER TransferDataHandler; // // These are optimizations for getting to PROTOCOL routines. They are not // necessary, but are here to save a dereference through the PROTOCOL block. // SEND_COMPLETE_HANDLER SendCompleteHandler; TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler; RECEIVE_HANDLER ReceiveHandler; RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler; // // Extentions to the OPEN_BLOCK since Product 1. // RECEIVE_HANDLER PostNt31ReceiveHandler; RECEIVE_COMPLETE_HANDLER PostNt31ReceiveCompleteHandler; // // NDIS 4.0 extensions // RECEIVE_PACKET_HANDLER ReceivePacketHandler; SEND_PACKETS_HANDLER SendPacketsHandler; // // More NDIS 3.0 Cached Handlers // RESET_HANDLER ResetHandler; REQUEST_HANDLER RequestHandler; // // Needed for PnP // UNICODE_STRING AdapterName; // Upcased name of the adapter we are bound to }; 上面的表结构可以很清楚的看到这张表是一个单向链接表,并且存放了和PNDIS_OPEN_BLOCK->ProtocolCharacteristics 一样的数据收发派发函数,当第N块网卡发送数据包到第N个协议时,就会调用第N个协议与第N个网卡之间建立的 NDIS_OPEN_BLOCK表里的SendHandler或SendPacketHandler。所以我们还需要对这张表里的派发函数进行处理(勾挂)。 那么又如何勾挂协议与网卡之间的NDIS_OPEN_BLOCK表呢。我们再回到NDIS_PROTOCOL_BLOCK这张表中,在 NDIS_PROTOCOL_BLOCK表中字段PNDIS_OPEN_BLOCK OpenQueue;就是所有该协议所有NDIS_OPEN_BLOCK的表头。 通过AdapterNextOpen遍历一下,再勾挂一把。就可以顺利拦截了。 值得注意的是。 1。 NDIS_OPEN_BLOCK NDIS_PROTOCOL_BLOCK 这些结构不同NDIS版本是不同的, 解决方法是在windows 98和windows95下(ndis 3.1)使用windows98ddk 带的NDIS.H 里的定义 在windows me下(ndis 5.0或4。0)请使用WINDOWS 98ddk里NDIS.H里的定义 nt(ndis4.0)用NTDDK里的定议,以此类推,2000(ndis5.0) 2。不要重复勾挂同一个函数。 |
|
[讨论]请大家在此贴发表--破解网络验证的有用工具软件
相关的另一点提示 BYTE btNewBytes[8] = { 0x0B8, 0x0, 0x0, 0x40, 0x0, 0x0FF, 0x0E0, 0 }; DWORD dwOldBytes[3][2]; DWORD pSend = 0,pRecv = 0,dwSize = 0; HMODULE hLib =NULL; hLib = LoadLibrary( "ws2_32.dll" ); pSend = (DWORD)GetProcAddress( hLib, "send" ); pRecv = (DWORD)GetProcAddress( hLib, "recv" ); ::ReadProcessMemory(INVALID_HANDLE_value, (void *)pSend, (void *)dwOldBytes[0], sizeof(DWORD)*2, &dwSize ); *(DWORD *)( btNewBytes + 1 ) = (DWORD)new_send; ::WriteProcessMemory(INVALID_HANDLE_value, (void *)pSend, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize ); |
|
[讨论]请大家在此贴发表--破解网络验证的有用工具软件
VC网络类编程:运用层截包办法与完成 [作者:匿名] [出处: ] [时间:2007-3-27 0:51:22 ] 为什么要在应用层截包 引言 截包的需求一般来自于过滤、转换协议、截取报文分析等。 过滤型的应用比较多,典型为包过滤型防火墙。 转换协议的应用局限于一些特定环境。比如第三方开发网络协议软件,不能够与原有操作系统软件融合,只好采取“嵌入协议栈的块”(B99vS)方式实施。比如IPSEC在Windows上的第三方实现,无法和操作系统厂商提供的IP软件融合,只好实现在IP层与链路层之间,作为协议栈的一层来实现。第三方PPPOE软件也是通过这种方式实现。 截取包用于分析的目的,用“抓包”描述更恰当一些,“截包”一般表示有截断的能力,“抓包”只需要能够获取即可。实现上一般作为协议层实现。 本文所说的“应用层截包”特指在驱动程序中截包,然后送到应用层处理的工作模式。 截包模式 用户态下的网络数据包拦截方式有 1. Winsock Layered Service Provider; 2. Windows 2000 包过滤接口; 3. 替换系统自带的WINSOCK动态连接库; 利用驱动程序拦截网络数据包的方式有 1. TDI过滤驱动程序(TDI Filter Driver) 2. NDIS中间层驱动程序(NDIS Intermediate Driver) 3. Win2k Filter-Hook Driver 4. NDIS Hook Driver 用户态下拦截数据包有一些局限性,“很显然,在用户态下进行数据包拦截最致命的缺点就是只能在Winsock层次上进行,而对于网络协议栈中底层协议的数据包无法进行处理。对于一些木马和病毒来说很容易避开这个层次的防火墙。” 我们所说的“应用层截包”不是指上面描述的在用户态拦截数据包。而是在驱动程序中拦截,在应用层中处理。要获得一个通用的方式,应该在IP层之下进行拦截。综合比较,本文选用中间层模式。 为什么要在应用层处理截取的报文 一般来说,网络应用如防火墙,协议类软件都是工作在内核,我们为什么要反过来,提出要在应用层处理报文呢?理由也可以找出几点(哪怕是比较牵强): 众所周知,驱动程序开发有一定的难度,对于一个经验丰富的程序员来说,或许开发过程中不存在技术问题,但是对初学者,尤其是第一次接触的程序员简直是痛苦的经历。 另外,开发周期也是一个不得不考虑的问题。程序工作在内核,稳定性/兼容性都需要大量测试,而且可供使用的函数库相对于应用层来说相当少。在应用层开发,调试修改相对要容易地多。 不利的因素也有: 性能影响,在应用层工作,改变了工作模式,每当驱动程序截到数据,送到应用层处理后再次送回内核,再向上传递到IP协议。因此,性能影响非常大,效率非常低,在100Mbps网络上,只有80%的性能表现。 综合来看,在特定的场合应用还是比较适合的: 台式机上使用,台式机的网络负载相当小,不到100Mbps足以满足要求,尤其是主要用于上网等环境,网络连接的流量不到512Kbps,根本不用考虑性能因素。作为单机防火墙或其他一些协议实现,分析等很容易基于这种方式实现。 方案 模型 上图描述了应用层截包的模型,主要的流程如下: 接收报文过程: 1. 网络接口收到报文,中间层截取,通过2送到应用层处理; 2. 应用层处理后,送回中间层处理结果; 3. 中间层根据处理结果,丢弃该报文,或者将处理后的报文通过1送到IP协议; 4. IP协议及上层应用接收到报文; 发送报文过程: 1. 上层应用发送数据,从而IP协议发送报文; 2. 报文被中间层截取,通过2送到应用层处理; 3. 应用层处理后,送回中间层处理结果; 4. 中间层根据处理结果,丢弃该报文,或者将处理后的报文发送到网络上; 实现细节探讨 IO与通讯 有一个很容易的方式,在驱动程序和应用程序之间用一个事件。 在应用程序CreateFile的时候,驱动程序IoCreateSynchronizationEvent一个有名的事件,然后应用程序CreateEvent/OpenEvent此有名事件即可。 注意点: 1, 不要在驱动初始化的时候创建事件,此时大多不能成功创建; 2, 让驱动先创建,那么此后应用程序打开时,只能读(Waitxxxx),不能写(SetEvent/ResetEvent)。反之,如果应用程序先创建,则应用程序和驱动程序都有读写权限; 3, 用名字比较理想,注意驱动中名字在\BaseNamedObjects\下,例如应用程序用“xxxEvent”,那么驱动中就是“\BaseNamedObjects\xxxEvent”; 4, 用HANDLE的方式也可以,但是在WIN98下是否可行,未知。 5, 此后,驱动对读请求应立即返回,否则就返回失败。不然将失去用事件通知的意义(不再等待读完成,而是有需要(通知事件)时才会读); 6, 应用程序发现有事件,应该在一个循环中读取,直到读取失败,表明没有数据可读;否则会漏掉后续数据,而没有及时读取; 处理线程优先级 应用层处理线程应该提高优先级,因为该线程为其他上层应用程序服务,如果优先级比其他线程优先级低的话,将会发生类似死锁的等待状态。 另外,提高优先级的时候必须注意,线程尽量缩短运行时间,不要长期占用CPU,否则其他线程无法得到服务。优先级不必提高到REALTIME_PRIOR99vY_CLASS级,此时线程不能做一些磁盘IO之类的操作,而且也影响到鼠标、键盘等工作。 驱动程序也可以动态地提高线程的优先级。 缓存 在驱动程序接收到报文后,至少应该有一个缓冲以便临时存储,等待应用层处理。缓冲不必很大,只要能在应用层得到时间片之前缓冲区不溢出就可以了,实践中大约能存储几十个报文就够了。 缓冲的使用方式,是一个先进先出的队列。考虑方便实现为静态存储的环形队列,也就是说,不必每次分配内存,而是一次性分配好一大块内存,环形的使用。 初始,head==tail==0; tail和head都是无限增长的。 Tail – head <= size; 放入一个报文时, tail=tail + packetlen; 取出一个报文时,head=head + packetlen; tail== head表明空; tail>head表明有数据; tail + input packet length - head >size表明满; 取数据时: ppacket GetPacket() { ASSERT(tail>=head); &nbs p;if(tail==head) return NULL; //else ppacket = &start[head % SIZE]; if(head % size + ppacket->length > size ) //数据不连续(一部分在尾部,一部分在头部); else //数据是连续的 return ppacket; } 放入数据: bool InputPacket(ppacket) { if(tail + input packet length - head >size) //满 return false; //copy packet to &start[tail % SIZE] //if(tail % SIZE + packet length > SIZE) //数据不连续(一部分在尾部,一部分在头部); //else //数据是连续的 tail = tail + packet length; return true; } 上面这种方式采用数组的方式组织,为每个报文提供一个最大报文长度的空间。因为缓冲区数目有限,因此这种方式可以满足需要。如果要考虑到减少空间的浪费,那么可以按每个报文的实际长度存储,上面的算法不能够适应这种方式。 应用层和驱动程序的通信 在网卡接收/IP发送过程中,驱动程序缓存报文,用事件通知应用层有报文需要处理。那么应用层可以通过IO方式或者共享内存方式取得此报文。 实践说明,在100Mbps速率下,以上两种方式都可以满足需要,最为简便的方式就是使用有缓冲的IO方式。 应用层处理完毕,也可以使用以上两种方式之一来向驱动程序递交结果。不过,IO方式因为一次只能发送一个报文,100Mbps网络速度下降为70%~80%网络速度,10Mbps不会有影响。也就是说,主机发出的最大速度只有70%的网络速度,这和应用程序发送不超过MTU的UDP数据报的速度是一样的。对TCP来说,由于是双向通信,损失更加大一些,大约40%~60%速度。 这时候,使用共享内存方式,因为减少了系统调用的开销,可以避免速度下降。 报文发送的速度控制 当IP协议发送报文的时候,一般来说,我们的中间层驱动必须把这些报文缓存起来,告诉IP软件发送成功,然后让应用层处理完毕之后再做决定。显然,存储报文的速度远远超过网卡能够发送的速度,然而IP软件(特别是UDP)将以我们存储的速度发送报文。造成缓存迅速耗尽。后续的报文只好丢弃。这样一来,UDP发送将不能正常工作。TCP由于可以自行适应网络状况,依然可以在这种情况下工作,速度在70%左右。在Passthru里,可以转发至低层驱动,然后用异步或同步方式返回,从而达到网卡的发送速度一致。 因此,必须有一个办法避免这种状况。中间层驱动把这些报文缓存起来,告诉IP软件发送状态未决(Pending)。等到最后处理完毕,告诉IP软件发送完成。从而协调了发送速度。这种方式带来一个问题,就是驱动程序必须在发送超时的情况下放弃对这些缓冲报文的所有权。具体来说,就是MiniportReset被调用的时候,就有可能是NDIS察觉到发送超时,从而放弃所有未完成的发送操作,如果没有正确处理这种情况,将会导致严重问题。如果中间层在Miniport初始化的时候通过调用NdisMSetAttributesEx函数设置了NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT标志,那么中间层驱动程序将不会得到报文超时通知,中间层必须自行处理缓存的报文。 与Passthru协同工作 当上层应用不再需要截包时,驱动程序应该完全是Passthru行为。这就要求所有发送/接收函数应该正确处理在截包与非截包状态,不至于做出危害行为。 具体来说,在从NIC上接收/发送,向IP协议提交数据包/接受IP协议发送四个方向上正确处理所有接收/发送函数。 其它辅助设施 添加一些控制功能提供更细粒度的控制,让应用程序获得更多的自由。比如,可以控制截取哪一个网卡,可以控制截取某个方向上的流量,网络是否有变化(网卡卸载/Disable)等等。 实现 实现选择Passthru源代码,在其上进行修改,主要修改包括: 1. 修改接收函数 2. 修改发送函数 3. 增加报文缓存 4. 增加IO部分 5. 增加控制功能 6. 增加应用层处理后的后续处理 这个实现使用了共享内存方式,具有一个处理前缓冲池和一个应用程序处理后的缓冲池。由于接收报文和待发送报文使用同一个缓冲池,也因为其他一些原因,这个实现的发送效率并没有比用IO方式快多少。 通过精心的设计和比较,完全可以做到100Mbps的收发速度。 这份文章旨在讨论这种应用层截报的工作方式和可行性。也由于驱动程序源代码并没有经过特别严格的测试,不适合商业使用,作为示范,也仅仅对以太网类型的报文进行了拦截。因此示范的驱动程序将不包含源代码。 API说明 第三方开发使用cap.h头文件,capdll.dll包含了下列函数: BOOL CapInitialize(); VOID CapUninitialize(); BOOL CapStartCapture(PKTPROC PacketProc, ADAPTERS_CHANGE_CALLBACK AdaptChange); VOID CapStopCapture(); DWORD CapGetAdaptList(PADAPT_INFO pAdaptInfo, DWORD BufferSize); VOID CapSetRule(HANDLE Adapter, ULONG Rule); BOOL CapSendPacket(HANDLE Adapter, ULONG Opcode, ULONG Length, PUCHAR Data); 同时提供了该dll的capdll.lib文件以便在vc工程文件中引入capdll.lib使用更为方便的编译连接方式。 说明 所有函数的返回值都没有指明错误原因。DEBUG版本可以在控制台打印出运行信息,并且在C:\ capture.txt有同样的输出信息。 BOOL CapInitialize(); 说明: 通知截报中间层驱动做一些必要的初始化工作。 参数: 无。 返回值: 失败返回FALSE。 VOID CapUninitialize(); 说明: 释放驱动程序创建的事件,线程,内存等。 参数: 无。 返回值: 无。 注意: 在调用此函数之前,应当调用CapSetRule将驱动程序截报规则设置成Opcode_PASSTHRU,以便恢复PASSTHRU行为。 BOOL CapStartCapture(PKTPROC PacketProc, ADAPTERS_CHANGE_CALLBACK AdaptChange); 说明: 启动截报。Capdll将会创建一个线程,运行在THRE AD_PRIOR99vY_HIGHEST优先级,并等待网络事件,当有驱动程序接收到报文,或者IP协议发送报文,或者发现网卡启动/禁用/插入/拔除等,将会通过用户提供的回调函数通知用户。 参数: PacketProc:用户提供的报文处理函数; AdaptChange:用户提供的网络变化通知函数; 返回值: VOID CapStopCapture(); 说明: 停止截报。销毁创建的线程。 参数: 无。 返回值: 无。 DWORD CapGetAdaptList(PADAPT_INFO pAdaptInfo, DWORD BufferSize); 说明: 获取网络适配卡列表。 参数: pAdaptInfo ADAPT_INFO结构数组,用户提供足够的空间。 BufferSize 缓冲区尺寸。 返回值: 网络适配卡数目。 VOID CapSetRule(HANDLE Adapter, ULONG Rule); 说明: 设置截报规则。 参数: Adapter:指定截取的网卡句柄。 Rule:为Opcode_PASSTHRU:PASSTHRU行为;Opcode_SND:截取所有发送报文;Opcode_RCV:截取所有接收报文。可以使用Opcode_SND | Opcode_RCV。 返回值: 无。 BOOL CapSendPacket(HANDLE Adapter, ULONG Opcode, ULONG Length, PUCHAR Data); 说明: 将处理后的报文放入缓冲区。也可以自行构造报文。不仅可以发送报文,也可以将报文送给本机IP软件。 参数: Adapter:指定使用的网卡句柄。 Opcode:Opcode_SND,将报文发送到网络上;Opcode_RCV,将报文传递给本机软件。 Length:报文长度; Data:报文内容; 返回值: 成功返回TRUE,失败返回FALSE。 Sample #include "cap.h" #include <stdio.h> // global data. ADAPT_INFO AdaptInfo[16]; int AdapterNum; VOID PacketProc(HANDLE Adapter, ULONG Opcode, ULONG Length, PUCHAR Data) { CapSendPacket(Adapter, Opcode, Length, Data); } VOID AdaptersChangeCallback() { AdapterNum = CapGetAdaptList(AdaptInfo, sizeof(AdaptInfo)); } int main(int argc, char* argv[]) { BOOL bRet; char cmd[80]; int i; bRet = CapInitialize(); if(bRet) { AdapterNum = CapGetAdaptList(AdaptInfo, sizeof(AdaptInfo)); for(i=0; i<AdapterNum; i++) { CapSetRule(AdaptInfo[i].Adapter, Opcode_SND | Opcode_RCV); } CapStartCapture(PacketProc, AdaptersChangeCallback); for(;;) { gets(cmd); if(strcmp(cmd, "quit")==0) { break; } } for(i=0; i<AdapterNum; i++) { CapSetRule(AdaptInfo[i].Adapter, Opcode_PASSTHRU); } CapStopCapture(); CapUninitialize(); } return 0; } 应用举例 上述代码做了一个Passthru行为。 作网桥或者NAT,需要在报文处理函数里,将报文内容根据需要修改以太网头部或其他行为,然后从合适的另一块网卡上发出去; 作协议转换,比如IP/UDP隧道或者复杂如IPSEC之类,可以在报文处理函数里将报文内容解开隧道或者解密,重新组报文,放入缓冲区,让驱动程序送到IP软件; 作防火墙,根据规则,丢弃不受欢迎的报文,正常的报文同样PASSTHRU; 作入侵监测/安全审计(当然只能保护本机),PASSTHRU同时纪录网络事件; |
|
[原创]欢迎破解我的程序!
任何软件都能破 |
|
|
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值