在应用层,枚举进程及其通信端口一般可以用iphlpapi.dll中提供的函数来获取。如获取Tcp连接,则调用GetTcpTable或者AllocateAndGetTcpTableFromStack来查询。这些API都是通过调用NtDeviceIoControlFile这个NativeAPI来进入内核查询信息的,如果在内核用SSDT Hook来挂钩此函数,从而隐藏特定的IP、端口信息的话,那么在应用层,常规的查询方法就查不到隐藏的端口了。
本文通过直接向设备对象\Device\Tcp发送IOCTL Code=IOCTL_TCP_QUERY_INFORMATION_EX的命令,直接获取进程,端口信息。本文也同时实现了UDP端口的查询。
具体请参考下面的代码,使用WinDDK 6001.18001编译。
1#include <ntddk.h>
2#include <tdiinfo.h>
3#include <tdistat.h>
4
5#define DD_TCP_DEVICE_NAME L"\\Device\\Tcp"
6#define DD_UDP_DEVICE_NAME L"\\Device\\Udp"
7
8#define TCP_MIB_ADDRTABLE_ENTRY_EX_ID 0x102
9
10/**//* TCP/UDP/RawIP IOCTL code definitions */
11
12#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
13
14#define _TCP_CTL_CODE(function, method, access) \
15 CTL_CODE(FSCTL_TCP_BASE, function, method, access)
16
17#define IOCTL_TCP_QUERY_INFORMATION_EX \
18 _TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
19
20#define ntohs(s) \
21 (((s >> 8) & 0x00FF) | \
22 ((s << 8) & 0xFF00))
23
24enum {TCPPORT, UDPPORT};
25
26typedef ULONG DWORD;
27
28typedef struct _MIB_TCPROW_OWNER_PID
29{
30 DWORD dwState;
31 DWORD dwLocalAddr;
32 DWORD dwLocalPort;
33 DWORD dwRemoteAddr;
34 DWORD dwRemotePort;
35 DWORD dwOwningPid;
36} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;
37
38/**//////////////////////////////////////////////////////////////////////////////////// 39//
40// 功能实现:根据设备名获取文件句柄或文件对象指针
41// 输入参数:FileHandle是要输出的文件句柄指针;
42// FileObject是要输出的文件对象指针
43// DeviceName是要获取设备的设备名
44// 输出参数:返回NTSTATUS类型的值
45//
46/**//////////////////////////////////////////////////////////////////////////////////// 47NTSTATUS
48GetObjectByName(OUT HANDLE *FileHandle, OUT PFILE_OBJECT *FileObject, IN WCHAR *DeviceName)
49{
50 UNICODE_STRING deviceTCPUnicodeString;
51 OBJECT_ATTRIBUTES TCP_object_attr;
52 NTSTATUS status;
53 IO_STATUS_BLOCK IoStatus;
54
55 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
56 RtlInitUnicodeString(&deviceTCPUnicodeString, DeviceName);
57 InitializeObjectAttributes(&TCP_object_attr,
58 &deviceTCPUnicodeString,
59 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
60 0,
61 0);
62 status = ZwCreateFile(FileHandle,
63 GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
64 &TCP_object_attr,
65 &IoStatus,
66 0,
67 FILE_ATTRIBUTE_NORMAL,
68 FILE_SHARE_READ,
69 FILE_OPEN,
70 0,
71 0,
72 0);
73 if(!NT_SUCCESS(status))
74 {
75 KdPrint(("Failed to open"));
76 return STATUS_UNSUCCESSFUL;
77 }
78 status = ObReferenceObjectByHandle(*FileHandle,
79 FILE_ANY_ACCESS,
80 0,
81 KernelMode,
82 (PVOID*)FileObject,
83 NULL);
84
85 return status;
86}
87
88/**//////////////////////////////////////////////////////////////////////////////////// 89//
90// 功能实现:枚举网络连接端口信息
91// 输入参数:OutLength为输出缓冲区的大小
92// PortType为要枚举的端口类型
93// TCPPORT-TCP端口
94// UDPPORT-UDP端口
95// 输出参数:输出端口信息,在函数内部分配空间,需要在外部释放
96//
97/**//////////////////////////////////////////////////////////////////////////////////// 98PVOID
99EnumPortInformation(OUT PULONG OutLength, IN USHORT PortType)
100{
101 ULONG BufLen = PAGE_SIZE;
102 PVOID pInputBuff=NULL;
103 PVOID pOutputBuff=NULL;
104 PVOID pOutBuf=NULL;
105 NTSTATUS status = STATUS_SUCCESS;
106 HANDLE FileHandle=NULL;
107 UNICODE_STRING DeviceName;
108 PFILE_OBJECT pFileObject=NULL;
109 PDEVICE_OBJECT pDeviceObject=NULL;
110 KEVENT Event ;
111 IO_STATUS_BLOCK StatusBlock;
112 PIRP pIrp;
113 PIO_STACK_LOCATION StackLocation ;
114 ULONG NumOutputBuffers;
115 ULONG i;
116 TCP_REQUEST_QUERY_INFORMATION_EX TdiId;
117
118 RtlZeroMemory(&TdiId, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
119
120 if(TCPPORT == PortType)
121 {
122 TdiId.ID.toi_entity.tei_entity = CO_TL_ENTITY;
123 }
124 else if(UDPPORT == PortType)
125 {
126 TdiId.ID.toi_entity.tei_entity = CL_TL_ENTITY;
127 }
128 else
129 {
130 KdPrint(("需要获取的端口类型无效\n"));
131 return NULL;
132 }
133
134 TdiId.ID.toi_entity.tei_instance = ENTITY_LIST_ID;
135 TdiId.ID.toi_class = INFO_CLASS_PROTOCOL;
136 TdiId.ID.toi_type = INFO_TYPE_PROVIDER;
137 TdiId.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID;
138
139 pInputBuff = (PVOID)&TdiId;
140
141 __try
142 {
143 if(UDPPORT == PortType)
144 {
145 BufLen *= 3;
146 }
147 pOutputBuff = ExAllocatePool(NonPagedPool, BufLen);
148 if(NULL == pOutputBuff)
149 {
150 KdPrint(("输出缓冲区内存分配失败!\n"));
151 *OutLength = 0;
152 __leave;
153 }
154
155 if(TCPPORT == PortType)
156 {
157 status = GetObjectByName(&FileHandle, &pFileObject, DD_TCP_DEVICE_NAME);
158 }
159 else if(UDPPORT == PortType)
160 {
161 status = GetObjectByName(&FileHandle, &pFileObject, DD_UDP_DEVICE_NAME);
162 }
163 if (!NT_SUCCESS(status))
164 {
165 KdPrint(("获取设备名失败!\n"));
166 *OutLength = 0;
167 __leave;
168 }
169
170 pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
171 if (NULL == pDeviceObject)
172 {
173 KdPrint(("获取设备对象失败!\n"));
174 *OutLength = 0;
175 __leave;
176 }
177
178 KdPrint(("Tcpip Driver Object:%08lX\n", pDeviceObject->DriverObject));
179
180 KeInitializeEvent(&Event, NotificationEvent, FALSE);
181
182 pIrp = IoBuildDeviceIoControlRequest(IOCTL_TCP_QUERY_INFORMATION_EX, \
183 pDeviceObject, pInputBuff, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), \
184 pOutputBuff, BufLen, FALSE, &Event, &StatusBlock);
185 if (NULL == pIrp)
186 {
187 KdPrint(("IRP生成失败!\n"));
188 *OutLength = 0;
189 __leave;
190 }
191
192 StackLocation = IoGetNextIrpStackLocation(pIrp);
193 StackLocation->FileObject = pFileObject;//不设置这里会蓝屏
194 StackLocation->DeviceObject = pDeviceObject;
195
196 status = IoCallDriver(pDeviceObject, pIrp);
197
198 KdPrint(("STATUS:%08lX\n", status));
199
200 if (STATUS_BUFFER_OVERFLOW == status)
201 {
202 KdPrint(("缓冲区太小!%d\n",StatusBlock.Information));
203 }
204
205 if (STATUS_PENDING == status)
206 {
207 KdPrint(("STATUS_PENDING"));
208 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
209 status = StatusBlock.Status;
210 }
211
212 if(STATUS_CANCELLED == status)
213 {
214 KdPrint(("STATUS_CANCELLED"));
215 }
216
217 if(status == STATUS_SUCCESS)
218 {
219 *OutLength = StatusBlock.Information;
220 pOutBuf = pOutputBuff;
221 }
222 }
223 __finally
224 {
225 ObDereferenceObject(pFileObject);
226 if(FileHandle)
227 {
228 ZwClose(FileHandle);
229 }
230 }
231 return pOutBuf;
232}
233
234NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)
235{
236 DbgPrint("DriverUnload\n");
237 return STATUS_SUCCESS;
238}
239
240NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
241{
242 PVOID pTcpBuf = NULL;
243 ULONG ulTcpBuf = 0;
244
245 DbgPrint("DriverEntry\n");
246
247 pDrvObj->DriverUnload = DriverUnload;
248
249 pTcpBuf = EnumPortInformation(&ulTcpBuf, TCPPORT);
250
251 if (pTcpBuf != NULL)
252 {
253 PMIB_TCPROW_OWNER_PID pTcpInfo = NULL;
254 // 打印tcp端口信息
255 pTcpInfo = (PMIB_TCPROW_OWNER_PID)pTcpBuf;
256
257 for(; pTcpInfo->dwOwningPid; pTcpInfo++)
258 {
259 KdPrint(("Pid:%d,Port:%d\n", pTcpInfo->dwOwningPid, ntohs(pTcpInfo->dwLocalPort)));
260 }
261 ExFreePool(pTcpBuf);
262 }
263
264 return STATUS_SUCCESS;
265}
266
posted on 2010-07-09 18:28
水 阅读(5885)
评论(3) 编辑 收藏 引用 所属分类:
windows驱动