对于这个任务,从Windows Vista开始特殊存在
FileProcessIdsUsingFileInformation
FILE_INFORMATION_CLASS
。
因此,我们需要使用
FILE_READ_ATTRIBUTES
打开文件(即使有人以0共享模式打开文件也是可能的。如果我们没有访问文件(通过它的
DACL)但具有父目录的读取访问权限)。并调用
NtQueryInformationFile
与
FileProcessIdsUsingFileInformation
。返回时,我们得到一个
FILE_PROCESS_IDS_USING_FILE_INFORMATION
结构(在
wdm.h
中定义),其中包含持有此文件(打开文件句柄或映射的部分。例如,如果此文件是exe/dll,则我们获得加载它的进程id)的
ProcessId
列表。还可以为每个id打印进程名称:
volatile UCHAR guz = 0;
NTSTATUS PrintProcessesUsingFile(HANDLE hFile)
{
NTSTATUS status;
IO_STATUS_BLOCK iosb;
ULONG cb = 0, rcb = FIELD_OFFSET(FILE_PROCESS_IDS_USING_FILE_INFORMATION, ProcessIdList[64]);
union {
PVOID buf;
PFILE_PROCESS_IDS_USING_FILE_INFORMATION ppiufi;
};
PVOID stack = alloca(guz);
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, ppiufi, cb, FileProcessIdsUsingFileInformation)))
{
if (ppiufi->NumberOfProcessIdsInList)
{
PrintProcessesUsingFile(ppiufi);
}
}
rcb = (ULONG)iosb.Information;
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
NTSTATUS PrintProcessesUsingFile(POBJECT_ATTRIBUTES poa)
{
IO_STATUS_BLOCK iosb;
HANDLE hFile;
NTSTATUS status;
if (0 <= (status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
{
status = PrintProcessesUsingFile(hFile);
NtClose(hFile);
}
return status;
}
NTSTATUS PrintProcessesUsingFile(PCWSTR FileName)
{
UNICODE_STRING ObjectName;
NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(FileName, &ObjectName, 0, 0);
if (0 <= status)
{
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
status = PrintProcessesUsingFile(&oa);
RtlFreeUnicodeString(&ObjectName);
}
return status;
}
NTSTATUS PrintProcessesUsingFile(PFILE_PROCESS_IDS_USING_FILE_INFORMATION ppiufi)
{
NTSTATUS status;
ULONG cb = 0x8000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PVOID buf = new BYTE[cb])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
ULONG NumberOfProcessIdsInList = ppiufi->NumberOfProcessIdsInList;
PULONG_PTR ProcessIdList = ppiufi->ProcessIdList;
do
{
if (*ProcessIdList++ == (ULONG_PTR)pspi->UniqueProcessId)
{
DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);
break;
}
} while (--NumberOfProcessIdsInList);
} while (NextEntryOffset = pspi->NextEntryOffset);
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
hanlde.exe
。除非你想在代码中自己完成,那么你可以枚举所有进程,然后检查它们的句柄? - Mihayl