目录
一丶简介
在内核中有时候想通过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的 卷的全路径.
至于转化为我们常用的路径.看下一讲.