windows 內核下獲取進程路徑


windows 內核下獲取進程路徑 

思路:
1):在EPROCESS結構中獲取。
此時要用到一個導出函數:PsGetProcessImageFileName,申明如下:

NTSYSAPI
UCHAR *
    PsGetProcessImageFileName(
    __in PEPROCESS Process
    );

此函數獲取的是一個簡單的進程名,並不是絕對路徑。

2):ZwQueryInformationProcess。

要想獲取進程的絕對路徑,可用一個未公開的函數:ZwQueryInformationProcess。MSDN上說win8以后此函數不支持了,但筆者在win7,win8 的x86,x64都試過了,都可以正常使用。筆者一般使用的時候用MmGetSystenRoutineAddress來找此函數的地址,找到后查找ProcessImageFileName(27號功能)信息,就可以得到UNICODE_STRING 類型的絕對進程路徑,但此絕對路徑並不是我我們在應用層看到的類似"C:\windows\abc.exe"這樣的路徑,而是這樣的表示方法"\Device\harddiskvolume1\windows\abc.exe".

3):從FILE_OBJECT中獲取

如果得到FILE_OBJECT的話可以從FILE_OBJECT中獲取。

typedef struct _FILE_OBJECT { CSHORT                            Type; CSHORT                            Size;  PDEVICE_OBJECT                    DeviceObject; PVPB                              Vpb; PVOID                             FsContext; PVOID                             FsContext2; PSECTION_OBJECT_POINTERS          SectionObjectPointer; PVOID                             PrivateCacheMap; NTSTATUS                          FinalStatus; struct _FILE_OBJECT  *RelatedFileObject; BOOLEAN                           LockOperation; BOOLEAN                           DeletePending; BOOLEAN                           ReadAccess; BOOLEAN                           WriteAccess; BOOLEAN                           DeleteAccess; BOOLEAN                           SharedRead; BOOLEAN                           SharedWrite; BOOLEAN                           SharedDelete; ULONG                             Flags; UNICODE_STRING                    FileName; LARGE_INTEGER                     CurrentByteOffset; __volatile ULONG                  Waiters; __volatile ULONG                  Busy; PVOID                             LastLock; KEVENT                            Lock; KEVENT                            Event; __volatile PIO_COMPLETION_CONTEXT CompletionContext; KSPIN_LOCK                        IrpListLock; LIST_ENTRY                        IrpList; __volatile PVOID                  FileObjectExtension; } FILE_OBJECT, *PFILE_OBJECT;
FILE_OBJECT中兩個重要的成員:FileName中含有除驅動器外的路徑,比如是這樣的"\WINDOWS\system32\notepad.exe"
此時再用另外一個函數IoVolumeDeviceToDosName,就可以將傳入的DeviceObject轉化為驅動器路徑。
NTSTATUS IoVolumeDeviceToDosName( _In_  PVOID      VolumeDeviceObject, _Out_ PUNICODE_STRING DosName );
將DosName和FileName拼接起來就可以得到絕對路徑"C:|windows\system32\notepad.exe".
最后用完后記得要把DosName的Buffer空間釋放掉。
MSDN如是說:

IoVolumeDeviceToDosName allocates the string buffer pointed to by the Buffer member of the UNICODE_STRING structure that the DosName parameter points to. After this buffer is no longer required, a caller of this routine should call the ExFreePool routine to free the buffer.

Starting with Windows Vista, you must ensure that APCs are not disabled before calling this routine. The KeAreAllApcsDisabled routine can be used to verify that APCs are not disabled

 

下面說幾個常見的類型轉換函數:

 ObReferenceObjectByHandle

此函數可以將句柄轉化成內核對應的結構,例如:

進程句柄(HANDLE)------>進程活動鏈指針(PEPROCESS)

文件句柄(HANDLE)------>文件對象指針(PFILE_OBJECT)

懶的說了,還是看圖吧,一圖勝千言:

PsGetProcessId
根據EPROCESS指針獲取進程ID

最后貼一段練習的代碼片段:

VOID GetProcPath(
	IN PRECORD_LIST pRecord,
	IN PHANDLE pHandle
	)
{
	NTSTATUS status = STATUS_SUCCESS;
	PUNICODE_STRING pUniImage = NULL;
	ULONG ulImageLen;

	UNICODE_STRING uniFunName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
	if (NULL == ZwQueryInformationProcess)
	{
		__try
		{
			ZwQueryInformationProcess = (PFUN_ZwQueryInformationProcess)MmGetSystemRoutineAddress(&uniFunName);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			KdPrint(("exception occured.\n"));
		}
		
		if (NULL == ZwQueryInformationProcess)
		{
			KdPrint(("MmGetSystemRoutineAddress failed .\n"));
			return;
		}
	}

	status = ZwQueryInformationProcess(*pHandle, ProcessImageFileName, pUniImage, 0, &ulImageLen);
	if (STATUS_INFO_LENGTH_MISMATCH != status)
	{
		KdPrint(("ZwQueryInformationProcess error code:(%x).\n", status));
		return;
	}
	pUniImage = ExAllocatePoolWithTag(NonPagedPool, ulImageLen, MEMTAG);
	if (NULL == pUniImage)
	{
		KdPrint((" no enough resources .\n"));
		return;
	}
	status = ZwQueryInformationProcess(*pHandle, ProcessImageFileName, pUniImage, ulImageLen, &ulImageLen);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("ZwQueryInformationProcess error code:(%x).\n", status));
		ExFreePool(pUniImage);
		return;
	}
	KdPrint(("ParentProcPath:(%wZ).\n", pUniImage));
	ExFreePool(pUniImage);
}



NTSTATUS GetProcessIdByHandle(
	IN const PHANDLE pHandle,
	IN PULONG pPid)
{
	NTSTATUS status = STATUS_SUCCESS;
	PEPROCESS pEprocess = NULL;

	status = ObReferenceObjectByHandle(*pHandle, 0, *PsProcessType, KernelMode, &pEprocess, NULL);
	if (!NT_SUCCESS(status))
	{
		KdPrint((" error code:(%08x) \n", status));
		return status;
	}

	*pPid = (ULONG)PsGetProcessId(pEprocess);
	ObDereferenceObject(pEprocess);

	return status;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM