内核中根据进程Pid获取卷的全目录
- 2019 年 10 月 8 日
- 笔记
目录
一丶简介
在内核中有时候想通过PID 获取进程的全路径以达到监控的作用 比如我们设置了进程回调.则可以根据PID看下进程的全路径.
二丶原理
原理就是在内核中 通过 ZwQueryInformationProcess 这个未公开的函数 进行查询. 查询好是 ** ProcessImageFileName ** 也就是27号功能.
但是查询出来的路径是Dos路径.还需要进行转化.
1.传入PID 使用 ZwOpenProcess打开PID获取Handle 2.使用ZwQueryInfomationProcess*的27号功能(ProcessImageFileName) 传入 Process的Handle来获取路径.
3.代码实现.
1.首先是未公开的函数获取.
结构定义:
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; }
2.获取NT路径
NTSTATUS GetDosPathByProcessId(ULONG pid) { /* 1.根据PID获取进程句柄 2.使用ZwQueryInformationProcess 传入HANDLE 使用27号功能获取路径 */ HANDLE hProcess = 0; CLIENT_ID cid; OBJECT_ATTRIBUTES obj; NTSTATUS ntStatus; ULONG RetLength = 0; PVOID pBuffer = NULL; UNICODE_STRING uRetStrNtPath; 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)) return STATUS_UNSUCCESSFUL; //此时Puffer就已经是我们的路径了 进行该有的操作即可. return STATUS_SUCCESS; }
因为暂时是做测试,所以并没有返回Buffer的值.
windbg查看.

可以看到已经获取了 calc的 卷的全路径.
至于转化为我们常用的路径.看下一讲.