NT5/NT6上的获取进程全路径

前面说过使用一大堆函数获取全路径

PID->eprocess->KeStackAttachProcess->ZwQueryInformationProcess->ProcessImageFileName->ZwCreateFile

->ObReferenceObjectByHandle->RtlVolumeDeviceToDosName
->ZwQueryInformationFile


code:

NTKERNELAPI NTSTATUS 
PsLookupProcessByProcessId(
	IN HANDLE ProcessId,
	OUT PEPROCESS *Process
);


/*NTSTATUS  
IoQueryFileDosDeviceName(  
    IN PFILE_OBJECT FileObject,  
    OUT POBJECT_NAME_INFORMATION *ObjectNameInformation  
); */


NTSTATUS
NTAPI
ZwQueryInformationProcess(
						  __in HANDLE ProcessHandle,
						  __in PROCESSINFOCLASS ProcessInformationClass,
						  __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
						  __in ULONG ProcessInformationLength,
						  __out_opt PULONG ReturnLength
    );


NTSTATUS  GetProcessFullNameByPid(HANDLE nPid, PUNICODE_STRING  FullPath)
{

    HANDLE               hFile      = NULL;
    ULONG                nNeedSize	= 0;
    NTSTATUS             nStatus    = STATUS_SUCCESS;
    NTSTATUS             nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
    PEPROCESS            Process    = NULL;
    KAPC_STATE           ApcState   = {0};			
    PVOID                lpBuffer   = NULL;
    OBJECT_ATTRIBUTES	 ObjectAttributes = {0};
    IO_STATUS_BLOCK      IoStatus   = {0}; 
    PFILE_OBJECT         FileObject = NULL;
    PFILE_NAME_INFORMATION FileName = NULL;   
    WCHAR                FileBuffer[MAX_PATH] = {0};
    DECLARE_UNICODE_STRING_SIZE(ProcessPath,MAX_PATH);
    DECLARE_UNICODE_STRING_SIZE(DosDeviceName,MAX_PATH);
    
    PAGED_CODE();

    nStatus = PsLookupProcessByProcessId(nPid, &Process);
    if(NT_ERROR(nStatus))
    {
        KdPrint(("%s error PsLookupProcessByProcessId.\n",__FUNCTION__));
        return nStatus;
    }



    __try
    {

        KeStackAttachProcess(Process, &ApcState);
        
        nStatus = ZwQueryInformationProcess(
            NtCurrentProcess(),
            ProcessImageFileName,
            NULL,
            NULL,
            &nNeedSize
            );

        if (STATUS_INFO_LENGTH_MISMATCH != nStatus)
        {
            KdPrint(("%s NtQueryInformationProcess error.\n",__FUNCTION__)); 
            nStatus = STATUS_MEMORY_NOT_ALLOCATED;
            __leave;

        }

        lpBuffer = ExAllocatePoolWithTag(NonPagedPool, nNeedSize,'GetP');
        if (lpBuffer == NULL)
        {
            KdPrint(("%s ExAllocatePoolWithTag error.\n",__FUNCTION__));
            nStatus = STATUS_MEMORY_NOT_ALLOCATED;
            __leave; 
        }

       nStatus =  ZwQueryInformationProcess(
           NtCurrentProcess(),
           ProcessImageFileName, 
           lpBuffer, 
           nNeedSize,
           &nNeedSize
           );

       if (NT_ERROR(nStatus))
       {
           KdPrint(("%s NtQueryInformationProcess error2.\n",__FUNCTION__));
           __leave;
       }

       RtlCopyUnicodeString(&ProcessPath,(PUNICODE_STRING)lpBuffer);
       InitializeObjectAttributes(
           &ObjectAttributes,
           &ProcessPath,
           OBJ_CASE_INSENSITIVE,
           NULL,
           NULL
           );

       nStatus = ZwCreateFile(
           &hFile,
           FILE_READ_ATTRIBUTES,
           &ObjectAttributes,
           &IoStatus,
           NULL,
           FILE_ATTRIBUTE_NORMAL,
           0,
           FILE_OPEN,
           FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
           NULL,
           0
           );  

       if (NT_ERROR(nStatus))
       {
           hFile = NULL;
           __leave;
       }

       nStatus = ObReferenceObjectByHandle(
           hFile, 
           NULL,
           *IoFileObjectType, 
           KernelMode, 
           (PVOID*)&FileObject,
           NULL
           );

       if (NT_ERROR(nStatus))
       {
           FileObject = NULL;
           __leave;
       }
       
       FileName = (PFILE_NAME_INFORMATION)FileBuffer;
       
       nStatus = ZwQueryInformationFile(
           hFile,
           &IoStatus,
           FileName,
           sizeof(WCHAR)*MAX_PATH,
           FileNameInformation
           );

       if (NT_ERROR(nStatus))
       {
           __leave;
       }

       if (FileObject->DeviceObject == NULL)
       {
           nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
           __leave;
       }

       nDeviceStatus = RtlVolumeDeviceToDosName(FileObject->DeviceObject,&DosDeviceName);

    }
    __finally
    {
        if (NULL != FileObject)
        {
            ObDereferenceObject(FileObject);
        }

        if (NULL != hFile)
        {
            ZwClose(hFile);
        }

        if (NULL != lpBuffer)
        {
            ExFreePool(lpBuffer);
        }

        KeUnstackDetachProcess(&ApcState);


    }

    if (NT_SUCCESS(nStatus))
    {
        RtlInitUnicodeString(&ProcessPath,FileName->FileName);

        if (NT_SUCCESS(nDeviceStatus))
        {
            RtlCopyUnicodeString(FullPath,&DosDeviceName);
            RtlUnicodeStringCat(FullPath,&ProcessPath);
        }
        else
        {
            RtlCopyUnicodeString(FullPath,&ProcessPath);
        }
    }


    return nStatus;
}

这实在是太麻烦了

其实要获得全路径 就是要获得FIleObject 而FIleObject就在EPROCESS结构下 详细继续读下去

在NT5上PsReferenceProcessFilePointer没有导出,需要自己实现

在WRK中:

NTSTATUS NTAPI PsReferenceProcessFilePointer        
(
        IN PEPROCESS         Process,
        OUT PFILE_OBJECT *         FileObject 
)                
{
    PSECTION Section;
    PAGED_CODE();

    /* Lock the process */
    ExAcquireRundownProtection(&Process->RundownProtect);

    /* Get the section */
    Section = Process->SectionObject;
    if (Section)
    {
        /* Get the file object and reference it */
        *FileObject = MmGetFileObjectForSection((PVOID)Section);
        ObReferenceObject(*FileObject);
    }

    /* Release the protection */
    ExReleaseRundownProtection(&Process->RundownProtect);

    /* Return status */
    return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}

PFILE_OBJECT NTAPI MmGetFileObjectForSection
(
        IN PVOID         Section
)        
{
    PSECTION_OBJECT Section;
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    ASSERT(SectionObject != NULL);

    /* Check if it's an ARM3, or ReactOS section */
    if (MiIsRosSectionObject(SectionObject) == FALSE)
    {
        /* Return the file pointer stored in the control area */
        Section = SectionObject;
        return Section->Segment->ControlArea->FilePointer;
    }

    /* Return the file object */
    return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
}

FileObject要这么获得:Process->SectionObject->Segment->ControlArea->FilePointer

大概需要4个硬编码

XP:

code:

//Process->SectionObject->Segment->ControlArea->FilePointer
PFILE_OBJECT __declspec(naked) __stdcall _MmGetFileObjectForSection(PVOID Section)  
{  
    __asm  
    {  
        push ebp;  
        mov  ebp, esp;  
        mov  eax, dword ptr ss:[ebp + 0x08];  
        mov  eax, dword ptr ds:[eax + 0x14];  
        mov  eax, dword ptr ds:[eax];  
        mov  eax, dword ptr ds:[eax + 0x24];  
        mov  esp, ebp;  
        pop  ebp;  
        ret  0x04;  
    }  
	/*
	kd> dt _section_object 0xe109e640
nt!_SECTION_OBJECT
   +0x000 StartingVa       : (null) 
   +0x004 EndingVa         : (null) 
   +0x008 Parent           : (null) 
   +0x00c LeftChild        : (null) 
   +0x010 RightChild       : (null) 
   +0x014 Segment          : 0xe10c14c0 _SEGMENT_OBJECT
kd> dt _SEGMENT_OBJECT 0xe10c14c0
nt!_SEGMENT_OBJECT
   +0x000 BaseAddress      : 0x861f2348 Void
   +0x004 TotalNumberOfPtes : 0xb1
   +0x008 SizeOfSegment    : _LARGE_INTEGER 0xb1
   +0x010 NonExtendedPtes  : 0xb1000
   +0x014 ImageCommitment  : 0
   +0x018 ControlArea      : 0xcbf13c3e _CONTROL_AREA
   +0x01c Subsection       : (null) 
   +0x020 LargeControlArea : (null) 
   +0x024 MmSectionFlags   : (null) 
   +0x028 MmSubSectionFlags : 0x00400000 _MMSUBSECTION_FLAGS
kd> dt _CONTROL_AREA 0x861f2348
nt!_CONTROL_AREA
   +0x000 Segment          : 0xe10c14c0 _SEGMENT
   +0x004 DereferenceList  : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x00c NumberOfSectionReferences : 1
   +0x010 NumberOfPfnReferences : 0xa1
   +0x014 NumberOfMappedViews : 1
   +0x018 NumberOfSubsections : 5
   +0x01a FlushInProgressCount : 0
   +0x01c NumberOfUserReferences : 2
   +0x020 u                : __unnamed
   +0x024 FilePointer      : 0x8602caf8 _FILE_OBJECT
   +0x028 WaitingForDeletion : (null) 
   +0x02c ModifiedWriteCount : 0
   +0x02e NumberOfSystemCacheViews : 0
kd> dt _FILE_OBJECT 0x8602caf8
nt!_FILE_OBJECT
   +0x000 Type             : 0n5
   +0x002 Size             : 0n112
   +0x004 DeviceObject     : 0x8632c030 _DEVICE_OBJECT
   +0x008 Vpb              : 0x862443c8 _VPB
   +0x00c FsContext        : 0xe1059aa0 Void
   +0x010 FsContext2       : 0xe105b648 Void
   +0x014 SectionObjectPointer : 0x85e16fa0 _SECTION_OBJECT_POINTERS
   +0x018 PrivateCacheMap  : (null) 
   +0x01c FinalStatus      : 0n0
   +0x020 RelatedFileObject : (null) 
   +0x024 LockOperation    : 0 ''
   +0x025 DeletePending    : 0 ''
   +0x026 ReadAccess       : 0x1 ''
   +0x027 WriteAccess      : 0 ''
   +0x028 DeleteAccess     : 0 ''
   +0x029 SharedRead       : 0x1 ''
   +0x02a SharedWrite      : 0 ''
   +0x02b SharedDelete     : 0x1 ''
   +0x02c Flags            : 0xc4042
   +0x030 FileName         : _UNICODE_STRING "\Program Files\VMware\VMware Tools\TPAutoConnect.exe"
   +0x038 CurrentByteOffset : _LARGE_INTEGER 0x0
   +0x040 Waiters          : 0
   +0x044 Busy             : 0
   +0x048 LastLock         : (null) 
   +0x04c Lock             : _KEVENT
   +0x05c Event            : _KEVENT
   +0x06c CompletionContext : (null) 

	*/
}  
  
NTSTATUS PsReferenceProcessFilePointer(IN PEPROCESS Process, OUT PVOID *OutFileObject)  
{  
    PVOID SectionObject;  
	//xp: 
	// +0x134 Job              : Ptr32 _EJOB
	// +0x138 SectionObject    : Ptr32 Void
    if (SectionObject = *(PVOID*)((PCHAR)Process + 0x138))  
    {  
        PFILE_OBJECT FileObject;  
  
        FileObject = _MmGetFileObjectForSection(SectionObject);  
        *OutFileObject = FileObject;  
        ObReferenceObject (FileObject);  
        return STATUS_SUCCESS;  
    }  
    return STATUS_UNSUCCESSFUL;  
}  

PUNICODE_STRING PsGetProcessFullNameByHardCodeOfXP(PEPROCESS pTargetProcess)
{
        PFILE_OBJECT pFileObject=NULL;
        POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
		if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
                return NULL;
        if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
                return NULL;
        return &(pObjectNameInfo->Name);//尚未释放内存
}

除了这个以外:还有一个

Process->SeAuditProcessCreationInfo.ImageFileName->Name


在WRK中可以看到

这说明从这个路径可能是不存在的

NTSTATUS
SeLocateProcessImageName(
    __in PEPROCESS Process,
    __deref_out PUNICODE_STRING *pImageFileName
    )


/*++


Routine Description
    
    This routine returns the ImageFileName information from the process, if available.  This is a "lazy evaluation" wrapper 
    around SeInitializeProcessAuditName.  If the image file name information has already been computed, then this call simply
    allocates and returns a UNICODE_STRING with this information.  Otherwise, the function determines the name, stores the name in the 
    EPROCESS structure, and then allocates and returns a UNICODE_STRING.  Caller must free the memory returned in pImageFileName.
    
Arguments


    Process - process for which to acquire the name
    
    pImageFileName - output parameter to return name to caller
    
Return Value


    NTSTATUS. 
    
--*/


{
    NTSTATUS                 Status            = STATUS_SUCCESS;
    PVOID                    FilePointer       = NULL;
    PVOID                    PreviousValue     = NULL;
    POBJECT_NAME_INFORMATION pProcessImageName = NULL;
    PUNICODE_STRING          pTempUS           = NULL;
    ULONG                    NameLength        = 0;


    PAGED_CODE();


    *pImageFileName = NULL;
    
    if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {


        //
        // The name has not been predetermined.  We must determine the process name.   First, reference the 
        // PFILE_OBJECT and lookup the name.  Then again check the process image name pointer against NULL.  
        // Finally, set the name.
        //


        Status = PsReferenceProcessFilePointer( Process, &FilePointer );
        
        if (NT_SUCCESS(Status)) {


            //
            // Get the process name information.  
            //


            Status = SeInitializeProcessAuditName( 
                          FilePointer,
                          TRUE, // skip audit policy
                          &pProcessImageName // to be allocated in nonpaged pool
                          );


            if (NT_SUCCESS(Status)) {


                //
                // Only use the pProcessImageName if the field in the process is currently NULL.
                //


                PreviousValue = InterlockedCompareExchangePointer(
                                    (PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
                                    (PVOID) pProcessImageName,
                                    (PVOID) NULL
                                    );
                
                if (NULL != PreviousValue) {
                    ExFreePool(pProcessImageName); // free what we caused to be allocated.
                }
            }
            ObDereferenceObject( FilePointer );
        }
    }
    
    
    if (NT_SUCCESS(Status)) {
        
        //
        // Allocate space for a buffer to contain the name for returning to the caller.
        //


        NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
        pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );


        if (NULL != pTempUS) {


            RtlCopyMemory( 
                pTempUS, 
                &Process->SeAuditProcessCreationInfo.ImageFileName->Name, 
                NameLength 
                );


            pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
            *pImageFileName = pTempUS;


        } else {
            
            Status = STATUS_NO_MEMORY;
        }
    }


    return Status;
}

我自己实现了下 在win7 x86下效果还是可以的 不过使用了硬编码,推荐还是在NT5上使用(NT6很简单)

PUNICODE_STRING GetSeLocateProcessImageName(PEPROCESS Process,PUNICODE_STRING *pImageFileName)
{
	 POBJECT_NAME_INFORMATION pProcessImageName = NULL;
	 PUNICODE_STRING pTempUS = NULL;
	 ULONG NameLength = 0;
	 //Process->SeAuditProcessCreationInfo.ImageFileName->Name
	 //win7 x86 offset = 0x1ec
	 //if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName)
	 pProcessImageName = (POBJECT_NAME_INFORMATION)(*(ULONG*)((ULONG)Process + 0x1ec));
	 if(pProcessImageName == NULL)
	 {
		 DbgPrint("Process->SeAuditProcessCreationInfo.ImageFileName == NULL \n");
		 return NULL;
	 }
	 else
	 {
		 NameLength = sizeof(UNICODE_STRING) + pProcessImageName->Name.MaximumLength;
		 pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
		 if (NULL != pTempUS) {

            RtlCopyMemory( 
                pTempUS, 
				&pProcessImageName->Name, 
                NameLength 
                );

            pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
            *pImageFileName = pTempUS;
			 DbgPrint("Path:%wZ\n",&pProcessImageName->Name); 
			 return *pImageFileName;
		 }
		 return NULL;
	 }

}


而NT6就很简单了

PsReferenceProcessFilePointe已经被导出了

那么直接使用

PsReferenceProcessFilePointe + IoQueryFileDosDeviceName就可以了

PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
{
        PFILE_OBJECT pFileObject=NULL;
        POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
		if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
                return NULL;
        if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
                return NULL;
        return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
}


除了这些以前还有一些路径存在PEB里 如果在x64的系统中 还得看是PEB32还是PEB64 虽然可以使用PsGetProcessWow64Process来判断是不是64进程

但这些数据在r3就可以直接被修改了 所以不太建议使用

PEB->ProcessParameters->ImagePathName
PEB->ProcessParameters->CommandLine
PEB->ProcessParameters->WindowTitle
PEB->Ldr->InLoadOrderLinks->FullDllName
PEB->Ldr->InMemoryOrderLinks->FullDllName


大家看看黑客防线里面的《伪造进程初探》和获取进程完整路径方法小结.pdf

另外一个博主写的也是不错的

http://blog.csdn.net/sidyhe/article/details/42969803 //EPROCESS取进程全路径

http://blog.csdn.net/sidyhe/article/details/43638651 //EPROCESS取进程全路径(xp)

发布了131 篇原创文章 · 获赞 53 · 访问量 28万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览