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;
}

原文地址:https://www.cnblogs.com/priarieNew/p/9760399.html

时间: 2024-11-05 14:49:57

windows 内核下获取进程路径的相关文章

写一个Windows上的守护进程(8)获取进程路径

写一个Windows上的守护进程(8)获取进程路径 要想守护某个进程,就先得知道这个进程在不在.我们假设要守护的进程只会存在一个实例(这也是绝大部分情形). 我是遍历系统上的所有进程,然后判断他们的路径和要守护的进程是否一致,以此来确定进程是否存在. 遍历进程大家都知道用CreateToolhelp32Snapshot系列API,但是他们最后取得的是进程exe名称,不是全路径,如果仅依靠名称就可以达到目的也就罢了,但是有的时候还是得取到全路径,这样会更靠谱一些. 那么问题来了,如何取到进程全路径

windows内核代码之进程操作

[toc] 一丶简介 整理一下windows内核中.常用的代码.这里只整理下进程的相关代码. 二丶 windows内核之遍历进程 内核中记录进程的结构体是EPROCESS结构.所以只需要遍历这个结构即可.标准方法可以使用ZwQuerySystemInformation函数.使用SystemProcessInformation功能号. 另外也有很多种枚举进程的方法比如找到EPROCESS结构进行枚举的.(CPU结构体 KPCR)等等.不过兼容性都是不太好.另一种方法是枚举句柄表 PspCidTab

根据进程ID获取进程路径

根据进程ID获取进程路径有两种方法:方法1:OpenProcess --> GetModuleFileNameEx方法2:OpenProcess --> EnumProcessModules --> GetModuleFileNameEx 注意事项:1.使用GetModuleFileNameEx()而不是GetModuleFileName()2.GetModuleFileNameEx()指定的hProcess需要PROCESS_QUERY_INFORMATION | PROCESS_VM

【转】Windows内核下操作字符串!

* Windows内核下操作字符串! */ #include <ntddk.h> #include <ntstrsafe.h> #define BUFFER_SIZE 1024 VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) { KdPrint(("DriverUnload Load...\n")); } //==================================================

windows平台下获取USB设备&ldquo;身份证&rdquo;

当我们将U盘插入windows主机时,会提示安装驱动,那么windows是如何判断应该安装哪个版本的驱动的呢?在这里将用到设备的身份信息,包括厂商.型号.序列号等.大概半年前做了一个关于设备检测的小工程,看了很多资料和帖子,将获取设备身份信息的方法在此记录,方便以后使用. 0x01 USB设备有哪些身份信息 根据USB规范中的说明USB规范官方文档,供应商ID(VID)/产品识别码(PID)唯一标识一个设备,VID和PID都是两个字节长,其中,供应商ID(VID)由供应商向USB执行论坛申请,每

.Net下获取程序路径的方法

//方法一: string sPath = System.IO.Path.GetDirectoryName(this.Page.Request.PhysicalPath); //方法二:("images/")是当前虚拟目录下的任意目录 sPath = System.Web.HttpContext.Current.Request.MapPath("images/"); //方法三: sPath = Page.Server.MapPath("images/&q

Windows内核原理研究——进程创建

进程可能是用户接触的Windows系统中最多的部分了,对于Windows系统而言,进程是一个独立的地址空间可以为线程提供一个独立的执行环境, 也就是说 进程= 独立的地址空间 一个进程内核对象 线程= 一个线程自己的栈 一个线程内核对象 当然这个栈是在进程的地址空间中.那么,也就是说线程才是真正“干活”的东西,进程只不过是一些资源的集合而已.只能说是“原材料”. 在我学习Windows内核以前一直觉得进程的种种特性很神奇,比如说地址空间独立是怎么实现的呢?我们的电脑使用的都是同一块内存怎么能实现

linux下查看进程路径

在linux下查看进程大家都会想到用 ps -ef|grep XXX可是看到的不是全路径,怎么看全路径呢?每个进程启动之后在 /proc下面有一个于pid对应的路径例如:ps -ef|grep python显示:oracle    4431  4366  0 18:56 pts/2    00:00:00 python Server.py4431就是进程号到/proc/4431下,ls -l 会看到:总用量 0-r--r--r--    1 oracle   oinstall        0

C++ 获取进程路径

下面的实例可以简便实现这个功能. #include <stdio.h> #include <windows.h> int main() {      char str[MAX_PATH];      GetModuleFileName(NULL, str, MAX_PATH);      puts(str);      return 0; } 另外,想要枚举系统里面全部的进程,可以使用如下方式,关键是CreateToolhelp32Snapshot函数. PROCESSENTRY3