In filter driver I can call IoGetCurrentProcess
to get an PEPROCESS
structure, and than call PsGetProcessImageFileName
to get file name.
在过滤器驱动程序中,我可以调用IoGetCurrentProcess来获取PEPROCESS结构,然后调用PsGetProcessImageFileName来获取文件名。
My questions is how I can get full name of the process image file?
我的问题是如何获得过程映像文件的全名?
2 个解决方案
#1
1
You can use ZwQueryInformationProcess
with the information class of 27. THe following code uses this routine to obtain the full image file name from process' handle.
您可以将ZwQueryInformationProcess与信息类27一起使用。以下代码使用此例程从进程'句柄获取完整的映像文件名。
NTSTATUS GetProcessNameByHandle(_In_ HANDLE ProcessHandle, _Out_ PUNICODE_STRING *Name)
{
ULONG retLength = 0;
ULONG pniSize = 512;
PUNICODE_STRING pni = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do {
pni = (PUNICODE_STRING)ExAllocatePoolWithTag(PagedPool, pniSize, POOL_TAG);
if (pni != NULL) {
status = ZwQueryInformationProcess(ProcessHandle, 27, pni, pniSize, &retLength);
if (!NT_SUCCESS(status)) {
ExFreePoolWithTag(pni, POOL_TAG);
pniSize *= 2;
}
} else status = STATUS_INSUFFICIENT_RESOURCES;
} while (status == STATUS_INFO_LENGTH_MISMATCH);
if (NT_SUCCESS(status))
*Name = pni;
return status;
}
You can obtain the process handle by the following ways:
您可以通过以下方式获取进程句柄:
-
ObOpenObjectByPointer
, you need process' EPROCESS address (PsLookupProcessByProcessId
may help).ObOpenObjectByPointer,您需要进程'EPROCESS地址(PsLookupProcessByProcessId可能有帮助)。
-
ZwOpenProcess
– youn need to know PID of the target process.ZwOpenProcess - 您需要知道目标进程的PID。
However, using this code in every invocation of your minifilter's pre/post callback can be quite time-consuming. I solve this problem by caching process names in a hash table that uses PID as a key. Notify routines (PsSetXXXNotifyRoutine(Ex)
) may prove very useful when building and managing such a table.
但是,在每次调用minifilter的前/后回调时使用此代码可能非常耗时。我通过在使用PID作为键的哈希表中缓存进程名来解决此问题。在构建和管理这样的表时,通知例程(PsSetXXXNotifyRoutine(Ex))可能非常有用。
#2
1
here I found full code like @Martin Drab code
在这里,我找到了像@Martin Drab代码的完整代码
EDIT: new fixed code
编辑:新的固定代码
NTSTATUS
GetProcessImageName(
PEPROCESS eProcess,
PUNICODE_STRING* ProcessImageName
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG returnedLength;
HANDLE hProcess = NULL;
PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
if (eProcess == NULL)
{
return STATUS_INVALID_PARAMETER_1;
}
status = ObOpenObjectByPointer(eProcess,
0, NULL, 0, 0, KernelMode, &hProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status);
return status;
}
if (ZwQueryInformationProcess == NULL)
{
UNICODE_STRING routineName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
ZwQueryInformationProcess =
(QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName);
if (ZwQueryInformationProcess == NULL)
{
DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
status = STATUS_UNSUCCESSFUL;
goto cleanUp;
}
}
/* Query the actual size of the process path */
status = ZwQueryInformationProcess(hProcess,
ProcessImageFileName,
NULL, // buffer
0, // buffer size
&returnedLength);
if (STATUS_INFO_LENGTH_MISMATCH != status) {
DbgPrint("ZwQueryInformationProcess status = %x\n", status);
goto cleanUp;
}
*ProcessImageName = kmalloc(returnedLength);
if (ProcessImageName == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanUp;
}
/* Retrieve the process path from the handle to the process */
status = ZwQueryInformationProcess(hProcess,
ProcessImageFileName,
*ProcessImageName,
returnedLength,
&returnedLength);
if (!NT_SUCCESS(status)) kfree(*ProcessImageName);
cleanUp:
ZwClose(hProcess);
return status;
}
FLT_POSTOP_CALLBACK_STATUS
PostCreate(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
PUNICODE_STRING pni = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
status = GetProcessImageName(IoThreadToProcess(Data->Thread), &pni);
if (NT_SUCCESS(status))
{
DbgPrint("ProcessName = %ws\n", pni->Buffer);
kfree(pni);
}
else
{
DbgPrint("GetProcessImageName status = %x\n", status);
}
// ...
}
#1
1
You can use ZwQueryInformationProcess
with the information class of 27. THe following code uses this routine to obtain the full image file name from process' handle.
您可以将ZwQueryInformationProcess与信息类27一起使用。以下代码使用此例程从进程'句柄获取完整的映像文件名。
NTSTATUS GetProcessNameByHandle(_In_ HANDLE ProcessHandle, _Out_ PUNICODE_STRING *Name)
{
ULONG retLength = 0;
ULONG pniSize = 512;
PUNICODE_STRING pni = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
do {
pni = (PUNICODE_STRING)ExAllocatePoolWithTag(PagedPool, pniSize, POOL_TAG);
if (pni != NULL) {
status = ZwQueryInformationProcess(ProcessHandle, 27, pni, pniSize, &retLength);
if (!NT_SUCCESS(status)) {
ExFreePoolWithTag(pni, POOL_TAG);
pniSize *= 2;
}
} else status = STATUS_INSUFFICIENT_RESOURCES;
} while (status == STATUS_INFO_LENGTH_MISMATCH);
if (NT_SUCCESS(status))
*Name = pni;
return status;
}
You can obtain the process handle by the following ways:
您可以通过以下方式获取进程句柄:
-
ObOpenObjectByPointer
, you need process' EPROCESS address (PsLookupProcessByProcessId
may help).ObOpenObjectByPointer,您需要进程'EPROCESS地址(PsLookupProcessByProcessId可能有帮助)。
-
ZwOpenProcess
– youn need to know PID of the target process.ZwOpenProcess - 您需要知道目标进程的PID。
However, using this code in every invocation of your minifilter's pre/post callback can be quite time-consuming. I solve this problem by caching process names in a hash table that uses PID as a key. Notify routines (PsSetXXXNotifyRoutine(Ex)
) may prove very useful when building and managing such a table.
但是,在每次调用minifilter的前/后回调时使用此代码可能非常耗时。我通过在使用PID作为键的哈希表中缓存进程名来解决此问题。在构建和管理这样的表时,通知例程(PsSetXXXNotifyRoutine(Ex))可能非常有用。
#2
1
here I found full code like @Martin Drab code
在这里,我找到了像@Martin Drab代码的完整代码
EDIT: new fixed code
编辑:新的固定代码
NTSTATUS
GetProcessImageName(
PEPROCESS eProcess,
PUNICODE_STRING* ProcessImageName
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG returnedLength;
HANDLE hProcess = NULL;
PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
if (eProcess == NULL)
{
return STATUS_INVALID_PARAMETER_1;
}
status = ObOpenObjectByPointer(eProcess,
0, NULL, 0, 0, KernelMode, &hProcess);
if (!NT_SUCCESS(status))
{
DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status);
return status;
}
if (ZwQueryInformationProcess == NULL)
{
UNICODE_STRING routineName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
ZwQueryInformationProcess =
(QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName);
if (ZwQueryInformationProcess == NULL)
{
DbgPrint("Cannot resolve ZwQueryInformationProcess\n");
status = STATUS_UNSUCCESSFUL;
goto cleanUp;
}
}
/* Query the actual size of the process path */
status = ZwQueryInformationProcess(hProcess,
ProcessImageFileName,
NULL, // buffer
0, // buffer size
&returnedLength);
if (STATUS_INFO_LENGTH_MISMATCH != status) {
DbgPrint("ZwQueryInformationProcess status = %x\n", status);
goto cleanUp;
}
*ProcessImageName = kmalloc(returnedLength);
if (ProcessImageName == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanUp;
}
/* Retrieve the process path from the handle to the process */
status = ZwQueryInformationProcess(hProcess,
ProcessImageFileName,
*ProcessImageName,
returnedLength,
&returnedLength);
if (!NT_SUCCESS(status)) kfree(*ProcessImageName);
cleanUp:
ZwClose(hProcess);
return status;
}
FLT_POSTOP_CALLBACK_STATUS
PostCreate(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
PUNICODE_STRING pni = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
status = GetProcessImageName(IoThreadToProcess(Data->Thread), &pni);
if (NT_SUCCESS(status))
{
DbgPrint("ProcessName = %ws\n", pni->Buffer);
kfree(pni);
}
else
{
DbgPrint("GetProcessImageName status = %x\n", status);
}
// ...
}