在應用層,枚舉進程及其通信端口一般可以用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
24
enum
{TCPPORT, UDPPORT};
25
26
typedef ULONG DWORD;
27
28
typedef 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
/**////////////////////////////////////////////////////////////////////////////////////
47
NTSTATUS
48
GetObjectByName(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
/**////////////////////////////////////////////////////////////////////////////////////
98
PVOID
99
EnumPortInformation(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
234
NTSTATUS DriverUnload(PDRIVER_OBJECT pDrvObj)
235

{
236
DbgPrint("DriverUnload\n");
237
return STATUS_SUCCESS;
238
}
239
240
NTSTATUS 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

2

3

4

5

6

7

8

9

10


11

12

13

14

15

16

17

18

19

20

21

22

23

24



25

26

27

28

29



30

31

32

33

34

35

36

37

38


39

40

41

42

43

44

45

46


47

48

49



50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74



75

76

77

78

79

80

81

82

83

84

85

86

87

88


89

90

91

92

93

94

95

96

97


98

99

100



101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121



122

123

124

125



126

127

128

129



130

131

132

133

134

135

136

137

138

139

140

141

142



143

144



145

146

147

148

149



150

151

152

153

154

155

156



157

158

159

160



161

162

163

164



165

166

167

168

169

170

171

172



173

174

175

176

177

178

179

180

181

182

183

184

185

186



187

188

189

190

191

192

193

194

195

196

197

198

199

200

201



202

203

204

205

206



207

208

209

210

211

212

213



214

215

216

217

218



219

220

221

222

223

224



225

226

227



228

229

230

231

232

233

234

235



236

237

238

239

240

241



242

243

244

245

246

247

248

249

250

251

252



253

254

255

256

257

258



259

260

261

262

263

264

265

266
