內核中通過進程PID獲取進程的全部路徑


一丶簡介

我們遇到的Dos路徑.如果想轉化為NT路徑(也就是 C:\xxxx)類似的格式
需要自己實現.
具體原理如下:

二丶原理

1.原理

1.使用** ZwOpenProcess ** 通過進程PID獲取HANDLE
2.使用** ZwQueryInformationProcess ** 查詢Handle,使用27號(ProcessFileNmae)得到NT路徑.
3.使用** ZwOpenFile 打開路徑得到Handle
4.使用
ObReferenceObjectByHandle ** 獲得 內核對象(FileObject)
5.從FileObject的成員FileName得到其路徑
6.使用 RtlVolumeDeviceToDosName 將FileObject設備對象傳入.獲得Dos路徑.也就是盤符
7.拼接路徑進行傳出

2.代碼實現.

typedef NTSTATUS(*PfnZwQueryInformationProcess) (
	__in HANDLE ProcessHandle,
	__in PROCESSINFOCLASS ProcessInformationClass,
	__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
	__in ULONG ProcessInformationLength,
	__out_opt PULONG ReturnLength
	);

PfnZwQueryInformationProcess ZwQueryInformationProcess;

//初始化未公開的導出函數
NTSTATUS InitGloableFunction()
{
	UNICODE_STRING UtrZwQueryInformationProcessName =
		RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
	ZwQueryInformationProcess =
		(PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);
	return STATUS_SUCCESS;
}
NTSTATUS GetDosPathByProcessId(IN ULONG pid,OUT PANSI_STRING pAnsiNtPath)
{
	/*
	1.根據PID獲取進程句柄
	2.使用ZwQueryInformationProcess 傳入HANDLE 使用27號功能獲取路徑
	*/
	HANDLE hProcess = 0;
	CLIENT_ID cid;
	OBJECT_ATTRIBUTES obj;
	NTSTATUS ntStatus;
	ULONG RetLength = 0;
	PVOID pBuffer = NULL;
	HANDLE hFile;
	IO_STATUS_BLOCK iostu;
	PVOID FileObject = NULL;
	PFILE_OBJECT pMyFileObject = NULL;
	UNICODE_STRING DosName;
	UNICODE_STRING FunllPath;
	
	if (ZwQueryInformationProcess == NULL)
		return STATUS_UNSUCCESSFUL;

	cid.UniqueProcess =(HANDLE)pid;
	cid.UniqueThread = 0;
	InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
	ntStatus = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &obj, &cid);
	if (!NT_SUCCESS(ntStatus))
		return STATUS_UNSUCCESSFUL;
	//使用27 號功能遍歷
	
	ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, NULL, 0, &RetLength);
	if (STATUS_INFO_LENGTH_MISMATCH != ntStatus)
		return STATUS_UNSUCCESSFUL;

	//申請內存繼續獲取.
	pBuffer = ExAllocatePoolWithTag(PagedPool, RetLength, 'niBI');
	if (NULL == pBuffer)
		return STATUS_UNSUCCESSFUL;
	//重新調用獲取.
	
	ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, pBuffer, RetLength, &RetLength);
	if (!NT_SUCCESS(ntStatus))
	{
		if (NULL != pBuffer)
		{
			ExFreePoolWithTag(pBuffer, 'niBI');
		}
		return STATUS_UNSUCCESSFUL;
	}
	
	//開始轉化路徑
	InitializeObjectAttributes(&obj, pBuffer, OBJ_KERNEL_HANDLE, 0, 0);
	ntStatus = ZwOpenFile(
		&hFile,
		GENERIC_READ,
		&obj,
		&iostu,
		FILE_SHARE_READ| FILE_SHARE_WRITE , 
		0);
	if (!NT_SUCCESS(ntStatus))
	{
		if (NULL != pBuffer)
		{
			ExFreePoolWithTag(pBuffer, 'niBI');
		}
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}

	//獲得文件對象
	ntStatus = ObReferenceObjectByHandle(
		hFile, 
		GENERIC_ALL, 
		*IoFileObjectType, 
		KernelMode,
		&FileObject,
		NULL);
	
	if (!NT_SUCCESS(ntStatus))
	{
		if (NULL != pBuffer)
		{
			ExFreePoolWithTag(pBuffer, 'niBI');
		}
		ntStatus = ObDereferenceObject(FileObject);
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}
	pMyFileObject = (PFILE_OBJECT)FileObject;
	if (NULL == pMyFileObject)
	{
		if (NULL != pBuffer)
		{
			ExFreePoolWithTag(pBuffer, 'niBI');
		}
		ntStatus = ObDereferenceObject(FileObject);
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
		
	}
	//通過 RtlVolumeDeviceToDosName 獲取Dos路徑 也即是C: D: 等盤符
	RtlVolumeDeviceToDosName(pMyFileObject->DeviceObject,&DosName);

	//獲得路徑直接直接拼接即可.

	FunllPath.MaximumLength = pMyFileObject->FileName.MaximumLength + DosName.MaximumLength;
	FunllPath.Length = pMyFileObject->FileName.Length + DosName.Length;
	FunllPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, FunllPath.MaximumLength, 0);

	//拼接路徑
	RtlCopyUnicodeString(&FunllPath, &DosName);//得到C:
	RtlAppendUnicodeStringToString(&FunllPath, &pMyFileObject->FileName);//得到C:\\xxx路徑,轉為Asii
	RtlUnicodeStringToAnsiString(pAnsiNtPath, &FunllPath,TRUE); //RtlFreeAnsiString  要釋放空間.

	
	ExFreePool(FunllPath.Buffer); //因為傳出自動為其分配了內存所以這個進行誰放
	if (NULL != pBuffer)
	{
		ExFreePoolWithTag(pBuffer, 'niBI');
	}

	ntStatus = ObDereferenceObject(FileObject);
	ZwClose(hFile);
	return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{


	
	ANSI_STRING AnsiNtPath;
	pDriverObj->DriverUnload = DriverUnLoad;
	InitGloableFunction();
	KdBreakPoint();
	GetDosPathByProcessId(3356,&AnsiNtPath);
	
	return STATUS_SUCCESS;
}

以下為調試的時候的代碼截圖.
1.得到FileName

2.使用RtlVolumeDeviceToDosName 得到盤符

3.拼接路徑為UNICODE_STRING類型

4.為傳入的ANSI_STRING 分配空間轉換.得到ANSI_STRING路徑.


免責聲明!

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



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