пятница, 18 апреля 2014 г.

Перечисление процессов, открывших указанный фаил

Код демонстрирует технику поиска процессов, открывших указанный файл используя недокумментированное NativeAPI.  Немного пошаманив, можно переделать этот код для перебора абсолютно любых типов описателей(handles).

Небольшая проблемка была обнаружена при перечислении описателей одного из процессов TortoiseSVN, почему-то NtQueryObject с флагом ObjectNameInformation не возвращает управление, не знаю баг ли это кода или баг  TortoiseSVN, если кто подскажет буду признателен. 

ntdll.h
  1
  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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// --------------------------------------------------------------
// This is example, how to listing of processes which use the 
// specified file
// by JKornev <c> http://k0rnev.blogspot.com
// --------------------------------------------------------------

#ifndef __NTDLL_H
#define __NTDLL_H

#include <Windows.h>

#define NT_DEF(proc) static Prototype_##proc proc
#define NT_BIND(proc) proc = (Prototype_##proc)GetProcAddress(GetModuleHandleA("ntdll"), "" #proc "")

// ----------------- Main def

typedef LONG NTSTATUS;

typedef NTSTATUS *PNTSTATUS;

typedef LONG KPRIORITY;


#define STATUS_SUCCESS                          ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH                ((NTSTATUS)0xC0000004L)

#define OBJECT_TYPE_0                   (BYTE)(0)
#define OBJECT_TYPE_1                   1
#define OBJECT_TYPE_DIRECTORY           2
#define OBJECT_TYPE_SYMBOLICLINK        3
#define OBJECT_TYPE_TOKEN               4
#define OBJECT_TYPE_PROCESS             5
#define OBJECT_TYPE_THREAD              6
#define OBJECT_TYPE_EVENT               7
#define OBJECT_TYPE_8                   8
#define OBJECT_TYPE_MUTANT              9
#define OBJECT_TYPE_SEMAPHORE           10
#define OBJECT_TYPE_TIMER               11
#define OBJECT_TYPE_12                  12
#define OBJECT_TYPE_WINDOWSTATION       13
#define OBJECT_TYPE_DESKTOP             14
#define OBJECT_TYPE_SECTION             15
#define OBJECT_TYPE_KEY                 16
#define OBJECT_TYPE_PORT                17
#define OBJECT_TYPE_18                  18
#define OBJECT_TYPE_19                  19
#define OBJECT_TYPE_20                  20
#define OBJECT_TYPE_21                  21
#define OBJECT_TYPE_IOCOMPLETION        22
#define OBJECT_TYPE_FILE                (BYTE)(23)

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;

// ----------------- System information class

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation,
    SystemProcessorInformation,             // obsolete...delete
    SystemPerformanceInformation,
    SystemTimeOfDayInformation,
    SystemPathInformation,
    SystemProcessInformation,
    SystemCallCountInformation,
    SystemDeviceInformation,
    SystemProcessorPerformanceInformation,
    SystemFlagsInformation,
    SystemCallTimeInformation,
    SystemModuleInformation,
    SystemLocksInformation,
    SystemStackTraceInformation,
    SystemPagedPoolInformation,
    SystemNonPagedPoolInformation,
    SystemHandleInformation,
    SystemObjectInformation,
    SystemPageFileInformation,
    SystemVdmInstemulInformation,
    SystemVdmBopInformation,
    SystemFileCacheInformation,
    SystemPoolTagInformation,
    SystemInterruptInformation,
    SystemDpcBehaviorInformation,
    SystemFullMemoryInformation,
    SystemLoadGdiDriverInformation,
    SystemUnloadGdiDriverInformation,
    SystemTimeAdjustmentInformation,
    SystemSummaryMemoryInformation,
    SystemMirrorMemoryInformation,
    SystemPerformanceTraceInformation,
    SystemObsolete0,
    SystemExceptionInformation,
    SystemCrashDumpStateInformation,
    SystemKernelDebuggerInformation,
    SystemContextSwitchInformation,
    SystemRegistryQuotaInformation,
    SystemExtendServiceTableInformation,
    SystemPrioritySeperation,
    SystemVerifierAddDriverInformation,
    SystemVerifierRemoveDriverInformation,
    SystemProcessorIdleInformation,
    SystemLegacyDriverInformation,
    SystemCurrentTimeZoneInformation,
    SystemLookasideInformation,
    SystemTimeSlipNotification,
    SystemSessionCreate,
    SystemSessionDetach,
    SystemSessionInformation,
    SystemRangeStartInformation,
    SystemVerifierInformation,
    SystemVerifierThunkExtend,
    SystemSessionProcessInformation,
    SystemLoadGdiDriverInSystemSpace,
    SystemNumaProcessorMap,
    SystemPrefetcherInformation,
    SystemExtendedProcessInformation,
    SystemRecommendedSharedDataAlignment,
    SystemComPlusPackage,
    SystemNumaAvailableMemory,
    SystemProcessorPowerInformation,
    SystemEmulationBasicInformation,
    SystemEmulationProcessorInformation,
    SystemExtendedHandleInformation,
    SystemLostDelayedWriteInformation,
    SystemBigPoolInformation,
    SystemSessionPoolTagInformation,
    SystemSessionMappedViewInformation,
    SystemHotpatchInformation,
    SystemObjectSecurityMode,
    SystemWatchdogTimerHandler,
    SystemWatchdogTimerInformation,
    SystemLogicalProcessorInformation,
    SystemWow64SharedInformation,
    SystemRegisterFirmwareTableInformationHandler,
    SystemFirmwareTableInformation,
    SystemModuleInformationEx,
    SystemVerifierTriageInformation,
    SystemSuperfetchInformation,
    SystemMemoryListInformation,
    SystemFileCacheInformationEx,
    MaxSystemInfoClass  // MaxSystemInfoClass should always be the last enum
} SYSTEM_INFORMATION_CLASS;

#if defined(_WIN64)
typedef ULONG SYSINF_PAGE_COUNT;
#else
typedef SIZE_T SYSINF_PAGE_COUNT;
#endif

typedef struct _SYSTEM_BASIC_INFORMATION {
    ULONG Reserved;
    ULONG TimerResolution;
    ULONG PageSize;
    SYSINF_PAGE_COUNT NumberOfPhysicalPages;
    SYSINF_PAGE_COUNT LowestPhysicalPageNumber;
    SYSINF_PAGE_COUNT HighestPhysicalPageNumber;
    ULONG AllocationGranularity;
    ULONG_PTR MinimumUserModeAddress;
    ULONG_PTR MaximumUserModeAddress;
    ULONG_PTR ActiveProcessorsAffinityMask;
    CHAR NumberOfProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

// ----------------- Process information class

typedef enum _PROCESSINFOCLASS {
    ProcessBasicInformation,
    ProcessQuotaLimits,
    ProcessIoCounters,
    ProcessVmCounters,
    ProcessTimes,
    ProcessBasePriority,
    ProcessRaisePriority,
    ProcessDebugPort,
    ProcessExceptionPort,
    ProcessAccessToken,
    ProcessLdtInformation,
    ProcessLdtSize,
    ProcessDefaultHardErrorMode,
    ProcessIoPortHandlers,          // Note: this is kernel mode only
    ProcessPooledUsageAndLimits,
    ProcessWorkingSetWatch,
    ProcessUserModeIOPL,
    ProcessEnableAlignmentFaultFixup,
    ProcessPriorityClass,
    ProcessWx86Information,
    ProcessHandleCount,
    ProcessAffinityMask,
    ProcessPriorityBoost,
    ProcessDeviceMap,
    ProcessSessionInformation,
    ProcessForegroundInformation,
    ProcessWow64Information,
    ProcessImageFileName,
    ProcessLUIDDeviceMapsEnabled,
    ProcessBreakOnTermination,
    ProcessDebugObjectHandle,
    ProcessDebugFlags,
    ProcessHandleTracing,
    ProcessIoPriority,
    ProcessExecuteFlags,
    ProcessResourceManagement,
    ProcessCookie,
    ProcessImageInformation,
    MaxProcessInfoClass             // MaxProcessInfoClass should always be the last enum
} PROCESSINFOCLASS;

typedef struct _PROCESS_BASIC_INFORMATION32 {
    NTSTATUS ExitStatus;
    PVOID PebBaseAddress;
    ULONG_PTR AffinityMask;
    KPRIORITY BasePriority;
    ULONG_PTR UniqueProcessId;
    ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION32;
typedef PROCESS_BASIC_INFORMATION32 *PPROCESS_BASIC_INFORMATION32;

typedef struct _PROCESS_BASIC_INFORMATION64 {
    NTSTATUS ExitStatus;
    PVOID PebBaseAddress;
    ULONG_PTR AffinityMask;
    KPRIORITY BasePriority;
    ULONG_PTR UniqueProcessId;
    ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION64;
typedef PROCESS_BASIC_INFORMATION64 *PPROCESS_BASIC_INFORMATION64;

// ----------------- Object information class

typedef enum _OBJECT_INFORMATION_CLASS {
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectTypesInformation,
    ObjectHandleFlagInformation,
    ObjectSessionInformation,
    MaxObjectInfoClass
} OBJECT_INFORMATION_CLASS;

typedef struct _OBJECT_NAME_INFORMATION {
    UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;

typedef struct _OBJECT_TYPE_INFORMATION {
    UNICODE_STRING TypeName;
    ULONG TotalNumberOfObjects;
    ULONG TotalNumberOfHandles;
    ULONG TotalPagedPoolUsage;
    ULONG TotalNonPagedPoolUsage;
    ULONG TotalNamePoolUsage;
    ULONG TotalHandleTableUsage;
    ULONG HighWaterNumberOfObjects;
    ULONG HighWaterNumberOfHandles;
    ULONG HighWaterPagedPoolUsage;
    ULONG HighWaterNonPagedPoolUsage;
    ULONG HighWaterNamePoolUsage;
    ULONG HighWaterHandleTableUsage;
    ULONG InvalidAttributes;
    GENERIC_MAPPING GenericMapping;
    ULONG ValidAccessMask;
    BOOLEAN SecurityRequired;
    BOOLEAN MaintainHandleCount;
    ULONG PoolType;
    ULONG DefaultPagedPoolCharge;
    ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

// ----------------- Platform-like def

#ifdef _WIN64

typedef PROCESS_BASIC_INFORMATION64 PROCESS_BASIC_INFORMATION;
typedef PPROCESS_BASIC_INFORMATION64 PPROCESS_BASIC_INFORMATION;

#else

typedef PROCESS_BASIC_INFORMATION32 PROCESS_BASIC_INFORMATION;
typedef PPROCESS_BASIC_INFORMATION32 PPROCESS_BASIC_INFORMATION;

#endif

// ----------------- Native API Prototypes

typedef NTSTATUS (WINAPI *Prototype_NtQuerySystemInformation)(
    _In_       SYSTEM_INFORMATION_CLASS SystemInformationClass,
    _Inout_    PVOID SystemInformation,
    _In_       ULONG SystemInformationLength,
    _Out_opt_  PULONG ReturnLength
    );

typedef NTSTATUS (WINAPI *Prototype_NtQueryInformationProcess)(
    _In_       HANDLE ProcessHandle,
    _In_       PROCESSINFOCLASS ProcessInformationClass,
    _Out_      PVOID ProcessInformation,
    _In_       ULONG ProcessInformationLength,
    _Out_opt_  PULONG ReturnLength
    );

typedef NTSTATUS (WINAPI *Prototype_NtQueryObject)(
    _In_opt_   HANDLE Handle,
    _In_       OBJECT_INFORMATION_CLASS ObjectInformationClass,
    _Out_opt_  PVOID ObjectInformation,
    _In_       ULONG ObjectInformationLength,
    _Out_opt_  PULONG ReturnLength
    );

#endif
main.cpp
  1
  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
// --------------------------------------------------------------
// This is example, how to listing of processes which use the 
// specified file
// by JKornev <c> http://k0rnev.blogspot.com
// --------------------------------------------------------------
#include <stdio.h>
#include <Windows.h>
#include "ntdll.h"

NT_DEF(NtQuerySystemInformation);
NT_DEF(NtQueryInformationProcess);
NT_DEF(NtQueryObject);

typedef void (*enum_proc_callback)(DWORD pid, HANDLE hndl, void *param);

bool EnumFileOwners(LPWSTR file_path, enum_proc_callback callback, void *param)
{
    PSYSTEM_HANDLE_INFORMATION phinfo;
    PSYSTEM_HANDLE_TABLE_ENTRY_INFO pentry;
    POBJECT_TYPE_INFORMATION pobj_type;
    POBJECT_NAME_INFORMATION pobj_name;
    PVOID buf, buf_type[512];
    ULONG count, res, size = 512, pid;
    HANDLE hobj = NULL, hproc = NULL;

    buf = new BYTE[size];

    res = NtQuerySystemInformation(SystemHandleInformation, buf, size, &count);
    if (res != STATUS_SUCCESS) {
        if (res == STATUS_INFO_LENGTH_MISMATCH) {
            size = count;

            delete[] buf;
            try {
                buf = new BYTE[size];
            } catch (...) {
                return 1;
            }

            res = NtQuerySystemInformation(SystemHandleInformation, buf, size, &count);
            if (res != STATUS_SUCCESS) {
                return 2;
            }
        } else {
            return 3;
        }
    }

    pid = 0;
    phinfo = (PSYSTEM_HANDLE_INFORMATION)buf;
    for (int i = 0; i < phinfo->NumberOfHandles; i++) {
        pentry = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO)&phinfo->Handles[i];

        if (pid != pentry->UniqueProcessId) {
            pid = pentry->UniqueProcessId;

            if (hproc) {
                CloseHandle(hproc);
            }

            hproc = OpenProcess(PROCESS_DUP_HANDLE, false, pentry->UniqueProcessId);
            if (!hproc) {
                continue;
            }
        }

        if (!DuplicateHandle(hproc, (HANDLE)pentry->HandleValue, GetCurrentProcess(), &hobj, 0, false, DUPLICATE_SAME_ACCESS)) {
            continue;
        }

        res = NtQueryObject(hobj, ObjectTypeInformation, &buf_type, sizeof(buf_type), &count);
        if (res != STATUS_SUCCESS) {
            CloseHandle(hobj);
            continue;
        }

        pobj_type = (POBJECT_TYPE_INFORMATION)buf_type;
        if (wcscmp(pobj_type->TypeName.Buffer, L"File")) {
            CloseHandle(hobj);
            continue;
        }

        res = NtQueryObject(hobj, ObjectNameInformation, &buf_type, sizeof(buf_type), &count);
        if (res != STATUS_SUCCESS) {
            CloseHandle(hobj);
            continue;
        }

        pobj_name = (POBJECT_NAME_INFORMATION)buf_type;

        if (!wcsicmp(pobj_name->Name.Buffer, file_path)) {
            callback(pentry->UniqueProcessId, (HANDLE)pentry->HandleValue, param);
        }

        CloseHandle(hobj);
    }
    if (hproc) {
        CloseHandle(hproc);
    }

    return true;
}

void output_proc_callback(DWORD pid, HANDLE hndl, void *)
{
    printf("PID:%d, Handle:0x%X\n", pid, hndl);
}

BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
    LUID luid;
    BOOL bRet=FALSE;

    if (LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
    {
        TOKEN_PRIVILEGES tp;

        tp.PrivilegeCount=1;
        tp.Privileges[0].Luid=luid;
        tp.Privileges[0].Attributes=(bEnablePrivilege) ? SE_PRIVILEGE_ENABLED: 0;
        //
        //  Enable the privilege or disable all privileges.
        //
        if (AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
        {
            //
            //  Check to see if you have proper access.
            //  You may get "ERROR_NOT_ALL_ASSIGNED".
            //
            bRet=(GetLastError() == ERROR_SUCCESS);
        }
    }
    return bRet;
}


int main(int argc, char* argv[])
{
    
    PSYSTEM_HANDLE_INFORMATION phinfo;
    PSYSTEM_HANDLE_TABLE_ENTRY_INFO pentry;

    NT_BIND(NtQuerySystemInformation);
    NT_BIND(NtQueryInformationProcess);
    NT_BIND(NtQueryObject);

    HANDLE hProcess = GetCurrentProcess();
    HANDLE hToken;

    if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
        CloseHandle(hToken);
    }

    if (!EnumFileOwners(L"\\Device\\HarddiskVolume2\\test.txt", output_proc_callback, NULL)) {
        printf ("Enum error!\n");
    }

    printf("end");
    getchar();
    return 0;
}

Комментариев нет:

Отправить комментарий