zoukankan      html  css  js  c++  java
  • 内核中通过进程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路径.

  • 相关阅读:
    join
    PS1-4
    tftp + bras
    awk调用shell
    curl
    ssh
    查看cp进度,使用watch
    tftp
    scp 链接文件的问题 + tar
    mysql必知必会(三、使用mysql)
  • 原文地址:https://www.cnblogs.com/iBinary/p/11371168.html
Copyright © 2011-2022 走看看