Hook NtMapViewOfSection 获取加载模块的全路径
实际使用中,LoadImageNotifyRoutine得到加载模块的路径是不包含盘符的;
原因很清楚,IDA ntoskrnl NtMapViewOfSection,可以看到最后调用NotifyRoutine时,仅仅是使用PFILE_OBJECT->FileName作为参数,PFILE_OBJECT->FileName是不包含盘符的,盘符需要从PFILE_OBJECT->DeviceObject来拿。
这个获取路径是:SectionHandle->SectionObject->ControlArea->FileObject;
需要注意的是,ControlArea里有个Flags,
if (g_vOSVer <= OS_2003)
Flags = *(PULONG)(pControlArea + 32);
else
Flags = *(PULONG)(pControlArea + 28);
if ( Flags & 0x400 || !(Flags & 0x20) )
这种不是加载image,需要忽略。
当 (g_vOSVer > OS_2003) 时,ControlArea->FileObject位置没变,但内容有所变化,实际就是低3bits变成了引用计数,需要
pFileObject = (PFILE_OBJECT)((ULONG)pFileObject & 0xFFFFFFF8);
通过PFILE_OBJECT->DeviceObject获取盘符,也有好几种办法,貌似有ZwCreateFile X:来比较;
也有
status=ZwOpenSymbolicLinkObject(&hLink,
GENERIC_READ,
&VolumeOA);
status=ZwQuerySymbolicLinkObject(hLink,
&usLinkObject,
&Retlen);
来获取的。
此外还有IoVolumeDeviceToDosName(pFileObject->DeviceObject, &dosName)来获取。
IoVolumeDeviceToDosName实际是往L"\\Device\\MountPointManager"发送请求来得到盘符。
PFILE_OBJECT->DeviceObject应该是卷设备,可以在windbg里!object 0xXXXXXXXX来看它的名字,
比如C:实际对应HarddiskVolume1,用DeviceTree可以看到设备之间的关系。
Win7 x64:
微软不按套路来,在SectionObject->Segment 本来是 _SEGMENT_OBJECT 结构,结果填了一个 _Segment 结构指针。
typedef union _D_EX_FAST_REF {
PVOID object; // +0x000 Object : Ptr64 Void
ULONG64 RefCnt : 4; // +0x000 RefCnt : Pos 0, 4 Bits
ULONG64 Value; // +0x000 Value : Uint8B
} D_EX_FAST_REF, *PD_EX_FAST_REF;
typedef struct _D_CONTROL_AREA {
PVOID Segment; // +0x000 Segment : Ptr64 _SEGMENT
LIST_ENTRY DereferenceList; // +0x008 DereferenceList : _LIST_ENTRY
ULONG_PTR NumberOfSectionReferences; // +0x018 NumberOfSectionReferences : Uint8B
ULONG_PTR NumberOfPfnReferences; // +0x020 NumberOfPfnReferences : Uint8B
ULONG_PTR NumberOfMappedView; // +0x028 NumberOfMappedViews : Uint8B
ULONG_PTR NumberOfUserReferences; // +0x030 NumberOfUserReferences : Uint8B
ULONG u; // +0x038 u : <unnamed-tag>
ULONG FlushInProgressCount; // +0x03c FlushInProgressCount : Uint4B
D_EX_FAST_REF FilePointer; // +0x040 FilePointer : _EX_FAST_REF
LONG ControlAreaLock; // +0x048 ControlAreaLock : Int4B
ULONG ModifiedWriteCount; // +0x04c ModifiedWriteCount : Uint4B
ULONG StartingFrame; // +0x04c StartingFrame : Uint4B
PVOID WaitingForDeletion; // +0x050 WaitingForDeletion : Ptr64 _MI_SECTION_CREATION_GATE
ULONG64 u2[2]; // +0x058 u2 : <unnamed-tag>
LONG64 LockedPage; // +0x068 LockedPages : Int8B
LIST_ENTRY ViewList; // +0x070 ViewList : _LIST_ENTRY
} D_CONTROL_AREA, *PD_CONTROL_AREA;
typedef struct _D_SEGMENT_OBJECT {
PVOID BaseAddress; // +0x000 BaseAddress : Ptr64 Void
ULONG TotalNumberOfPte; // +0x008 TotalNumberOfPtes : Uint4B
LARGE_INTEGER SizeOfSegment; // +0x010 SizeOfSegment : _LARGE_INTEGER
ULONG NonExtendedPtes; // +0x018 NonExtendedPtes : Uint4B
ULONG ImageCommitment; // +0x01c ImageCommitment : Uint4B
PVOID ControlArea; // +0x020 ControlArea : Ptr64 _CONTROL_AREA
PVOID Subsection; // +0x028 Subsection : Ptr64 _SUBSECTION
PVOID MmSectionFlags; // +0x030 MmSectionFlags : Ptr64 _MMSECTION_FLAGS
PVOID MmSubSectionFlags; // +0x038 MmSubSectionFlags : Ptr64 _MMSUBSECTION_FLAGS
} D_SEGMENT_OBJECT, *PD_SEGMENT_OBJECT;
typedef struct _D_SECTION_OBJECT {
PVOID StartingVa;
PVOID EndingVa;
PVOID Parent;
PVOID LeftChild;
PVOID RightChild;
PD_SEGMENT_OBJECT Segment;
} D_SECTION_OBJECT, *PD_SECTION_OBJECT;
PD_CONTROL_AREA pControlArea =
*(PD_CONTROL_AREA *)(((PD_SECTION_OBJECT)pSectionObject)->Segment);
if ( !MmIsAddressValid(pControlArea) )
{
goto L_Error;
}
// MM_PhysicalMemory = 0x400
// MM_Image = 0x20
ULONG Flags = pControlArea->u;
if ( (Flags & 0x400) || !(Flags & 0x20) ) // 这种不是加载image
{
goto L_Error;
}
pFileObject = (PFILE_OBJECT)pControlArea->FilePointer.object;
pFileObject = (PFILE_OBJECT)((ULONG_PTR)pFileObject & 0xFFFFFFFFFFFFFFF0);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!