驱动层得到进程的完整路径

   在得到进程EProcess之后,对于进程完整路径的获得一般有两种方法,一种是访问的进程的PEB结构,在PEB结构中保存有进程的完整路径,另一种方法就是采用访问_FILE_OBJECT的方法。

  访问PEB的方法便存在线程靠挂的问题,因为运行于Ring0层的线程是无法去访问用户地址空间的,需要将线程暂时靠挂到目标呢进程,进而去访问进程的PEB结构。我一般都采用的访问_FILE_OBJECT的方法,避免了线程的靠挂问题,而且访问peb的方法会存在一个问题:如果想要进行进程拦截,在进程未启动之前就阻止进程的启动,此时进程空间还未开辟,peb结构都不存在,只能去访问exe文件在ring0层的文件对象,通过文件对象来获得进程的完整路径。

  进程靠挂函数原型

1 VOID KeStackAttachProcess (

2     PKPROCESS  Process,

3     PRKAPC_STATE  ApcState

4     );

访问目标进程的用户地址空间之后返回ring0运行调用函数

VOID KeUnstackDetachProcess(

   PRKAPC_STATE  ApcState

    );

kd> dt _eprocess

+0x1b0 Peb              : Ptr32 _PEB    //X86 Peb在EProcess中的偏移量

kd> dt _peb

+0x00c Ldr              : Ptr32 _PEB_LDR_DATA        ;进程加载的模块链表

关于进程加载模块链表是有三条链表

InLoadOrderModuleList    //模块的加载顺序

InMemoryOrderModuleList   // 模块在内存中的顺序

InInitializationOrderModuleList   // 模块的初始化顺序

进程的第一模块就是exe文件,对于exe的路径就是取InLoadOrderModuleList 中的第一模块的FullDllName。

 

第二种方法,用_FILE_OBJECT 的方法

以下为Windbg的调试过程,在虚拟机中打开calc.exe然后获得calc.exe的完整路径

Win7 X64

1 kd> !process 0 0

2 

3 PROCESS fffffa801a619b30

4     SessionId: 1  Cid: 0b10    Peb: 7fffffd6000  ParentCid: 05fc

5     DirBase: 5f017000  ObjectTable: fffff8a00296ac00  HandleCount:  79.

6     Image: calc.exe

kd> dt _eprocess fffffa801a619b30

+0x268 SectionObject    : 0xfffff8a0`01ba1f30 Void


kd> dt _section_object 0xfffff8a0`01ba1f30
nt!_SECTION_OBJECT
+0x000 StartingVa : (null)
+0x008 EndingVa : 0xfffff880`03bd4ba8 Void
+0x010 Parent : 0xfffff880`03bd4b90 Void
+0x018 LeftChild : (null)
+0x020 RightChild : 0xfffffa80`19e84300 Void
+0x028 Segment : 0xfffff8a0`01b19850 _SEGMENT_OBJECT


  

kd> dt _segment 0xfffff8a0`01b19850
nt!_SEGMENT
+0x000 ControlArea : 0xfffffa80`1a687d30 _CONTROL_AREA
+0x008 TotalNumberOfPtes : 0xe3
+0x00c SegmentFlags : _SEGMENT_FLAGS
+0x010 NumberOfCommittedPages : 0
+0x018 SizeOfSegment : 0xe3000
+0x020 ExtendInfo : 0x00000000`ffbf0000 _MMEXTEND_INFO
+0x020 BasedAddress : 0x00000000`ffbf0000 Void
+0x028 SegmentLock : _EX_PUSH_LOCK
+0x030 u1 : <unnamed-tag>
+0x038 u2 : <unnamed-tag>
+0x040 PrototypePte : 0xfffff8a0`01b19898 _MMPTE
+0x048 ThePtes : [1] _MMPTE

 

kd> dt _CONTROL_AREA 0xfffffa80`1a687d30
nt!_CONTROL_AREA
+0x000 Segment : 0xfffff8a0`01b19850 _SEGMENT
+0x008 DereferenceList : _LIST_ENTRY [ 0x00000000`00000000 - 0xfffffa80`1a8a1018 ]
+0x018 NumberOfSectionReferences : 1
+0x020 NumberOfPfnReferences : 0x97
+0x028 NumberOfMappedViews : 1
+0x030 NumberOfUserReferences : 2
+0x038 u : <unnamed-tag>
+0x03c FlushInProgressCount : 0
+0x040 FilePointer : _EX_FAST_REF       //与X86的不同,X86下FilePointer的类型为_FILE_OBJECT,X64加了一层封装

 

kd> dt _EX_FAST_REF 0xfffffa80`1a687d30+0x040
nt!_EX_FAST_REF
+0x000 Object : 0xfffffa80`1a685073 Void         //真正的_FILE_OBJECT 最后一位要进行清0操作,  文件对象的最后一位必然为0
+0x000 RefCnt : 0y0011
+0x000 Value : 0xfffffa80`1a685073

 

 

kd> dt _File_object 0xfffffa80`1a685070 //_File_Object 最后一位清0
nt!_FILE_OBJECT
+0x000 Type : 0n5
+0x002 Size : 0n216
+0x008 DeviceObject : 0xfffffa80`19376530 _DEVICE_OBJECT
+0x010 Vpb : 0xfffffa80`19376470 _VPB
+0x018 FsContext : 0xfffff8a0`000f5140 Void
+0x020 FsContext2 : 0xfffff8a0`019715d0 Void
+0x028 SectionObjectPointer : 0xfffffa80`19e5ec88 _SECTION_OBJECT_POINTERS
+0x030 PrivateCacheMap : (null)
+0x038 FinalStatus : 0n0
+0x040 RelatedFileObject : (null)
+0x048 LockOperation : 0 ''
+0x049 DeletePending : 0 ''
+0x04a ReadAccess : 0x1 ''
+0x04b WriteAccess : 0 ''
+0x04c DeleteAccess : 0 ''
+0x04d SharedRead : 0x1 ''
+0x04e SharedWrite : 0 ''
+0x04f SharedDelete : 0x1 ''
+0x050 Flags : 0x44042
+0x058 FileName : _UNICODE_STRING "\Windows\System32\calc.exe"                                    //完整路径
+0x068 CurrentByteOffset : _LARGE_INTEGER 0x0
+0x070 Waiters : 0
+0x074 Busy : 0
+0x078 LastLock : (null)
+0x080 Lock : _KEVENT
+0x098 Event : _KEVENT
+0x0b0 CompletionContext : (null)
+0x0b8 IrpListLock : 0
+0x0c0 IrpList : _LIST_ENTRY [ 0xfffffa80`1a685130 - 0xfffffa80`1a685130 ]
+0x0d0 FileObjectExtension : (null)

 

 

 

 

 

 

WinXP X86

kd> !process 0 0

PROCESS 8971d6f8 SessionId: 0 Cid: 0378 Peb: 7ffdc000 ParentCid: 0664
DirBase: 0f8c02a0 ObjectTable: e23027a8 HandleCount: 44.
Image: calc.exe


kd> dt _eprocess 8971d6f8

+0x138 SectionObject : 0xe22963d0 Void


kd> dt _section_object 0xe22963d0
nt!_SECTION_OBJECT
+0x000 StartingVa : (null)
+0x004 EndingVa : (null)
+0x008 Parent : (null)
+0x00c LeftChild : (null)
+0x010 RightChild : (null)
+0x014 Segment : 0xe18e4820 _SEGMENT_OBJECT

kd> dt _segment 0xe18e4820
nt!_SEGMENT
+0x000 ControlArea : 0x89769478 _CONTROL_AREA
+0x004 TotalNumberOfPtes : 0x1f
+0x008 NonExtendedPtes : 0x1f
+0x00c WritableUserReferences : 0
+0x010 SizeOfSegment : 0x1f000
+0x018 SegmentPteTemplate : _MMPTE
+0x020 NumberOfCommittedPages : 0
+0x024 ExtendInfo : (null)
+0x028 SystemImageBase : (null)
+0x02c BasedAddress : 0x01000000 Void
+0x030 u1 : __unnamed
+0x034 u2 : __unnamed
+0x038 PrototypePte : 0xe18e4860 _MMPTE
+0x040 ThePtes : [1] _MMPTE


kd> dt _CONTROL_AREA 0x89769478
nt!_CONTROL_AREA
+0x000 Segment : 0xe18e4820 _SEGMENT
+0x004 DereferenceList : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x00c NumberOfSectionReferences : 1
+0x010 NumberOfPfnReferences : 0x1d
+0x014 NumberOfMappedViews : 1
+0x018 NumberOfSubsections : 4
+0x01a FlushInProgressCount : 0
+0x01c NumberOfUserReferences : 2
+0x020 u : __unnamed
+0x024 FilePointer : 0x8958a9b0 _FILE_OBJECT
+0x028 WaitingForDeletion : (null)
+0x02c ModifiedWriteCount : 0
+0x02e NumberOfSystemCacheViews : 0


kd> dt _FILE_OBJECT 0x8958a9b0
nt!_FILE_OBJECT
+0x000 Type : 0n5
+0x002 Size : 0n112
+0x004 DeviceObject : 0x899ab900 _DEVICE_OBJECT
+0x008 Vpb : 0x8994c1d8 _VPB                               //卷参数块,由此得到所属卷设备,即盘符
+0x00c FsContext : 0xe228f710 Void
+0x010 FsContext2 : 0xe1f5ea90 Void
+0x014 SectionObjectPointer : 0x894bbbe4 _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 : 0x44042
+0x030 FileName : _UNICODE_STRING "\WINDOWS\system32\calc.exe"                            //完整路径
+0x038 CurrentByteOffset : _LARGE_INTEGER 0x0
+0x040 Waiters : 0
+0x044 Busy : 0
+0x048 LastLock : (null)
+0x04c Lock : _KEVENT
+0x05c Event : _KEVENT
+0x06c CompletionContext : (null)

 结构体的定义

ypedef struct _CONTROL_AREA64

{

    PVOID64 Segment;

    PVOID64 p1;

    PVOID64 p2;

    ULONG64 NumberOfSectionReferences;

    ULONG64 NumberOfPfnReferences;

    ULONG64 NumberOfMappedViews;

    ULONG64 NumberOfUserReferences;

    union

    {

        ULONG LongFlags;

        ULONG Flags;

    } u;

    PVOID64 FilePointer;

} CONTROL_AREA64, *PCONTROL_AREA64;



typedef struct _CONTROL_AREA

{

    PVOID Segment;

    LIST_ENTRY DereferenceList;

    ULONG NumberOfSectionReferences;

    ULONG NumberOfPfnReferences;

    ULONG NumberOfMappedViews;

    ULONG NumberOfSystemCacheViews;

    ULONG NumberOfUserReferences;

    union

    {

        ULONG LongFlags;

        ULONG Flags;

    } u;

    PFILE_OBJECT FilePointer;

} CONTROL_AREA, *PCONTROL_AREA;





typedef struct _SEGMENT64

{

    PVOID64 ControlArea;

    ULONG TotalNumberOfPtes;

    ULONG NonExtendedPtes;

    ULONG Spare0;

}SEGMENT64,*PSEGMENT64;



typedef struct _SEGMENT

{

    struct _CONTROL_AREA *ControlArea;

    ULONG TotalNumberOfPtes;

    ULONG NonExtendedPtes;

    ULONG Spare0;

} SEGMENT, *PSEGMENT;





typedef struct _SECTION_OBJECT

{

    PVOID StartingVa;

    PVOID EndingVa;

    PVOID Parent;

    PVOID LeftChild;

    PVOID RightChild;

    PSEGMENT Segment;

} SECTION_OBJECT, *PSECTION_OBJECT;





typedef struct _SECTION_OBJECT64

{

    PVOID64 StartingVa;

    PVOID64 EndingVa;

    PVOID64 Parent;

    PVOID64 LeftChild;

    PVOID64 RightChild;

    PVOID64 Segment;

} SECTION_OBJECT64, *PSECTION_OBJECT64;

 

 

BOOLEAN

GetProcessPathBySectionObject(ULONG_PTR ulProcessID,WCHAR* wzProcessPath)

{

    PEPROCESS         EProcess = NULL;

    PSECTION_OBJECT   SectionObject   = NULL;

    PSECTION_OBJECT64 SectionObject64 = NULL;

    PSEGMENT        Segment   = NULL;

    PSEGMENT64      Segment64 = NULL;

    PCONTROL_AREA   ControlArea = NULL;

    PCONTROL_AREA64 ControlArea64 = NULL;

    PFILE_OBJECT    FileObject  = NULL;

    BOOLEAN         bGetPath = FALSE;



    if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ulProcessID, &EProcess)))

    {



        switch(WinVersion)

        {

        case WINDOWS_XP:   //x86 XP sp3

            {

                SectionObjectOfEProcess  = 0x138;

                if (SectionObjectOfEProcess!=0&&MmIsAddressValid((PVOID)((ULONG_PTR)EProcess + SectionObjectOfEProcess)))

                {

                    SectionObject = *(PSECTION_OBJECT*)((ULONG_PTR)EProcess + SectionObjectOfEProcess);

                    if (SectionObject && MmIsAddressValid(SectionObject))

                    {

                        Segment = (PSEGMENT)SectionObject->Segment;

                        if (Segment && MmIsAddressValid(Segment))

                        {

                            ControlArea = Segment->ControlArea;

                            if (ControlArea && MmIsAddressValid(ControlArea))

                            {

                                FileObject = ControlArea->FilePointer;

                                if (FileObject&&MmIsAddressValid(FileObject))

                                {

                                    bGetPath = GetPathByFileObject(FileObject, wzProcessPath);

                                    if (!bGetPath)

                                    {

                                        DbgPrint("SectionObject: 0x%08X, FileObject: 0x%08X\n", SectionObject, FileObject);

                                    }

                                }

                            }

                        }

                    }

                }

                break;

            }



        case WINDOWS_7:  //Win 7 x64 sp1

            {    

                SectionObjectOfEProcess = 0x268;           

                if (SectionObjectOfEProcess!=0&&MmIsAddressValid((PVOID)((ULONG_PTR)EProcess + SectionObjectOfEProcess)))

                {

                    SectionObject64 = *(PSECTION_OBJECT64*)((ULONG_PTR)EProcess + SectionObjectOfEProcess);

                    if (SectionObject64 && MmIsAddressValid(SectionObject64))

                    {



                        Segment64 = (PSEGMENT64)(SectionObject64->Segment);

                        if (Segment64 && MmIsAddressValid(Segment64))

                        {

                            ControlArea64 = (PCONTROL_AREA64)Segment64->ControlArea;

                            if (ControlArea64 && MmIsAddressValid(ControlArea64))

                            {

                                FileObject = (PFILE_OBJECT)ControlArea64->FilePointer;

                                if (FileObject&&MmIsAddressValid(FileObject))

                                {

                                    FileObject = (PFILE_OBJECT)((ULONG_PTR)FileObject & 0xFFFFFFFFFFFFFFF0);

                                    bGetPath = GetPathByFileObject(FileObject, wzProcessPath);

                                    if (!bGetPath)

                                    {

                                        DbgPrint("SectionObject: 0x%08X, FileObject: 0x%08X\n", SectionObject, FileObject);

                                    }

                                }

                            }

                        }

                    }

                }

                break;

            }

        }        

    }

    if (bGetPath==FALSE)

    {

        wcscpy(wzProcessPath,L"Unknow");

    }



    return bGetPath;    



}

 

获得文件对象以后,获得完整的路径

//传入文件对象,返回完整路径

  1 BOOLEAN GetPathByFileObject(PFILE_OBJECT FileObject, WCHAR* wzPath)

  2 {

  3     BOOLEAN bGetPath = FALSE;

  4     CHAR szIoQueryFileDosDeviceName[] = "IoQueryFileDosDeviceName";

  5     CHAR szIoVolumeDeviceToDosName[] = "IoVolumeDeviceToDosName";

  6     CHAR szRtlVolumeDeviceToDosName[] = "RtlVolumeDeviceToDosName";

  7 

  8     POBJECT_NAME_INFORMATION ObjectNameInformation = NULL;

  9     __try

 10     {

 11         if (FileObject && MmIsAddressValid(FileObject) && wzPath)

 12         {

 13         

 14             if (NT_SUCCESS(IoQueryFileDosDeviceName(FileObject,&ObjectNameInformation)))   //注意该函数调用后要释放内存

 15             {

 16                 wcsncpy(wzPath,ObjectNameInformation->Name.Buffer,ObjectNameInformation->Name.Length);

 17 

 18                 bGetPath = TRUE;

 19 

 20                 ExFreePool(ObjectNameInformation);

 21             }

 22             

 23             

 24             if (!bGetPath)

 25             {

 26             

 27                 if (IoVolumeDeviceToDosName||RtlVolumeDeviceToDosName)

 28                 {

 29                     NTSTATUS  Status = STATUS_UNSUCCESSFUL;

 30                     ULONG_PTR ulRet= 0;

 31                     PVOID     Buffer = ExAllocatePool(PagedPool,0x1000);

 32 

 33                     if (Buffer)

 34                     {

 35                         // ObQueryNameString : \Device\HarddiskVolume1\Program Files\VMware\VMware Tools\VMwareTray.exe

 36                         memset(Buffer, 0, 0x1000);

 37                         Status = ObQueryNameString(FileObject, (POBJECT_NAME_INFORMATION)Buffer, 0x1000, &ulRet);

 38                         if (NT_SUCCESS(Status))

 39                         {

 40                             POBJECT_NAME_INFORMATION Temp = (POBJECT_NAME_INFORMATION)Buffer;

 41                         

 42                             WCHAR szHarddiskVolume[100] = L"\\Device\\HarddiskVolume";

 43 

 44                             if (Temp->Name.Buffer!=NULL)

 45                             {

 46                                 if (Temp->Name.Length / sizeof(WCHAR) > wcslen(szHarddiskVolume) &&

 47                                     !_wcsnicmp(Temp->Name.Buffer, szHarddiskVolume, wcslen(szHarddiskVolume)))

 48                                 {

 49                                     // 如果是以 "\\Device\\HarddiskVolume" 这样的形式存在的,那么再查询其卷名。

 50                                     UNICODE_STRING uniDosName;

 51 

 52                                     if (NT_SUCCESS(IoVolumeDeviceToDosName(FileObject->DeviceObject, &uniDosName)))

 53                                     {

 54                                         if (uniDosName.Buffer!=NULL)

 55                                         {

 56                                         

 57                                             wcsncpy(wzPath, uniDosName.Buffer, uniDosName.Length);

 58                                             wcsncat(wzPath, Temp->Name.Buffer + wcslen(szHarddiskVolume) + 1, Temp->Name.Length - (wcslen(szHarddiskVolume) + 1));

 59                                             bGetPath = TRUE;

 60                                         }    

 61 

 62                                         ExFreePool(uniDosName.Buffer);

 63                                     }

 64 

 65                                     else if (NT_SUCCESS(RtlVolumeDeviceToDosName(FileObject->DeviceObject, &uniDosName)))

 66                                     {

 67                                         if (uniDosName.Buffer!=NULL)

 68                                         {

 69 

 70                                             wcsncpy(wzPath, uniDosName.Buffer, uniDosName.Length);

 71                                             wcsncat(wzPath, Temp->Name.Buffer + wcslen(szHarddiskVolume) + 1, Temp->Name.Length - (wcslen(szHarddiskVolume) + 1));

 72                                             bGetPath = TRUE;

 73                                         }    

 74 

 75                                         ExFreePool(uniDosName.Buffer);

 76                                     }

 77                                     

 78                                 }

 79                                 else

 80                                 {

 81                                     // 如果不是以 "\\Device\\HarddiskVolume" 这样的形式开头的,那么直接复制名称。

 82                                     

 83                                     wcsncpy(wzPath, Temp->Name.Buffer, Temp->Name.Length);

 84                                     bGetPath = TRUE;

 85                                 }

 86                             }

 87                         }

 88 

 89                         ExFreePool(Buffer);

 90                     }

 91                 }

 92             }

 93         }

 94     }

 95     __except(1)

 96     {

 97         DbgPrint("GetPathByFileObject Catch __Except\r\n");

 98         bGetPath = FALSE;

 99     }

100 

101     return bGetPath;

102 }

 

你可能感兴趣的:(进程)