看流星社区

 找回密码
 注册账号
查看: 1859|回复: 0

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

[复制链接]

该用户从未签到

发表于 2017-6-1 13:33:02 | 显示全部楼层 |阅读模式
前面说过使用一大堆函数获取全路径


PID->eprocess->KeStackAttachProcess->ZwQueryInformationProcess-&gtrocessImageFileName->ZwCreateFile

->ObReferenceObjectByHandle->RtlVolumeDeviceToDosName
->ZwQueryInformationFile


code:
  1. NTKERNELAPI NTSTATUS
  2. PsLookupProcessByProcessId(
  3.         IN HANDLE ProcessId,
  4.         OUT PEPROCESS *Process
  5. );
  6. /*NTSTATUS  
  7. IoQueryFileDosDeviceName(  
  8.     IN PFILE_OBJECT FileObject,  
  9.     OUT POBJECT_NAME_INFORMATION *ObjectNameInformation  
  10. ); */
  11. NTSTATUS
  12. NTAPI
  13. ZwQueryInformationProcess(
  14.                                                   __in HANDLE ProcessHandle,
  15.                                                   __in PROCESSINFOCLASS ProcessInformationClass,
  16.                                                   __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
  17.                                                   __in ULONG ProcessInformationLength,
  18.                                                   __out_opt PULONG ReturnLength
  19.     );
复制代码


  1. NTSTATUS  GetProcessFullNameByPid(HANDLE nPid, PUNICODE_STRING  FullPath)
  2. {
  3.     HANDLE               hFile      = NULL;
  4.     ULONG                nNeedSize        = 0;
  5.     NTSTATUS             nStatus    = STATUS_SUCCESS;
  6.     NTSTATUS             nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  7.     PEPROCESS            Process    = NULL;
  8.     KAPC_STATE           ApcState   = {0};                       
  9.     PVOID                lpBuffer   = NULL;
  10.     OBJECT_ATTRIBUTES         ObjectAttributes = {0};
  11.     IO_STATUS_BLOCK      IoStatus   = {0};
  12.     PFILE_OBJECT         FileObject = NULL;
  13.     PFILE_NAME_INFORMATION FileName = NULL;   
  14.     WCHAR                FileBuffer[MAX_PATH] = {0};
  15.     DECLARE_UNICODE_STRING_SIZE(ProcessPath,MAX_PATH);
  16.     DECLARE_UNICODE_STRING_SIZE(DosDeviceName,MAX_PATH);
  17.    
  18.     PAGED_CODE();
  19.     nStatus = PsLookupProcessByProcessId(nPid, &Process);
  20.     if(NT_ERROR(nStatus))
  21.     {
  22.         KdPrint(("%s error PsLookupProcessByProcessId.\n",__FUNCTION__));
  23.         return nStatus;
  24.     }
  25.     __try
  26.     {
  27.         KeStackAttachProcess(Process, &ApcState);
  28.         
  29.         nStatus = ZwQueryInformationProcess(
  30.             NtCurrentProcess(),
  31.             ProcessImageFileName,
  32.             NULL,
  33.             NULL,
  34.             &nNeedSize
  35.             );
  36.         if (STATUS_INFO_LENGTH_MISMATCH != nStatus)
  37.         {
  38.             KdPrint(("%s NtQueryInformationProcess error.\n",__FUNCTION__));
  39.             nStatus = STATUS_MEMORY_NOT_ALLOCATED;
  40.             __leave;
  41.         }
  42.         lpBuffer = ExAllocatePoolWithTag(NonPagedPool, nNeedSize,'GetP');
  43.         if (lpBuffer == NULL)
  44.         {
  45.             KdPrint(("%s ExAllocatePoolWithTag error.\n",__FUNCTION__));
  46.             nStatus = STATUS_MEMORY_NOT_ALLOCATED;
  47.             __leave;
  48.         }
  49.        nStatus =  ZwQueryInformationProcess(
  50.            NtCurrentProcess(),
  51.            ProcessImageFileName,
  52.            lpBuffer,
  53.            nNeedSize,
  54.            &nNeedSize
  55.            );
  56.        if (NT_ERROR(nStatus))
  57.        {
  58.            KdPrint(("%s NtQueryInformationProcess error2.\n",__FUNCTION__));
  59.            __leave;
  60.        }
  61.        RtlCopyUnicodeString(&ProcessPath,(PUNICODE_STRING)lpBuffer);
  62.        InitializeObjectAttributes(
  63.            &ObjectAttributes,
  64.            &ProcessPath,
  65.            OBJ_CASE_INSENSITIVE,
  66.            NULL,
  67.            NULL
  68.            );
  69.        nStatus = ZwCreateFile(
  70.            &hFile,
  71.            FILE_READ_ATTRIBUTES,
  72.            &ObjectAttributes,
  73.            &IoStatus,
  74.            NULL,
  75.            FILE_ATTRIBUTE_NORMAL,
  76.            0,
  77.            FILE_OPEN,
  78.            FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
  79.            NULL,
  80.            0
  81.            );  
  82.        if (NT_ERROR(nStatus))
  83.        {
  84.            hFile = NULL;
  85.            __leave;
  86.        }
  87.        nStatus = ObReferenceObjectByHandle(
  88.            hFile,
  89.            NULL,
  90.            *IoFileObjectType,
  91.            KernelMode,
  92.            (PVOID*)&FileObject,
  93.            NULL
  94.            );
  95.        if (NT_ERROR(nStatus))
  96.        {
  97.            FileObject = NULL;
  98.            __leave;
  99.        }
  100.       
  101.        FileName = (PFILE_NAME_INFORMATION)FileBuffer;
  102.       
  103.        nStatus = ZwQueryInformationFile(
  104.            hFile,
  105.            &IoStatus,
  106.            FileName,
  107.            sizeof(WCHAR)*MAX_PATH,
  108.            FileNameInformation
  109.            );
  110.        if (NT_ERROR(nStatus))
  111.        {
  112.            __leave;
  113.        }
  114.        if (FileObject->DeviceObject == NULL)
  115.        {
  116.            nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  117.            __leave;
  118.        }
  119.        nDeviceStatus = RtlVolumeDeviceToDosName(FileObject->DeviceObject,&DosDeviceName);
  120.     }
  121.     __finally
  122.     {
  123.         if (NULL != FileObject)
  124.         {
  125.             ObDereferenceObject(FileObject);
  126.         }
  127.         if (NULL != hFile)
  128.         {
  129.             ZwClose(hFile);
  130.         }
  131.         if (NULL != lpBuffer)
  132.         {
  133.             ExFreePool(lpBuffer);
  134.         }
  135.         KeUnstackDetachProcess(&ApcState);
  136.     }
  137.     if (NT_SUCCESS(nStatus))
  138.     {
  139.         RtlInitUnicodeString(&ProcessPath,FileName->FileName);
  140.         if (NT_SUCCESS(nDeviceStatus))
  141.         {
  142.             RtlCopyUnicodeString(FullPath,&DosDeviceName);
  143.             RtlUnicodeStringCat(FullPath,&ProcessPath);
  144.         }
  145.         else
  146.         {
  147.             RtlCopyUnicodeString(FullPath,&ProcessPath);
  148.         }
  149.     }
  150.     return nStatus;
  151. }
复制代码
这实在是太麻烦了

其实要获得全路径 就是要获得FIleObject 而FIleObject就在EPROCESS结构下 详细继续读下去
在NT5上PsReferenceProcessFilePointer没有导出,需要自己实现
在WRK中:
  1. NTSTATUS NTAPI PsReferenceProcessFilePointer        
  2. (
  3.         IN PEPROCESS         Process,
  4.         OUT PFILE_OBJECT *         FileObject
  5. )               
  6. {
  7.     PSECTION Section;
  8.     PAGED_CODE();
  9.     /* Lock the process */
  10.     ExAcquireRundownProtection(&Process->RundownProtect);
  11.     /* Get the section */
  12.     Section = Process->SectionObject;
  13.     if (Section)
  14.     {
  15.         /* Get the file object and reference it */
  16.         *FileObject = MmGetFileObjectForSection((PVOID)Section);
  17.         ObReferenceObject(*FileObject);
  18.     }
  19.     /* Release the protection */
  20.     ExReleaseRundownProtection(&Process->RundownProtect);
  21.     /* Return status */
  22.     return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  23. }
  24. PFILE_OBJECT NTAPI MmGetFileObjectForSection
  25. (
  26.         IN PVOID         Section
  27. )        
  28. {
  29.     PSECTION_OBJECT Section;
  30.     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  31.     ASSERT(SectionObject != NULL);
  32.     /* Check if it's an ARM3, or ReactOS section */
  33.     if (MiIsRosSectionObject(SectionObject) == FALSE)
  34.     {
  35.         /* Return the file pointer stored in the control area */
  36.         Section = SectionObject;
  37.         return Section->Segment->ControlArea->FilePointer;
  38.     }
  39.     /* Return the file object */
  40.     return ((PROS_SECTION_OBJECT)SectionObject)->FileObject;
  41. }
复制代码
FileObject要这么获得:Process->SectionObject->Segment->ControlArea->FilePointer

大概需要4个硬编码
XP:
code:
  1. //Process->SectionObject->Segment->ControlArea->FilePointer
  2. PFILE_OBJECT __declspec(naked) __stdcall _MmGetFileObjectForSection(PVOID Section)  
  3. {  
  4.     __asm  
  5.     {  
  6.         push ebp;  
  7.         mov  ebp, esp;  
  8.         mov  eax, dword ptr ss:[ebp + 0x08];  
  9.         mov  eax, dword ptr ds:[eax + 0x14];  
  10.         mov  eax, dword ptr ds:[eax];  
  11.         mov  eax, dword ptr ds:[eax + 0x24];  
  12.         mov  esp, ebp;  
  13.         pop  ebp;  
  14.         ret  0x04;  
  15.     }  
  16.         /*
  17.         kd> dt _section_object 0xe109e640
  18. nt!_SECTION_OBJECT
  19.    +0x000 StartingVa       : (null)
  20.    +0x004 EndingVa         : (null)
  21.    +0x008 Parent           : (null)
  22.    +0x00c LeftChild        : (null)
  23.    +0x010 RightChild       : (null)
  24.    +0x014 Segment          : 0xe10c14c0 _SEGMENT_OBJECT
  25. kd> dt _SEGMENT_OBJECT 0xe10c14c0
  26. nt!_SEGMENT_OBJECT
  27.    +0x000 BaseAddress      : 0x861f2348 Void
  28.    +0x004 TotalNumberOfPtes : 0xb1
  29.    +0x008 SizeOfSegment    : _LARGE_INTEGER 0xb1
  30.    +0x010 NonExtendedPtes  : 0xb1000
  31.    +0x014 ImageCommitment  : 0
  32.    +0x018 ControlArea      : 0xcbf13c3e _CONTROL_AREA
  33.    +0x01c Subsection       : (null)
  34.    +0x020 LargeControlArea : (null)
  35.    +0x024 MmSectionFlags   : (null)
  36.    +0x028 MmSubSectionFlags : 0x00400000 _MMSUBSECTION_FLAGS
  37. kd> dt _CONTROL_AREA 0x861f2348
  38. nt!_CONTROL_AREA
  39.    +0x000 Segment          : 0xe10c14c0 _SEGMENT
  40.    +0x004 DereferenceList  : _LIST_ENTRY [ 0x0 - 0x0 ]
  41.    +0x00c NumberOfSectionReferences : 1
  42.    +0x010 NumberOfPfnReferences : 0xa1
  43.    +0x014 NumberOfMappedViews : 1
  44.    +0x018 NumberOfSubsections : 5
  45.    +0x01a FlushInProgressCount : 0
  46.    +0x01c NumberOfUserReferences : 2
  47.    +0x020 u                : __unnamed
  48.    +0x024 FilePointer      : 0x8602caf8 _FILE_OBJECT
  49.    +0x028 WaitingForDeletion : (null)
  50.    +0x02c ModifiedWriteCount : 0
  51.    +0x02e NumberOfSystemCacheViews : 0
  52. kd> dt _FILE_OBJECT 0x8602caf8
  53. nt!_FILE_OBJECT
  54.    +0x000 Type             : 0n5
  55.    +0x002 Size             : 0n112
  56.    +0x004 DeviceObject     : 0x8632c030 _DEVICE_OBJECT
  57.    +0x008 Vpb              : 0x862443c8 _VPB
  58.    +0x00c FsContext        : 0xe1059aa0 Void
  59.    +0x010 FsContext2       : 0xe105b648 Void
  60.    +0x014 SectionObjectPointer : 0x85e16fa0 _SECTION_OBJECT_POINTERS
  61.    +0x018 PrivateCacheMap  : (null)
  62.    +0x01c FinalStatus      : 0n0
  63.    +0x020 RelatedFileObject : (null)
  64.    +0x024 LockOperation    : 0 ''
  65.    +0x025 DeletePending    : 0 ''
  66.    +0x026 ReadAccess       : 0x1 ''
  67.    +0x027 WriteAccess      : 0 ''
  68.    +0x028 DeleteAccess     : 0 ''
  69.    +0x029 SharedRead       : 0x1 ''
  70.    +0x02a SharedWrite      : 0 ''
  71.    +0x02b SharedDelete     : 0x1 ''
  72.    +0x02c Flags            : 0xc4042
  73.    +0x030 FileName         : _UNICODE_STRING "\Program Files\VMware\VMware Tools\TPAutoConnect.exe"
  74.    +0x038 CurrentByteOffset : _LARGE_INTEGER 0x0
  75.    +0x040 Waiters          : 0
  76.    +0x044 Busy             : 0
  77.    +0x048 LastLock         : (null)
  78.    +0x04c Lock             : _KEVENT
  79.    +0x05c Event            : _KEVENT
  80.    +0x06c CompletionContext : (null)
  81.         */
  82. }  
  83.   
  84. NTSTATUS PsReferenceProcessFilePointer(IN PEPROCESS Process, OUT PVOID *OutFileObject)  
  85. {  
  86.     PVOID SectionObject;  
  87.         //xp:
  88.         // +0x134 Job              : Ptr32 _EJOB
  89.         // +0x138 SectionObject    : Ptr32 Void
  90.     if (SectionObject = *(PVOID*)((PCHAR)Process + 0x138))  
  91.     {  
  92.         PFILE_OBJECT FileObject;  
  93.   
  94.         FileObject = _MmGetFileObjectForSection(SectionObject);  
  95.         *OutFileObject = FileObject;  
  96.         ObReferenceObject (FileObject);  
  97.         return STATUS_SUCCESS;  
  98.     }  
  99.     return STATUS_UNSUCCESSFUL;  
  100. }  
  101. PUNICODE_STRING PsGetProcessFullNameByHardCodeOfXP(PEPROCESS pTargetProcess)
  102. {
  103.         PFILE_OBJECT pFileObject=NULL;
  104.         POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
  105.                 if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
  106.                 return NULL;
  107.         if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
  108.                 return NULL;
  109.         return &(pObjectNameInfo->Name);//尚未释放内存
  110. }
复制代码
除了这个以外:还有一个

Process->SeAuditProcessCreationInfo.ImageFileName->Name


在WRK中可以看到
这说明从这个路径可能是不存在的
  1. NTSTATUS
  2. SeLocateProcessImageName(
  3.     __in PEPROCESS Process,
  4.     __deref_out PUNICODE_STRING *pImageFileName
  5.     )
  6. /*++
  7. Routine Description
  8.    
  9.     This routine returns the ImageFileName information from the process, if available.  This is a "lazy evaluation" wrapper
  10.     around SeInitializeProcessAuditName.  If the image file name information has already been computed, then this call simply
  11.     allocates and returns a UNICODE_STRING with this information.  Otherwise, the function determines the name, stores the name in the
  12.     EPROCESS structure, and then allocates and returns a UNICODE_STRING.  Caller must free the memory returned in pImageFileName.
  13.    
  14. Arguments
  15.     Process - process for which to acquire the name
  16.    
  17.     pImageFileName - output parameter to return name to caller
  18.    
  19. Return Value
  20.     NTSTATUS.
  21.    
  22. --*/
  23. {
  24.     NTSTATUS                 Status            = STATUS_SUCCESS;
  25.     PVOID                    FilePointer       = NULL;
  26.     PVOID                    PreviousValue     = NULL;
  27.     POBJECT_NAME_INFORMATION pProcessImageName = NULL;
  28.     PUNICODE_STRING          pTempUS           = NULL;
  29.     ULONG                    NameLength        = 0;
  30.     PAGED_CODE();
  31.     *pImageFileName = NULL;
  32.    
  33.     if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName) {
  34.         //
  35.         // The name has not been predetermined.  We must determine the process name.   First, reference the
  36.         // PFILE_OBJECT and lookup the name.  Then again check the process image name pointer against NULL.  
  37.         // Finally, set the name.
  38.         //
  39.         Status = PsReferenceProcessFilePointer( Process, &FilePointer );
  40.         
  41.         if (NT_SUCCESS(Status)) {
  42.             //
  43.             // Get the process name information.  
  44.             //
  45.             Status = SeInitializeProcessAuditName(
  46.                           FilePointer,
  47.                           TRUE, // skip audit policy
  48.                           &pProcessImageName // to be allocated in nonpaged pool
  49.                           );
  50.             if (NT_SUCCESS(Status)) {
  51.                 //
  52.                 // Only use the pProcessImageName if the field in the process is currently NULL.
  53.                 //
  54.                 PreviousValue = InterlockedCompareExchangePointer(
  55.                                     (PVOID *) &Process->SeAuditProcessCreationInfo.ImageFileName,
  56.                                     (PVOID) pProcessImageName,
  57.                                     (PVOID) NULL
  58.                                     );
  59.                
  60.                 if (NULL != PreviousValue) {
  61.                     ExFreePool(pProcessImageName); // free what we caused to be allocated.
  62.                 }
  63.             }
  64.             ObDereferenceObject( FilePointer );
  65.         }
  66.     }
  67.    
  68.    
  69.     if (NT_SUCCESS(Status)) {
  70.         
  71.         //
  72.         // Allocate space for a buffer to contain the name for returning to the caller.
  73.         //
  74.         NameLength = sizeof(UNICODE_STRING) + Process->SeAuditProcessCreationInfo.ImageFileName->Name.MaximumLength;
  75.         pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
  76.         if (NULL != pTempUS) {
  77.             RtlCopyMemory(
  78.                 pTempUS,
  79.                 &Process->SeAuditProcessCreationInfo.ImageFileName->Name,
  80.                 NameLength
  81.                 );
  82.             pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
  83.             *pImageFileName = pTempUS;
  84.         } else {
  85.             
  86.             Status = STATUS_NO_MEMORY;
  87.         }
  88.     }
  89.     return Status;
  90. }
复制代码
我自己实现了下 在win7 x86下效果还是可以的 不过使用了硬编码,推荐还是在NT5上使用(NT6很简单)

  1. PUNICODE_STRING GetSeLocateProcessImageName(PEPROCESS Process,PUNICODE_STRING *pImageFileName)
  2. {
  3.          POBJECT_NAME_INFORMATION pProcessImageName = NULL;
  4.          PUNICODE_STRING pTempUS = NULL;
  5.          ULONG NameLength = 0;
  6.          //Process->SeAuditProcessCreationInfo.ImageFileName->Name
  7.          //win7 x86 offset = 0x1ec
  8.          //if (NULL == Process->SeAuditProcessCreationInfo.ImageFileName)
  9.          pProcessImageName = (POBJECT_NAME_INFORMATION)(*(ULONG*)((ULONG)Process + 0x1ec));
  10.          if(pProcessImageName == NULL)
  11.          {
  12.                  DbgPrint("Process->SeAuditProcessCreationInfo.ImageFileName == NULL \n");
  13.                  return NULL;
  14.          }
  15.          else
  16.          {
  17.                  NameLength = sizeof(UNICODE_STRING) + pProcessImageName->Name.MaximumLength;
  18.                  pTempUS = ExAllocatePoolWithTag( NonPagedPool, NameLength, 'aPeS' );
  19.                  if (NULL != pTempUS) {
  20.             RtlCopyMemory(
  21.                 pTempUS,
  22.                                 &pProcessImageName->Name,
  23.                 NameLength
  24.                 );
  25.             pTempUS->Buffer = (PWSTR)(((PUCHAR) pTempUS) + sizeof(UNICODE_STRING));
  26.             *pImageFileName = pTempUS;
  27.                          DbgPrint("Path:%wZ\n",&pProcessImageName->Name);
  28.                          return *pImageFileName;
  29.                  }
  30.                  return NULL;
  31.          }
  32. }
复制代码



而NT6就很简单了
PsReferenceProcessFilePointe已经被导出了
那么直接使用
PsReferenceProcessFilePointe +IoQueryFileDosDeviceName就可以了
  1. PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
  2. {
  3.         PFILE_OBJECT pFileObject=NULL;
  4.         POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
  5.                 if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
  6.                 return NULL;
  7.         if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
  8.                 return NULL;
  9.         return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
  10. }
复制代码


除了这些以前还有一些路径存在PEB里 如果在x64的系统中 还得看是PEB32还是PEB64 虽然可以使用PsGetProcessWow64Process来判断是不是64进程
但这些数据在r3就可以直接被修改了 所以不太建议使用
PEB-&gtrocessParameters->ImagePathName
PEB-&gtrocessParameters->CommandLine
PEB-&gtrocessParameters->WindowTitle
PEB->Ldr->InLoadOrderLinks->FullDllName
PEB->Ldr->InMemoryOrderLinks->FullDllName


大家看看黑客防线里面的《伪造进程初探》和获取进程完整路径方法小结.pdf
另外一个博主写的也是不错的
42969803 //EPROCESS取进程全路径
43638651 //EPROCESS取进程全路径(xp)
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-29 03:39

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表