| 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 |