驱动层得到进程的完整路径
在得到进程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
|
1
|
<br>kd> dt _eprocess fffffa801a619b30<br><br>+0x268 SectionObject : 0xfffff8a0`01ba1f30 Void<br><br><br> |
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
|
1
|
<br> |
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 }


浙公网安备 33010602011771号