当前位置: 首页 > news >正文

nt!MiDispatchFault函数分析之nt!MiCompleteProtoPteFault函数的作用

nt!MiDispatchFault函数分析之nt!MiCompleteProtoPteFault函数的作用


第一部分:

       //
        // PTE is still in transition state, same protection, etc.
        //

        ASSERT (Pfn1->u4.InPageError == 0);

        if (Pfn1->u2.ShareCount == 0) {
            MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9);
        }

        Pfn1->u2.ShareCount += 1;
        Pfn1->u3.e1.PageLocation = ActiveAndValid;
        Pfn1->u3.e1.CacheAttribute = MiCached;

        MI_MAKE_TRANSITION_PTE_VALID (TempPte, ReadPte);
        if (StoreInstruction && TempPte.u.Hard.Write) {
            MI_SET_PTE_DIRTY (TempPte);
        }
        MI_WRITE_VALID_PTE (ReadPte, TempPte);

        if (PointerProtoPte != NULL) {

            //
            // The prototype PTE has been made valid, now make the
            // original PTE valid.  The original PTE must still be invalid
            // otherwise MiWaitForInPageComplete would have returned
            // a collision status.
            //

            ASSERT (PointerPte->u.Hard.Valid == 0);

            //
            // PTE is not valid, continue with operation.
            //

            status = MiCompleteProtoPteFault (StoreInstruction,
                                              VirtualAddress,
                                              PointerPte,
                                              PointerProtoPte,
                                              OldIrql,
                                              &LockedProtoPfn);


第二部分:

        //
        // This is the thread which owns the event, clear the event field
        // in the PFN database.
        //

        Pfn1 = ReadBlock->Pfn;
        Page = &ReadBlock->Page[0];
        NumberOfBytes = (LONG)ReadBlock->Mdl.ByteCount;
        CheckPte = ReadBlock->BasePte;

dv
             ReadPte = 0xe1009c00
           ReadBlock = 0x8962de10

1: kd> dx -r1 ((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10)
((ntkrnlmp!_MMINPAGE_SUPPORT *)0x8962de10)                 : 0x8962de10 [Type: _MMINPAGE_SUPPORT *]
    [+0x000] Event            [Type: _KEVENT]
    [+0x010] IoStatus         [Type: _IO_STATUS_BLOCK]
    [+0x018] ReadOffset       : {0} [Type: _LARGE_INTEGER]
    [+0x020] WaitCount        : 1 [Type: long]
    [+0x024] Thread           : 0x8999d020 [Type: _ETHREAD *]
    [+0x028] FilePointer      : 0x899abb00 [Type: _FILE_OBJECT *]
    [+0x02c] BasePte          : 0xe1009c00 [Type: _MMPTE *]
    [+0x030] Pfn              : 0x810f1650 [Type: _MMPFN *]
    [+0x034] u1               [Type: __unnamed]
    [+0x038] Mdl              [Type: _MDL]
    [+0x054] Page             [Type: unsigned long [16]]
    [+0x094] ListEntry        [Type: _SINGLE_LIST_ENTRY]
1: kd> dx -r1 (*((ntkrnlmp!_MDL *)0x8962de48))
(*((ntkrnlmp!_MDL *)0x8962de48))                 [Type: _MDL]
    [+0x000] Next             : 0x0 [Type: _MDL *]
    [+0x004] Size             : 32 [Type: short]
    [+0x006] MdlFlags         : 66 [Type: short]
    [+0x008] Process          : 0x20202020 [Type: _EPROCESS *]
    [+0x00c] MappedSystemVa   : 0x80402020 [Type: void *]
    [+0x010] StartVa          : 0x2700000 [Type: void *]
    [+0x014] ByteCount        : 0x1000 [Type: unsigned long]
    [+0x018] ByteOffset       : 0x0 [Type: unsigned long]
1: kd> dx -r1 (*((ntkrnlmp!unsigned long (*)[16])0x8962de64))
(*((ntkrnlmp!unsigned long (*)[16])0x8962de64))                 [Type: unsigned long [16]]
    [0]              : 0xa0ee [Type: unsigned long]


dv

             ReadPte = 0xe1009c00
      IoCompleteTime = {0}
        ProtoProtect = struct _MMWSLE
             PfnHeld = 0
    StoreInstruction = 0
               Flags = 0xc1080000
             OldIrql = 0x01 ''
            CheckPte = 0xe1009c00

                Page = 0x8962de64
1: kd> dx -r1 ((ntkrnlmp!unsigned long *)0x8962de64)
((ntkrnlmp!unsigned long *)0x8962de64)                 : 0x8962de64 : 0xa0ee [Type: unsigned long *]
    0xa0ee [Type: unsigned long]


1: kd>  dd 0xe1009c00
e1009c00  0a0ee8c0 fcf194c6 fcf194c6 fcf194c6
e1009c10  fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c20  fcf194c6 fcf194c6 fcf194c6 fcf194c6

            else {
                PageFrameIndex = *Page;
                MI_SNAP_DATA (MI_PFN_ELEMENT (PageFrameIndex),
                              MI_PFN_ELEMENT (PageFrameIndex)->PteAddress,
                              0xC);
            }


#define MI_SNAP_DATA(_Pfn, _Pte, _CallerId) MiSnapData(_Pfn, _Pte, _CallerId)

            CheckPte += 1;
            Page += 1;
            NumberOfBytes -= PAGE_SIZE;


第三部分:

        //
        // PTE is still in transition state, same protection, etc.
        //

        ASSERT (Pfn1->u4.InPageError == 0);

        if (Pfn1->u2.ShareCount == 0) {
            MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 9);
        }

        Pfn1->u2.ShareCount += 1;
        Pfn1->u3.e1.PageLocation = ActiveAndValid;
        Pfn1->u3.e1.CacheAttribute = MiCached;

        MI_MAKE_TRANSITION_PTE_VALID (TempPte, ReadPte);


dv
                Pfn1 = 0x810f1650

第四部分:

1: kd> dd 810f1650
810f1650  00000000 e1009c00 00000000 00011008
810f1660  fcf194c6 2000a1cd

        Pfn1->u2.ShareCount += 1;
        Pfn1->u3.e1.PageLocation = ActiveAndValid;
        Pfn1->u3.e1.CacheAttribute = MiCached;

1: kd> dd 810f1650
810f1650  00000000 e1009c00 00000001 00011608
810f1660  fcf194c6 0000a1cd


第五部分:修改 e1009c00 ,先构造一个TempPte


        MI_MAKE_TRANSITION_PTE_VALID (TempPte, ReadPte);    //关键代码1:构造TempPte=0a0ee921


#define MI_MAKE_TRANSITION_PTE_VALID(OUTPTE,PPTE)                             \
        ASSERT (((PPTE)->u.Hard.Valid == 0) &&                                \
                ((PPTE)->u.Trans.Prototype == 0) &&                           \
                ((PPTE)->u.Trans.Transition == 1));                           \
               (OUTPTE).u.Long = (((PPTE)->u.Long & ~0xFFF) |                 \
                         (MmProtectToPteMask[(PPTE)->u.Trans.Protection]) |   \
                          MiDetermineUserGlobalPteMask ((PMMPTE)PPTE));


1: kd> p
nt!MiDispatchFault+0x29fa:
80a93016 e88fc30300      call    nt!MiDetermineUserGlobalPteMask (80acf3aa)
1: kd> p
nt!MiDispatchFault+0x29ff:
80a9301b 8bd8            mov     ebx,eax
1: kd> r
eax=00000121


1: kd> p
nt!MiDispatchFault+0x2a19:
80a93035 0bd8            or      ebx,eax
1: kd> r
eax=0a0ee000 ebx=00000921

第六部分:修改 e1009c00 ,使用TempPte

        MI_WRITE_VALID_PTE (ReadPte, TempPte);        0a0ee921        //关键代码2:赋值给ReadPte


1: kd> p
nt!MiDispatchFault+0x2b32:
80a9314e 8918            mov     dword ptr [eax],ebx
1: kd> r
eax=e1009c00 ebx=0a0ee921


1: kd> dd e1009c00
e1009c00  0a0ee921 fcf194c6 fcf194c6 fcf194c6
e1009c10  fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c20  fcf194c6 fcf194c6 fcf194c6 fcf194c6
e1009c30  fcf194c6 fcf194c6 fcf194c6 fcf194c6


第七部分:现在还是无效的not valid,需要修改C0304200


1: kd> !pte c1080000
                 VA c1080000
PDE at C0300C10         PTE at C0304200
contains 0A03F963       contains 00027400
pfn a03f  -G-DA--KWEV   not valid
                         Proto: E1009C00

1: kd> dd 0xc0304200
c0304200  00027400 00027402 00027404 00027406
c0304210  00027408 0002740a 0002740c 0002740e
c0304220  00027410 00027412 00027414 00027416
c0304230  00027418 0002741a 0002741c 0002741e


//关键代码3:改变    00027400

            //
            // PTE is not valid, continue with operation.
            //

            status = MiCompleteProtoPteFault (StoreInstruction,
                                              VirtualAddress,
                                              PointerPte,
                                              PointerProtoPte,
                                              OldIrql,
                                              &LockedProtoPfn);

第八部分:

1: kd> p
nt!MiDispatchFault+0x2b64:
80a93180 e8df4fffff      call    nt!MiCompleteProtoPteFault (80a88164)
1: kd> t
nt!MiCompleteProtoPteFault:
80a88164 55              push    ebp
1: kd> kc
 #
00 nt!MiCompleteProtoPteFault
01 nt!MiDispatchFault
02 nt!MmAccessFault
03 nt!_KiTrap0E
04 nt!CcMapData
05 Ntfs!NtfsMapStream
06 Ntfs!NtfsReadBootSector
07 Ntfs!NtfsMountVolume
08 Ntfs!NtfsCommonFileSystemControl
09 Ntfs!NtfsFspDispatch
0a nt!ExpWorkerThread
0b nt!PspSystemThreadStartup
0c nt!KiThreadStartup
1: kd> dv
StoreInstruction = 0
 FaultingAddress = 0xc1080000
      PointerPte = 0xc0304200
 PointerProtoPte = 0xe1009c00
         OldIrql = 0x01 ''
  LockedProtoPfn = 0xf78d68e0
      FileOffset = 0n48
     OriginalPte = struct _MMPTE
    ProtoProtect = struct _MMWSLE
          Status = 0n1
   MarkPageDirty = 0xa0ee921
            Pfn1 = 0x80a88164


第九部分:

NTSTATUS
MiCompleteProtoPteFault (
    IN ULONG_PTR StoreInstruction,
    IN PVOID FaultingAddress,
    IN PMMPTE PointerPte,
    IN PMMPTE PointerProtoPte,
    IN KIRQL OldIrql,
    IN OUT PMMPFN *LockedProtoPfn
    )

/*++

Routine Description:

    This routine completes a prototype PTE fault.  It is invoked
    after a read operation has completed bringing the data into
    memory.

第十部分:

    ProtoPteContents.u.Long = PointerProtoPte->u.Long;


1: kd> p
nt!MiCompleteProtoPteFault+0x50:
80a881b4 8b3f            mov     edi,dword ptr [edi]
1: kd> r
eax=00000002 ebx=0a0ee921 ecx=f78d6910 edx=e80e369c esi=c0304200 edi=e1009c00

    PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (&ProtoPteContents);
    Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    Pfn1->u3.e1.PrototypePte = 1;

1: kd> p
nt!MiCompleteProtoPteFault+0x52:
80a881b6 8b0dd805bf80    mov     ecx,dword ptr [nt!MmPfnDatabase (80bf05d8)]
1: kd> p
nt!MiCompleteProtoPteFault+0x58:
80a881bc c1ef0c          shr     edi,0Ch
1: kd> p
nt!MiCompleteProtoPteFault+0x5b:
80a881bf 8d047f          lea     eax,[edi+edi*2]
1: kd> r
eax=00000002 ebx=0a0ee921 ecx=81000000 edx=e80e369c esi=c0304200 edi=0000a0ee
eip=80a881bf esp=f78d682c ebp=f78d6858 iopl=0         nv up ei pl nz na pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000207
nt!MiCompleteProtoPteFault+0x5b:
80a881bf 8d047f          lea     eax,[edi+edi*2]

1: kd> dd 810f1650
810f1650  00000000 e1009c00 00000001 00011608
810f1660  fcf194c6 0000a1cd


   +0x00c u3               : __unnamed
      +0x000 e1               : _MMPFNENTRY
         +0x000 Modified         : Pos 0, 1 Bit
         +0x000 ReadInProgress   : Pos 1, 1 Bit
         +0x000 WriteInProgress  : Pos 2, 1 Bit
         +0x000 PrototypePte     : Pos 3, 1 Bit        1

    //
    // Capture prefetch fault information.
    //

    OriginalPte = Pfn1->OriginalPte;        


第十一部分:

    ContainingPageTablePointer = MiGetPteAddress (PointerPte);        C0300C10

      PointerPte = 0xc0304200
#define MiGetPteAddress(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))


1: kd> !pte 0xc0304200
                 VA c1080000
PDE at C0300C10         PTE at C0304200
contains 0A03F963       contains 00027400
pfn a03f  -G-DA--KWEV   not valid
                         Proto: E1009C00

C0304200


1100 0000 0011 0000 0100 0010 0000 0000

11    00 00    00 00    11 00    00 01    00 00

300c10

第十二部分:

eax=0a03f963

0a03f


    Pfn2 = MI_PFN_ELEMENT (ContainingPageTablePointer->u.Hard.PageFrameNumber);    81000000+0a03f*18


1: kd> dd 81000000+0a03f*18
810f05e8  00000000 c0300c10 00000025 00011601
810f05f8  00000080 00000039

1: kd> p
nt!MiCompleteProtoPteFault+0x87:
80a881eb 8d04c2          lea     eax,[edx+eax*8]
1: kd> p
nt!MiCompleteProtoPteFault+0x8a:
80a881ee ff4008          inc     dword ptr [eax+8]
1: kd> r
eax=810f05e8


dv
    ProtoProtect = struct _MMWSLE
    
1: kd> dx -r1 (*((ntkrnlmp!_MMWSLE *)0xf78d6854))
(*((ntkrnlmp!_MMWSLE *)0xf78d6854))                 [Type: _MMWSLE]
    [+0x000] u1               [Type: __unnamed]


1: kd> dd 0xf78d6854
f78d6854  00000346

    ProtoProtect.u1.Long = 0;


        ProtoProtect.u1.e1.Protection = MI_GET_PROTECTION_FROM_SOFT_PTE(&OriginalPte);
        ProtoProtect.u1.e1.SameProtectAsProto = 1;


#define MI_GET_PROTECTION_FROM_SOFT_PTE(PTE) ((PTE)->u.Soft.Protection)

fcf194c6


    +0x000 Soft             : _MMPTE_SOFTWARE
         +0x000 Valid            : Pos 0, 1 Bit
         +0x000 PageFileLow      : Pos 1, 4 Bits
         +0x000 Protection       : Pos 5, 5 Bits    00 110=0x6


0100 1100 0110

第十三部分:

    MI_MAKE_VALID_PTE (TempPte,
                       PageFrameIndex,
                       ProtoProtect.u1.e1.Protection,
                       PointerPte);            //TempPte=ebx=0a0ee921

#define MI_MAKE_VALID_PTE(OUTPTE,FRAME,PMASK,PPTE)                            \
       (OUTPTE).u.Long = ((FRAME << 12) |                                     \
                         (MmProtectToPteMask[PMASK]) |                        \
                          MiDetermineUserGlobalPteMask ((PMMPTE)PPTE));


1: kd> p
nt!MiCompleteProtoPteFault+0x4e2:
80a88646 e85f6d0400      call    nt!MiDetermineUserGlobalPteMask (80acf3aa)
1: kd> p
nt!MiCompleteProtoPteFault+0x4e7:
80a8864b 8bd8            mov     ebx,eax
1: kd> r
eax=00000121

1: kd> p
nt!MiCompleteProtoPteFault+0x4f0:
80a88654 c1e70c          shl     edi,0Ch
1: kd> p
nt!MiCompleteProtoPteFault+0x4f3:
80a88657 0bdf            or      ebx,edi
1: kd> p
nt!MiCompleteProtoPteFault+0x4f5:
80a88659 837dec00        cmp     dword ptr [ebp-14h],0
1: kd> r
eax=00000121 ebx=0a0ee921

   MI_WRITE_VALID_PTE (PointerPte, TempPte);


1: kd> dd 0xc0304200
c0304200  00027400 00027402 00027404 00027406
c0304210  00027408 0002740a 0002740c 0002740e
c0304220  00027410 00027412 00027414 00027416

改为

1: kd> dd 0xc0304200
c0304200  0a0ee921 00027402 00027404 00027406
c0304210  00027408 0002740a 0002740c 0002740e
c0304220  00027410 00027412 00027414 00027416

1: kd> p
nt!MiCompleteProtoPteFault+0x60f:
80a88773 8918            mov     dword ptr [eax],ebx
1: kd> r
eax=c0304200 ebx=0a0ee921


1: kd> dd 0xc0304200
c0304200  0a0ee921 00027402 00027404 00027406
c0304210  00027408 0002740a 0002740c 0002740e
c0304220  00027410 00027412 00027414 00027416


1: kd> !pte c1080000
                 VA c1080000
PDE at C0300C10         PTE at C0304200
contains 0A03F963       contains 0A0EE921
pfn a03f  -G-DA--KWEV   pfn a0ee  -G--A--KREV        

第十四部分:


    WorkingSetIndex = MiAddValidPageToWorkingSet (FaultingAddress,
                                                  PointerPte,
                                                  Pfn1,
                                                  (ULONG) ProtoProtect.u1.Long);

1: kd> x nt!MmSystemCacheWs
80bf03c0          nt!MmSystemCacheWs = struct _MMSUPPORT
1: kd> dx -r1 (*((ntkrnlmp!_MMSUPPORT *)0x80bf03c0))
(*((ntkrnlmp!_MMSUPPORT *)0x80bf03c0))                 [Type: _MMSUPPORT]
    [+0x000] WorkingSetExpansionLinks [Type: _LIST_ENTRY]
    [+0x008] LastTrimTime     : {0} [Type: _LARGE_INTEGER]
    [+0x010] Flags            [Type: _MMSUPPORT_FLAGS]
    [+0x014] PageFaultCount   : 0x378 [Type: unsigned long]
    [+0x018] PeakWorkingSetSize : 0x342 [Type: unsigned long]
    [+0x01c] GrowthSinceLastEstimate : 0x378 [Type: unsigned long]
    [+0x020] MinimumWorkingSetSize : 0x3f1 [Type: unsigned long]
    [+0x024] MaximumWorkingSetSize : 0x20000 [Type: unsigned long]
    [+0x028] VmWorkingSetList : 0xc0c00000 [Type: _MMWSL *]
    [+0x02c] Claim            : 0x0 [Type: unsigned long]
    [+0x030] NextEstimationSlot : 0x0 [Type: unsigned long]
    [+0x034] NextAgingSlot    : 0x0 [Type: unsigned long]
    [+0x038] EstimatedAvailable : 0x0 [Type: unsigned long]
    [+0x03c] WorkingSetSize   : 0x342 [Type: unsigned long]
    [+0x040] WorkingSetMutex  [Type: _KGUARDED_MUTEX]


1: kd> dx -r1 ((ntkrnlmp!_MMWSL *)0xc0c00000)
((ntkrnlmp!_MMWSL *)0xc0c00000)                 : 0xc0c00000 [Type: _MMWSL *]
    [+0x000] FirstFree        : 0x343 [Type: unsigned long]
    [+0x004] FirstDynamic     : 0x1 [Type: unsigned long]
    [+0x008] LastEntry        : 0x3f1 [Type: unsigned long]
    [+0x00c] NextSlot         : 0x1 [Type: unsigned long]
    [+0x010] Wsle             : 0xc0c00038 [Type: _MMWSLE *]
    [+0x014] LastInitializedWsle : 0x3f1 [Type: unsigned long]
    [+0x018] NonDirectCount   : 0x1d [Type: unsigned long]
    [+0x01c] HashTable        : 0x0 [Type: _MMWSLE_HASH *]
    [+0x020] HashTableSize    : 0x0 [Type: unsigned long]
    [+0x024] NumberOfCommittedPageTables : 0x0 [Type: unsigned long]
    [+0x028] HashTableStart   : 0xc0df1000 [Type: void *]
    [+0x02c] HighestPermittedHashAddress : 0xc1000000 [Type: void *]
    [+0x030] NumberOfImageWaiters : 0x0 [Type: unsigned long]
    [+0x034] VadBitMapHint    : 0x0 [Type: unsigned long]
    [+0x038] UsedPageTableEntries [Type: unsigned short [768]]
    [+0x638] CommittedPageTables [Type: unsigned long [24]]


结果:


    Wsle[WorkingSetIndex] = WsleContents;

1: kd> dd 0xc0c00038+343*4
c0c00d44  c1080201 00003450 00003460 00003470
c0c00d54  00003480 00003490 000034a0 000034b0

    if (WsleMask != 0) {
        Wsle[WorkingSetIndex].u1.Long |= WsleMask;
    }


1: kd> dd 0xc0c00038+343*4
c0c00d44  c1080331 00003450 00003460 00003470
c0c00d54  00003480 00003490 000034a0 000034b0
c0c00d64  000034c0 000034d0 000034e0 000034f0
c0c00d74  00003500 00003510 00003520 00003530


第十五部分:最终结果0xc0304200和e1009c00地址处的内容都修改为0a0ee921


1: kd> dd 0xc0304200
c0304200  0a0ee921 00027402 00027404 00027406
c0304210  00027408 0002740a 0002740c 0002740e
c0304220  00027410 00027412 00027414 00027416
c0304230  00027418 0002741a 0002741c 0002741e
c0304240  00027420 00027422 00027424 00027426
c0304250  00027428 0002742a 0002742c 0002742e
c0304260  00027430 00027432 00027434 00027436
c0304270  00027438 0002743a 0002743c 0002743e
1: kd> dd e1009c00
e1009c00  0a0ee921 fcf194c6 fcf194c6 fcf194c6
e1009c10  fcf194c6 fcf194c6 fcf194c6 fcf194c6

相关文章:

  • InfluxDB 高级分析实战:预测、技术指标与异常检测全指南
  • 70.新增用户内容复制功能
  • 1-2 Dart SDK 安装
  • rl_sar功能包详解
  • PTA-根据已有类Worker,使用LinkedList编写一个WorkerList类,实现计算所有工人总工资的功能。
  • Python+MongoDb使用手册(精简)
  • Baklib加速企业AI数据治理实践
  • Flickr30k Entities短语定位评测指南
  • 基于大模型预测的寻常型天疱疮诊疗方案研究报告
  • 鸿蒙OSUniApp内存管理优化实战:从入门到精通#三方框架 #Uniapp
  • 牛顿迭代算法-深度解析
  • TDengine 基于 TDgpt 的 AI 应用实战
  • Kubernetes(K8s)核心架构解析与实用命令大全
  • Ansible自动化运维工具全面指南:从安装到实战应用
  • Ansible 进阶 - Roles 与 Inventory 的高效组织
  • 《分子动力学模拟的参数困局:QML的突围方案》
  • Python实现HPSO-TVAC优化算法优化支持向量机SVC分类模型项目实战
  • 行业分析---小米汽车2025第一季度财报
  • 复杂业务场景下 JSON 规范设计:Map<String,Object>快速开发 与 ResponseEntity精细化控制HTTP 的本质区别与应用场景解析
  • 手写ArrayList和LinkedList
  • 网站做的文字乱码/长沙seo
  • 怎样做 网站做seo/qq排名优化网站
  • 三大门户网站/百度快速排名 搜
  • wordpress 主题演示/优化技术
  • 企业购 网站建设/广州百度推广电话
  • 德州哪里有做网站推广的/班级优化大师的功能有哪些