• 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:windowsabc.exe"这样的路径,而是这样的表示方法"Deviceharddiskvolume1windowsabc.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中含有除驱动器外的路径,比如是这样的"WINDOWSsystem32 otepad.exe"
    此时再用另外一个函数IoVolumeDeviceToDosName,就可以将传入的DeviceObject转化为驱动器路径。
    NTSTATUS IoVolumeDeviceToDosName( _In_  PVOID      VolumeDeviceObject, _Out_ PUNICODE_STRING DosName );
    将DosName和FileName拼接起来就可以得到绝对路径"C:|windowssystem32 otepad.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.
    "));
    		}
    		
    		if (NULL == ZwQueryInformationProcess)
    		{
    			KdPrint(("MmGetSystemRoutineAddress failed .
    "));
    			return;
    		}
    	}
    
    	status = ZwQueryInformationProcess(*pHandle, ProcessImageFileName, pUniImage, 0, &ulImageLen);
    	if (STATUS_INFO_LENGTH_MISMATCH != status)
    	{
    		KdPrint(("ZwQueryInformationProcess error code:(%x).
    ", status));
    		return;
    	}
    	pUniImage = ExAllocatePoolWithTag(NonPagedPool, ulImageLen, MEMTAG);
    	if (NULL == pUniImage)
    	{
    		KdPrint((" no enough resources .
    "));
    		return;
    	}
    	status = ZwQueryInformationProcess(*pHandle, ProcessImageFileName, pUniImage, ulImageLen, &ulImageLen);
    	if (!NT_SUCCESS(status))
    	{
    		KdPrint(("ZwQueryInformationProcess error code:(%x).
    ", status));
    		ExFreePool(pUniImage);
    		return;
    	}
    	KdPrint(("ParentProcPath:(%wZ).
    ", 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) 
    ", status));
    		return status;
    	}
    
    	*pPid = (ULONG)PsGetProcessId(pEprocess);
    	ObDereferenceObject(pEprocess);
    
    	return status;
    }
    
  • 相关阅读:
    Linux文件属性
    [Oracle] Listener的动态注册
    jQuery easyUI Pagination控件自定义div分页(不用datagrid)
    桂林电子科技大学出校流量控制器Android版1.0.0
    php使用check box
    Python windows ping
    Python selenium chrome 环境配置
    Linux wget auto login and backup database
    PyQt4 ShowHMDB show sqlite3 with QTableWidget summary
    PyQt4 py2exe 打包 HardwareManager
  • 原文地址:https://www.cnblogs.com/priarieNew/p/9760399.html
Copyright © 2020-2023  润新知