在windows驱动中,通过 进程ID,可以获得进程完整路径和进程名,
也可以获得进程所属的用户名。
以下代码是整理出来完成这些功能的 两个实现函数。
// By fanxiushu 2013-07-02
///获得进程名
NTSTATUS get_process_name(int pid, PWCHAR* out_fullpath, PWCHAR* out_name )
{
typedef NTSTATUS (*xxQUERY_INFO_PROCESS) (
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);
static xxQUERY_INFO_PROCESS ZwQueryInformationProcess = NULL ;
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG returnedLength;
ULONG bufferLength;
PVOID buffer;
PUNICODE_STRING imageName;
HANDLE handle;
*out_name = NULL; *out_fullpath = 0;
if( KeGetCurrentIrql() != PASSIVE_LEVEL ){
DPT("IRQL Must PASSIVE_LEVEL.\n");
return status;
}
if (NULL == ZwQueryInformationProcess) {
UNICODE_STRING routineName;
RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");
ZwQueryInformationProcess =
(xxQUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName);
if (NULL == ZwQueryInformationProcess) {
DPT("Cannot resolve ZwQueryInformationProcess\n");
return status ;
}
}
///get process handle;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID clientid;
InitializeObjectAttributes(&ObjectAttributes, 0 ,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
clientid.UniqueProcess = (HANDLE)pid;
clientid.UniqueThread=0;
status = ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &ObjectAttributes, &clientid);
if( !NT_SUCCESS(status)){
return status;
}
//
status = ZwQueryInformationProcess( handle,
ProcessImageFileName,
NULL, // buffer
0, // buffer size
&returnedLength);
if (STATUS_INFO_LENGTH_MISMATCH != status) {
ZwClose(handle);
return status;
}
bufferLength = returnedLength - sizeof(UNICODE_STRING);
buffer = ExAllocatePoolWithTag(NonPagedPool, returnedLength, 'FXSD');
if (NULL == buffer) {
ZwClose(handle);
return STATUS_NO_MEMORY ;
}
__try
{
status = ZwQueryInformationProcess( handle,
ProcessImageFileName,
buffer,
returnedLength,
&returnedLength);
if (NT_SUCCESS(status)) {
imageName = (PUNICODE_STRING) buffer;
////
USHORT len = imageName->Length;
RtlMoveMemory( buffer, imageName->Buffer, imageName->Length );
RtlZeroMemory( ((PUCHAR)buffer) + len, sizeof(WCHAR) );
*out_fullpath = (PWCHAR)buffer;
PWCHAR ptr = wcsrchr( (PWCHAR)buffer, L'\\');
if( ptr ){
*out_name = ptr + 1;
}else{
*out_name = (PWCHAR)buffer;
}
ZwClose(handle);
return STATUS_SUCCESS;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
DPT("get_process_name: Exception!!\n");
}
ZwClose(handle);
ExFreePool(buffer);
return status;
}
///以上是获得进程名,函数用完,需要手动释放内存 ExFreePool( out_fullpath );
/////////////////////
//获得进程所在用户,函数使用完,需要手动释放内存 ExFreePool( out_name);
//要能成功编译,需要 包含 ntifs.h头文件和添加 ksecdd.lib 库
static NTSTATUS get_procees_user( int pid, PWCHAR* out_name )
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
*out_name = NULL;
PEPROCESS pProcess = NULL;
PACCESS_TOKEN Token;
LUID luid;
PSecurityUserData userInformation = NULL;
PWCHAR name = NULL;
///
if( KeGetCurrentIrql() != PASSIVE_LEVEL ){
DPT("IRQL Must PASSIVE_LEVEL.\n");
return status;
}
////
status = PsLookupProcessByProcessId((HANDLE)pid, &pProcess );
if(!NT_SUCCESS(status)){
DPT("Not Find PID=%d\n", pid);
return status;
}
Token = PsReferencePrimaryToken(pProcess);
status = SeQueryAuthenticationIdToken(Token, &luid);
if( !NT_SUCCESS(status)){
DPT("SeQueryAuthenticationIdToken Error<%u>\n",status );
goto E;
}
status = GetSecurityUserInfo(&luid, UNDERSTANDS_LONG_NAMES, &userInformation);
if(!NT_SUCCESS(status) ){
DPT("GetSecurityUserInfo Error<%u>\n",status );
goto E;
}
name = (PWCHAR)ExAllocatePool(NonPagedPool, userInformation->UserName.Length +sizeof(WCHAR) );
if(!name){
status = STATUS_NO_MEMORY;
goto E;
}
RtlZeroMemory( name, userInformation->UserName.Length +sizeof(WCHAR) );
RtlCopyMemory( name, userInformation->UserName.Buffer, userInformation->UserName.Length );
*out_name = name ;
E:
ObDereferenceObject( pProcess );
ObDereferenceObject( Token );
if( userInformation )
LsaFreeReturnBuffer( userInformation );
return status;
}