OLD | NEW |
| (Empty) |
1 /* | |
2 * $Id: process_handles.c 1142 2011-10-05 18:45:49Z g.rodola $ | |
3 * | |
4 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 * | |
8 */ | |
9 | |
10 #ifndef UNICODE | |
11 #define UNICODE | |
12 #endif | |
13 | |
14 #include <Python.h> | |
15 #include <windows.h> | |
16 #include <stdio.h> | |
17 #include "process_handles.h" | |
18 | |
19 #ifndef NT_SUCCESS | |
20 #define NT_SUCCESS(x) ((x) >= 0) | |
21 #endif | |
22 #define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 | |
23 | |
24 #define SystemHandleInformation 16 | |
25 #define ObjectBasicInformation 0 | |
26 #define ObjectNameInformation 1 | |
27 #define ObjectTypeInformation 2 | |
28 | |
29 | |
30 typedef LONG NTSTATUS; | |
31 | |
32 typedef struct _UNICODE_STRING { | |
33 USHORT Length; | |
34 USHORT MaximumLength; | |
35 PWSTR Buffer; | |
36 } UNICODE_STRING, *PUNICODE_STRING; | |
37 | |
38 typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)( | |
39 ULONG SystemInformationClass, | |
40 PVOID SystemInformation, | |
41 ULONG SystemInformationLength, | |
42 PULONG ReturnLength | |
43 ); | |
44 | |
45 typedef NTSTATUS (NTAPI *_NtDuplicateObject)( | |
46 HANDLE SourceProcessHandle, | |
47 HANDLE SourceHandle, | |
48 HANDLE TargetProcessHandle, | |
49 PHANDLE TargetHandle, | |
50 ACCESS_MASK DesiredAccess, | |
51 ULONG Attributes, | |
52 ULONG Options | |
53 ); | |
54 | |
55 typedef NTSTATUS (NTAPI *_NtQueryObject)( | |
56 HANDLE ObjectHandle, | |
57 ULONG ObjectInformationClass, | |
58 PVOID ObjectInformation, | |
59 ULONG ObjectInformationLength, | |
60 PULONG ReturnLength | |
61 ); | |
62 | |
63 typedef struct _SYSTEM_HANDLE | |
64 { | |
65 ULONG ProcessId; | |
66 BYTE ObjectTypeNumber; | |
67 BYTE Flags; | |
68 USHORT Handle; | |
69 PVOID Object; | |
70 ACCESS_MASK GrantedAccess; | |
71 } SYSTEM_HANDLE, *PSYSTEM_HANDLE; | |
72 | |
73 typedef struct _SYSTEM_HANDLE_INFORMATION | |
74 { | |
75 ULONG HandleCount; | |
76 SYSTEM_HANDLE Handles[1]; | |
77 } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; | |
78 | |
79 typedef enum _POOL_TYPE | |
80 { | |
81 NonPagedPool, | |
82 PagedPool, | |
83 NonPagedPoolMustSucceed, | |
84 DontUseThisType, | |
85 NonPagedPoolCacheAligned, | |
86 PagedPoolCacheAligned, | |
87 NonPagedPoolCacheAlignedMustS | |
88 } POOL_TYPE, *PPOOL_TYPE; | |
89 | |
90 typedef struct _OBJECT_TYPE_INFORMATION | |
91 { | |
92 UNICODE_STRING Name; | |
93 ULONG TotalNumberOfObjects; | |
94 ULONG TotalNumberOfHandles; | |
95 ULONG TotalPagedPoolUsage; | |
96 ULONG TotalNonPagedPoolUsage; | |
97 ULONG TotalNamePoolUsage; | |
98 ULONG TotalHandleTableUsage; | |
99 ULONG HighWaterNumberOfObjects; | |
100 ULONG HighWaterNumberOfHandles; | |
101 ULONG HighWaterPagedPoolUsage; | |
102 ULONG HighWaterNonPagedPoolUsage; | |
103 ULONG HighWaterNamePoolUsage; | |
104 ULONG HighWaterHandleTableUsage; | |
105 ULONG InvalidAttributes; | |
106 GENERIC_MAPPING GenericMapping; | |
107 ULONG ValidAccess; | |
108 BOOLEAN SecurityRequired; | |
109 BOOLEAN MaintainHandleCount; | |
110 USHORT MaintainTypeList; | |
111 POOL_TYPE PoolType; | |
112 ULONG PagedPoolUsage; | |
113 ULONG NonPagedPoolUsage; | |
114 } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; | |
115 | |
116 PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName) | |
117 { | |
118 return GetProcAddress(GetModuleHandleA(LibraryName), ProcName); | |
119 } | |
120 | |
121 | |
122 PyObject* | |
123 get_open_files(long pid, HANDLE processHandle) | |
124 { | |
125 _NtQuerySystemInformation NtQuerySystemInformation = | |
126 GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); | |
127 _NtDuplicateObject NtDuplicateObject = | |
128 GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); | |
129 _NtQueryObject NtQueryObject = | |
130 GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); | |
131 | |
132 NTSTATUS status; | |
133 PSYSTEM_HANDLE_INFORMATION handleInfo; | |
134 ULONG handleInfoSize = 0x10000; | |
135 | |
136 ULONG i; | |
137 ULONG fileNameLength; | |
138 PyObject *filesList = Py_BuildValue("[]"); | |
139 PyObject *arg = NULL; | |
140 PyObject *fileFromWchar = NULL; | |
141 | |
142 | |
143 | |
144 handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); | |
145 | |
146 /* NtQuerySystemInformation won't give us the correct buffer size, | |
147 so we guess by doubling the buffer size. */ | |
148 while ((status = NtQuerySystemInformation( | |
149 SystemHandleInformation, | |
150 handleInfo, | |
151 handleInfoSize, | |
152 NULL | |
153 )) == STATUS_INFO_LENGTH_MISMATCH) | |
154 handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoS
ize *= 2); | |
155 | |
156 /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. *
/ | |
157 if (!NT_SUCCESS(status)) { | |
158 //printf("NtQuerySystemInformation failed!\n"); | |
159 return NULL; | |
160 } | |
161 | |
162 for (i = 0; i < handleInfo->HandleCount; i++) | |
163 { | |
164 SYSTEM_HANDLE handle = handleInfo->Handles[i]; | |
165 HANDLE dupHandle = NULL; | |
166 POBJECT_TYPE_INFORMATION objectTypeInfo; | |
167 PVOID objectNameInfo; | |
168 UNICODE_STRING objectName; | |
169 ULONG returnLength; | |
170 | |
171 /* Check if this handle belongs to the PID the user specified. */ | |
172 if (handle.ProcessId != pid) | |
173 continue; | |
174 | |
175 /* Skip handles with the following access codes as the next call | |
176 to NtDuplicateObject() or NtQueryObject() might hang forever. */ | |
177 if((handle.GrantedAccess == 0x0012019f) | |
178 || (handle.GrantedAccess == 0x001a019f) | |
179 || (handle.GrantedAccess == 0x00120189) | |
180 || (handle.GrantedAccess == 0x00100000)) { | |
181 continue; | |
182 } | |
183 | |
184 /* Duplicate the handle so we can query it. */ | |
185 if (!NT_SUCCESS(NtDuplicateObject( | |
186 processHandle, | |
187 handle.Handle, | |
188 GetCurrentProcess(), | |
189 &dupHandle, | |
190 0, | |
191 0, | |
192 0 | |
193 ))) | |
194 { | |
195 //printf("[%#x] Error!\n", handle.Handle); | |
196 continue; | |
197 } | |
198 | |
199 /* Query the object type. */ | |
200 objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); | |
201 if (!NT_SUCCESS(NtQueryObject( | |
202 dupHandle, | |
203 ObjectTypeInformation, | |
204 objectTypeInfo, | |
205 0x1000, | |
206 NULL | |
207 ))) | |
208 { | |
209 //printf("[%#x] Error!\n", handle.Handle); | |
210 CloseHandle(dupHandle); | |
211 continue; | |
212 } | |
213 | |
214 objectNameInfo = malloc(0x1000); | |
215 if (!NT_SUCCESS(NtQueryObject( | |
216 dupHandle, | |
217 ObjectNameInformation, | |
218 objectNameInfo, | |
219 0x1000, | |
220 &returnLength | |
221 ))) | |
222 { | |
223 /* Reallocate the buffer and try again. */ | |
224 objectNameInfo = realloc(objectNameInfo, returnLength); | |
225 if (!NT_SUCCESS(NtQueryObject( | |
226 dupHandle, | |
227 ObjectNameInformation, | |
228 objectNameInfo, | |
229 returnLength, | |
230 NULL | |
231 ))) | |
232 { | |
233 /* We have the type name, so just display that.*/ | |
234 /* | |
235 printf( | |
236 "[%#x] %.*S: (could not get name)\n", | |
237 handle.Handle, | |
238 objectTypeInfo->Name.Length / 2, | |
239 objectTypeInfo->Name.Buffer | |
240 ); | |
241 */ | |
242 free(objectTypeInfo); | |
243 free(objectNameInfo); | |
244 CloseHandle(dupHandle); | |
245 continue; | |
246 | |
247 } | |
248 } | |
249 | |
250 /* Cast our buffer into an UNICODE_STRING. */ | |
251 objectName = *(PUNICODE_STRING)objectNameInfo; | |
252 | |
253 /* Print the information! */ | |
254 if (objectName.Length) | |
255 { | |
256 /* The object has a name. Make sure it is a file otherwise | |
257 ignore it */ | |
258 fileNameLength = objectName.Length / 2; | |
259 if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) { | |
260 //printf("%.*S\n", objectName.Length / 2, objectName.Buffer); | |
261 fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer, | |
262 fileNameLength); | |
263 #if PY_MAJOR_VERSION >= 3 | |
264 arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWcha
r)); | |
265 #else | |
266 arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar)
); | |
267 #endif | |
268 Py_XDECREF(fileFromWchar); | |
269 PyList_Append(filesList, arg); | |
270 Py_XDECREF(arg); | |
271 } | |
272 /* | |
273 printf( | |
274 "[%#x] %.*S: %.*S\n", | |
275 handle.Handle, | |
276 objectTypeInfo->Name.Length / 2, | |
277 objectTypeInfo->Name.Buffer, | |
278 objectName.Length / 2, | |
279 objectName.Buffer | |
280 ); | |
281 */ | |
282 } | |
283 else | |
284 { | |
285 /* Print something else. */ | |
286 /* | |
287 printf( | |
288 "[%#x] %.*S: (unnamed)\n", | |
289 handle.Handle, | |
290 objectTypeInfo->Name.Length / 2, | |
291 objectTypeInfo->Name.Buffer | |
292 ); | |
293 */ | |
294 ;; | |
295 } | |
296 free(objectTypeInfo); | |
297 free(objectNameInfo); | |
298 CloseHandle(dupHandle); | |
299 } | |
300 free(handleInfo); | |
301 CloseHandle(processHandle); | |
302 return filesList; | |
303 } | |
304 | |
OLD | NEW |