首页
社区
课程
招聘
21
攻破 Window AMD64 平台的 PatchGuard - 清除执行中的 PatchGuard
发表于: 2019-5-27 16:47 18437

攻破 Window AMD64 平台的 PatchGuard - 清除执行中的 PatchGuard

2019-5-27 16:47
18437
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
VOID
NTAPI
PgCheckAllWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PSYSTEM_PROCESS_INFORMATION ProcessInfo = NULL;
    PSYSTEM_EXTENDED_THREAD_INFORMATION ThreadInfo = NULL;
    PVOID Buffer = NULL;
    ULONG BufferSize = PAGE_SIZE;
    ULONG ReturnLength = 0;
    ULONG Index = 0;
    PULONG64 InitialStack = 0;
    DISPATCHER_HEADER * Header = NULL;
 
    /*
    if (os build >= 9600){
        PgBlock->WorkerContext = struct _DISPATCHER_HEADER
 
            Header->Type = 0x15
            Header->Hand = 0xac
    }
    else {
        PgBlock->WorkerContext = enum _WORK_QUEUE_TYPE
 
            CriticalWorkQueue = 0
            DelayedWorkQueue = 1
    }
    */
 
    InitialStack = IoGetInitialStack();
 
    if (GetGpBlock(PgBlock)->BuildNumber >= 9600) {
        while ((ULONG64)InitialStack != (ULONG64)&PgBlock) {
            Header = *(PVOID *)InitialStack;
 
            if (FALSE != MmIsAddressValid(Header)) {
                if (FALSE != MmIsAddressValid((PCHAR)(Header + 1) - 1)) {
                    if (0x15 == Header->Type &&
                        0xac == Header->Hand) {
                        PgBlock->WorkerContext = Header;
 
                        break;
                    }
                }
            }
 
            InitialStack--;
        }
    }
    else {
        PgBlock->WorkerContext = UlongToPtr(CriticalWorkQueue);
    }
 
retry:
    Buffer = ExAllocatePool(
        NonPagedPool,
        BufferSize);
 
    if (NULL != Buffer) {
        RtlZeroMemory(
            Buffer,
            BufferSize);
 
        Status = ZwQuerySystemInformation(
            SystemExtendedProcessInformation,
            Buffer,
            BufferSize,
            &ReturnLength);
 
        if (NT_SUCCESS(Status)) {
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
 
            while (TRUE) {
                if (PsGetCurrentProcessId() == ProcessInfo->UniqueProcessId) {
                    ThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION)
                        (ProcessInfo + 1);
 
                    if (NULL == PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() ==
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread) {
                                PgBlock->ExpWorkerThread = ThreadInfo[Index].Win32StartAddress;
 
                                break;
                            }
                        }
                    }
 
                    if (NULL != PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() !=
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread &&
                                (ULONG64)PgBlock->ExpWorkerThread ==
                                (ULONG64)ThreadInfo[Index].Win32StartAddress) {
                                AsyncCall(
                                    ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread,
                                    NULL,
                                    NULL,
                                    (PUSER_THREAD_START_ROUTINE)PgCheckWorkerThread,
                                    PgBlock);
                            }
                        }
                    }
 
                    break;
                }
 
                if (0 == ProcessInfo->NextEntryOffset) {
                    break;
                }
                else {
                    ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
                        ((PCHAR)ProcessInfo + ProcessInfo->NextEntryOffset);
                }
            }
        }
 
        ExFreePool(Buffer);
        Buffer = NULL;
 
        if (STATUS_INFO_LENGTH_MISMATCH == Status) {
            BufferSize = ReturnLength;
            goto retry;
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
VOID
NTAPI
PgLocatePoolObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PFN_NUMBER Index = 0;
    PVOID Establisher = NULL;
 
    GetCounterBody(&Object->Establisher, &Establisher);
 
    for (Index = 0;
        Index < PgBlock->PoolBigPageTableSize;
        Index++) {
        if (POOL_BIG_TABLE_ENTRY_FREE !=
            ((ULONG64)PgBlock->PoolBigPageTable[Index].Va & POOL_BIG_TABLE_ENTRY_FREE)) {
            if (NonPagedPool == PgBlock->MmDeterminePoolType(PgBlock->PoolBigPageTable[Index].Va)) {
                if (PgBlock->PoolBigPageTable[Index].NumberOfPages > PgBlock->SizeINITKDBG) {
                    if ((ULONG64)Establisher >= (ULONG64)PgBlock->PoolBigPageTable[Index].Va &&
                        (ULONG64)Establisher < (ULONG64)PgBlock->PoolBigPageTable[Index].Va +
                        PgBlock->PoolBigPageTable[Index].NumberOfPages) {
                        Object->BaseAddress = PgBlock->PoolBigPageTable[Index].Va;
                        Object->RegionSize = PgBlock->PoolBigPageTable[Index].NumberOfPages;
 
#ifndef PUBLIC
                        DbgPrint(
                            "[Sefirot] [PatchGuard] < %p > found region in pool < %p - %08x >\n",
                            Establisher,
                            Object->BaseAddress,
                            Object->RegionSize);
#endif // !PUBLIC
 
                        Object->Type = PgPoolBigPage;
 
                        break;
                    }
                }
            }
        }
    }
}
 
VOID
NTAPI
PgLocateSystemPtesObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PRTL_BITMAP BitMap = NULL;
    ULONG BitMapSize = 0;
    PFN_NUMBER NumberOfPtes = 0;
    ULONG HintIndex = 0;
    ULONG StartingRunIndex = 0;
    PVOID Establisher = NULL;
 
    NumberOfPtes = PgBlock->NumberOfPtes;
 
    GetCounterBody(&Object->Establisher, &Establisher);
 
    BitMapSize =
        sizeof(RTL_BITMAP) +
        (ULONG)((((NumberOfPtes + 1) + 31) / 32) * 4);
 
    BitMap = ExAllocatePool(NonPagedPool, BitMapSize);
 
    if (NULL != BitMap) {
        RtlInitializeBitMap(
            BitMap,
            (PULONG)(BitMap + 1),
            (ULONG)(NumberOfPtes + 1));
 
        RtlClearAllBits(BitMap);
 
        InitializeSystemPtesBitMap(
            PgBlock->BasePte,
            NumberOfPtes,
            BitMap);
 
        do {
            HintIndex = RtlFindSetBits(
                BitMap,
                1,
                HintIndex);
 
            if (MAXULONG != HintIndex) {
                RtlFindNextForwardRunClear(
                    BitMap,
                    HintIndex,
                    &StartingRunIndex);
 
                RtlClearBits(BitMap, HintIndex, StartingRunIndex - HintIndex);
 
                if ((ULONG64)Establisher >=
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + HintIndex) &&
                        (ULONG64)Establisher <
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + StartingRunIndex) - PgBlock->SizeCmpAppendDllSection) {
                    Object->BaseAddress =
                        GetVirtualAddressMappedByPte(PgBlock->BasePte + HintIndex);
 
                    Object->RegionSize =
                        (SIZE_T)(StartingRunIndex - HintIndex) * PAGE_SIZE;
 
#ifndef PUBLIC
                    DbgPrint(
                        "[Sefirot] [PatchGuard] < %p > found region in system ptes < %p - %08x >\n",
                        Establisher,
                        Object->BaseAddress,
                        Object->RegionSize);
#endif // !PUBLIC
 
                    Object->Type = PgSystemPtes;
 
                    break;
                }
 
                HintIndex = StartingRunIndex;
            }
        while (HintIndex < NumberOfPtes);
 
        ExFreePool(BitMap);
    }
}
 
VOID
NTAPI
PgLocateObject(
    __inout PPGBLOCK PgBlock,
    __out PPGOBJECT Object
)
{
    IpiSingleCall(
        (PPS_APC_ROUTINE)NULL,
        (PKSYSTEM_ROUTINE)PgLocatePoolObject,
        (PUSER_THREAD_START_ROUTINE)PgBlock,
        (PVOID)Object);
 
    if (-1 == Object->Type) {
        IpiSingleCall(
            (PPS_APC_ROUTINE)NULL,
            (PKSYSTEM_ROUTINE)PgLocateSystemPtesObject,
            (PUSER_THREAD_START_ROUTINE)PgBlock,
            (PVOID)Object);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
VOID
NTAPI
PgCheckWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    ULONG64 LowLimit = 0;
    ULONG64 HighLimit = 0;
    PULONG64 InitialStack = 0;
    PULONG64 TargetPc = NULL;
    ULONG Count = 0;
    PCALLERS Callers = NULL;
    ULONG Index = 0;
    LONG_PTR Reference = 0;
    PVOID * Parameters = NULL;
    PGOBJECT TempObject = { 0 };
    PPGOBJECT Object = NULL;
 
    Callers = ExAllocatePool(
        NonPagedPool,
        MAX_STACK_DEPTH * sizeof(CALLERS));
 
    if (NULL != Callers) {
        Count = WalkFrameChain(
            Callers,
            MAX_STACK_DEPTH);
 
        if (0 != Count) {
            // PrintFrameChain(Callers, 0, Count);
 
            IoGetStackLimits(&LowLimit, &HighLimit);
 
            InitialStack = IoGetInitialStack();
 
            // all worker thread start at KiStartSystemThread and return address == 0
            // if null != last return address code is in noimage
 
            if (NULL != Callers[Count - 1].Establisher) {
#ifndef PUBLIC
                DbgPrint(
                    "[Sefirot] [PatchGuard] < %p > found noimage return address in worker thread\n",
                    Callers[Count - 1].Establisher);
#endif // !PUBLIC
 
                for (TargetPc = (PULONG64)Callers[Count - 1].EstablisherFrame;
                    (ULONG64)TargetPc < (ULONG64)InitialStack;
                    TargetPc++) {
                    // In most cases, PatchGuard code will wait for a random time.
                    // set return address in current thread stack to _RevertWorkerToSelf
                    // than PatchGuard code was not continue
 
                    if ((ULONG64)*TargetPc == (ULONG64)Callers[Count - 1].Establisher) {
                        // restart ExpWorkerThread
 
                        // ExFrame->P1Home = WorkerContext;
                        // ExFrame->P2Home = ExpWorkerThread;
                        // ExFrame->P3Home = PspSystemThreadStartup;
                        // ExFrame->Return = KiStartSystemThread; <- jmp this function return address == 0
 
                        SetCounterBody(
                            &TempObject.Establisher,
                            Callers[Count - 1].Establisher);
 
                        TempObject.Type = -1;
 
                        PgLocateObject(PgBlock, &TempObject);
 
                        if (-1 != TempObject.Type) {
                            Object = PgCreateObject(
                                PgDeclassified,
                                TempObject.Type,
                                TempObject.BaseAddress,
                                TempObject.RegionSize,
                                NULL,
                                PgBlock,
                                PgBlock->ClearCallback,
                                Callers[Count - 1].Establisher,
                                GetGpBlock(PgBlock)->CaptureContext);
 
                            if (NULL != Object) {
                                SetCounterBody(
                                    &Object->Establisher,
                                    Callers[Count - 1].Establisher);
 
                                *TargetPc = (ULONG64)&Object->Establisher;
 
                                InterlockedIncrementSizeT(&PgBlock->ReferenceCount);
 
#ifndef PUBLIC
                                DbgPrint(
                                    "[Sefirot] [PatchGuard] < %p > insert worker thread check code\n",
                                    PgBlock->ReferenceCount);
#endif // !PUBLIC
                            }
                        }
 
                        break;
                    }
                }
            }
        }
 
        ExFreePool(Callers);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
VOID
NTAPI
PgCheckAllWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PSYSTEM_PROCESS_INFORMATION ProcessInfo = NULL;
    PSYSTEM_EXTENDED_THREAD_INFORMATION ThreadInfo = NULL;
    PVOID Buffer = NULL;
    ULONG BufferSize = PAGE_SIZE;
    ULONG ReturnLength = 0;
    ULONG Index = 0;
    PULONG64 InitialStack = 0;
    DISPATCHER_HEADER * Header = NULL;
 
    /*
    if (os build >= 9600){
        PgBlock->WorkerContext = struct _DISPATCHER_HEADER
 
            Header->Type = 0x15
            Header->Hand = 0xac
    }
    else {
        PgBlock->WorkerContext = enum _WORK_QUEUE_TYPE
 
            CriticalWorkQueue = 0
            DelayedWorkQueue = 1
    }
    */
 
    InitialStack = IoGetInitialStack();
 
    if (GetGpBlock(PgBlock)->BuildNumber >= 9600) {
        while ((ULONG64)InitialStack != (ULONG64)&PgBlock) {
            Header = *(PVOID *)InitialStack;
 
            if (FALSE != MmIsAddressValid(Header)) {
                if (FALSE != MmIsAddressValid((PCHAR)(Header + 1) - 1)) {
                    if (0x15 == Header->Type &&
                        0xac == Header->Hand) {
                        PgBlock->WorkerContext = Header;
 
                        break;
                    }
                }
            }
 
            InitialStack--;
        }
    }
    else {
        PgBlock->WorkerContext = UlongToPtr(CriticalWorkQueue);
    }
 
retry:
    Buffer = ExAllocatePool(
        NonPagedPool,
        BufferSize);
 
    if (NULL != Buffer) {
        RtlZeroMemory(
            Buffer,
            BufferSize);
 
        Status = ZwQuerySystemInformation(
            SystemExtendedProcessInformation,
            Buffer,
            BufferSize,
            &ReturnLength);
 
        if (NT_SUCCESS(Status)) {
            ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
 
            while (TRUE) {
                if (PsGetCurrentProcessId() == ProcessInfo->UniqueProcessId) {
                    ThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION)
                        (ProcessInfo + 1);
 
                    if (NULL == PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() ==
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread) {
                                PgBlock->ExpWorkerThread = ThreadInfo[Index].Win32StartAddress;
 
                                break;
                            }
                        }
                    }
 
                    if (NULL != PgBlock->ExpWorkerThread) {
                        for (Index = 0;
                            Index < ProcessInfo->NumberOfThreads;
                            Index++) {
                            if ((ULONG64)PsGetCurrentThreadId() !=
                                (ULONG64)ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread &&
                                (ULONG64)PgBlock->ExpWorkerThread ==
                                (ULONG64)ThreadInfo[Index].Win32StartAddress) {
                                AsyncCall(
                                    ThreadInfo[Index].ThreadInfo.ClientId.UniqueThread,
                                    NULL,
                                    NULL,
                                    (PUSER_THREAD_START_ROUTINE)PgCheckWorkerThread,
                                    PgBlock);
                            }
                        }
                    }
 
                    break;
                }
 
                if (0 == ProcessInfo->NextEntryOffset) {
                    break;
                }
                else {
                    ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
                        ((PCHAR)ProcessInfo + ProcessInfo->NextEntryOffset);
                }
            }
        }
 
        ExFreePool(Buffer);
        Buffer = NULL;
 
        if (STATUS_INFO_LENGTH_MISMATCH == Status) {
            BufferSize = ReturnLength;
            goto retry;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
VOID
NTAPI
PgLocatePoolObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PFN_NUMBER Index = 0;
    PVOID Establisher = NULL;
 
    GetCounterBody(&Object->Establisher, &Establisher);
 
    for (Index = 0;
        Index < PgBlock->PoolBigPageTableSize;
        Index++) {
        if (POOL_BIG_TABLE_ENTRY_FREE !=
            ((ULONG64)PgBlock->PoolBigPageTable[Index].Va & POOL_BIG_TABLE_ENTRY_FREE)) {
            if (NonPagedPool == PgBlock->MmDeterminePoolType(PgBlock->PoolBigPageTable[Index].Va)) {
                if (PgBlock->PoolBigPageTable[Index].NumberOfPages > PgBlock->SizeINITKDBG) {
                    if ((ULONG64)Establisher >= (ULONG64)PgBlock->PoolBigPageTable[Index].Va &&
                        (ULONG64)Establisher < (ULONG64)PgBlock->PoolBigPageTable[Index].Va +
                        PgBlock->PoolBigPageTable[Index].NumberOfPages) {
                        Object->BaseAddress = PgBlock->PoolBigPageTable[Index].Va;
                        Object->RegionSize = PgBlock->PoolBigPageTable[Index].NumberOfPages;
 
#ifndef PUBLIC
                        DbgPrint(
                            "[Sefirot] [PatchGuard] < %p > found region in pool < %p - %08x >\n",
                            Establisher,
                            Object->BaseAddress,
                            Object->RegionSize);
#endif // !PUBLIC
 
                        Object->Type = PgPoolBigPage;
 
                        break;
                    }
                }
            }
        }
    }
}
 
VOID
NTAPI
PgLocateSystemPtesObject(
    __inout PPGBLOCK PgBlock,
    __in PPGOBJECT Object
)
{
    PRTL_BITMAP BitMap = NULL;
    ULONG BitMapSize = 0;
    PFN_NUMBER NumberOfPtes = 0;
    ULONG HintIndex = 0;
    ULONG StartingRunIndex = 0;
    PVOID Establisher = NULL;
 
    NumberOfPtes = PgBlock->NumberOfPtes;
 
    GetCounterBody(&Object->Establisher, &Establisher);
 
    BitMapSize =
        sizeof(RTL_BITMAP) +
        (ULONG)((((NumberOfPtes + 1) + 31) / 32) * 4);
 
    BitMap = ExAllocatePool(NonPagedPool, BitMapSize);
 
    if (NULL != BitMap) {
        RtlInitializeBitMap(
            BitMap,
            (PULONG)(BitMap + 1),
            (ULONG)(NumberOfPtes + 1));
 
        RtlClearAllBits(BitMap);
 
        InitializeSystemPtesBitMap(
            PgBlock->BasePte,
            NumberOfPtes,
            BitMap);
 
        do {
            HintIndex = RtlFindSetBits(
                BitMap,
                1,
                HintIndex);
 
            if (MAXULONG != HintIndex) {
                RtlFindNextForwardRunClear(
                    BitMap,
                    HintIndex,
                    &StartingRunIndex);
 
                RtlClearBits(BitMap, HintIndex, StartingRunIndex - HintIndex);
 
                if ((ULONG64)Establisher >=
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + HintIndex) &&
                        (ULONG64)Establisher <
                    (ULONG64)GetVirtualAddressMappedByPte(
                        PgBlock->BasePte + StartingRunIndex) - PgBlock->SizeCmpAppendDllSection) {
                    Object->BaseAddress =
                        GetVirtualAddressMappedByPte(PgBlock->BasePte + HintIndex);
 
                    Object->RegionSize =
                        (SIZE_T)(StartingRunIndex - HintIndex) * PAGE_SIZE;
 
#ifndef PUBLIC
                    DbgPrint(
                        "[Sefirot] [PatchGuard] < %p > found region in system ptes < %p - %08x >\n",
                        Establisher,
                        Object->BaseAddress,
                        Object->RegionSize);
#endif // !PUBLIC
 
                    Object->Type = PgSystemPtes;
 
                    break;
                }
 
                HintIndex = StartingRunIndex;
            }
        while (HintIndex < NumberOfPtes);
 
        ExFreePool(BitMap);
    }
}
 
VOID
NTAPI
PgLocateObject(
    __inout PPGBLOCK PgBlock,
    __out PPGOBJECT Object
)
{
    IpiSingleCall(
        (PPS_APC_ROUTINE)NULL,
        (PKSYSTEM_ROUTINE)PgLocatePoolObject,
        (PUSER_THREAD_START_ROUTINE)PgBlock,
        (PVOID)Object);
 
    if (-1 == Object->Type) {
        IpiSingleCall(
            (PPS_APC_ROUTINE)NULL,
            (PKSYSTEM_ROUTINE)PgLocateSystemPtesObject,
            (PUSER_THREAD_START_ROUTINE)PgBlock,
            (PVOID)Object);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
VOID
NTAPI
PgCheckWorkerThread(
    __inout PPGBLOCK PgBlock
)
{
    ULONG64 LowLimit = 0;
    ULONG64 HighLimit = 0;
    PULONG64 InitialStack = 0;
    PULONG64 TargetPc = NULL;
    ULONG Count = 0;
    PCALLERS Callers = NULL;
    ULONG Index = 0;
    LONG_PTR Reference = 0;
    PVOID * Parameters = NULL;
    PGOBJECT TempObject = { 0 };
    PPGOBJECT Object = NULL;
 
    Callers = ExAllocatePool(
        NonPagedPool,
        MAX_STACK_DEPTH * sizeof(CALLERS));
 
    if (NULL != Callers) {
        Count = WalkFrameChain(
            Callers,
            MAX_STACK_DEPTH);
 
        if (0 != Count) {
            // PrintFrameChain(Callers, 0, Count);
 
            IoGetStackLimits(&LowLimit, &HighLimit);
 
            InitialStack = IoGetInitialStack();
 
            // all worker thread start at KiStartSystemThread and return address == 0
            // if null != last return address code is in noimage
 
            if (NULL != Callers[Count - 1].Establisher) {
#ifndef PUBLIC
                DbgPrint(
                    "[Sefirot] [PatchGuard] < %p > found noimage return address in worker thread\n",
                    Callers[Count - 1].Establisher);
#endif // !PUBLIC
 
                for (TargetPc = (PULONG64)Callers[Count - 1].EstablisherFrame;
                    (ULONG64)TargetPc < (ULONG64)InitialStack;
                    TargetPc++) {
                    // In most cases, PatchGuard code will wait for a random time.
                    // set return address in current thread stack to _RevertWorkerToSelf
                    // than PatchGuard code was not continue
 
                    if ((ULONG64)*TargetPc == (ULONG64)Callers[Count - 1].Establisher) {
                        // restart ExpWorkerThread
 
                        // ExFrame->P1Home = WorkerContext;
                        // ExFrame->P2Home = ExpWorkerThread;
                        // ExFrame->P3Home = PspSystemThreadStartup;
                        // ExFrame->Return = KiStartSystemThread; <- jmp this function return address == 0
 
                        SetCounterBody(
                            &TempObject.Establisher,
                            Callers[Count - 1].Establisher);
 
                        TempObject.Type = -1;
 
                        PgLocateObject(PgBlock, &TempObject);
 
                        if (-1 != TempObject.Type) {
                            Object = PgCreateObject(
                                PgDeclassified,
                                TempObject.Type,
                                TempObject.BaseAddress,
                                TempObject.RegionSize,
                                NULL,
                                PgBlock,
                                PgBlock->ClearCallback,
                                Callers[Count - 1].Establisher,
                                GetGpBlock(PgBlock)->CaptureContext);
 
                            if (NULL != Object) {
                                SetCounterBody(
                                    &Object->Establisher,
                                    Callers[Count - 1].Establisher);
 
                                *TargetPc = (ULONG64)&Object->Establisher;
 
                                InterlockedIncrementSizeT(&PgBlock->ReferenceCount);
 
#ifndef PUBLIC
                                DbgPrint(
                                    "[Sefirot] [PatchGuard] < %p > insert worker thread check code\n",
                                    PgBlock->ReferenceCount);
#endif // !PUBLIC
                            }
                        }
 
                        break;
                    }
                }
            }
        }
 
        ExFreePool(Callers);
    }
}
最近微软更新了 1903 忙着更新了一下代码, 顺便把文章补全, 主要是解释一下如何检测的.

当 PatchGuad 处于执行状态时, 首先解密头部的CmpAppendDllSection, 然后在 CmpAppendDllSection内部完整解密整个Context, 进入PatchGuardEntryPointer, 替换IDT, 关闭DR中断, 自检, 插入WORKER(自捡成功的话), 清空栈, 进入FsRtlUninitializeSmallMcb, 这里FsRtlUninitializeSmallMcb 就是 PatchGuad 的执行主逻辑, 在这个逻辑中大部分时间 PatchGuad 都是处于延时状态以减少CPU 占用.

[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2019-6-1 15:15 被blindtiger编辑 ,原因:
收藏
免费 21
支持
分享
赞赏记录
参与人
雪币
留言
时间
zhang_derek
为你点赞~
2022-9-30 00:22
PLEBFE
为你点赞~
2022-7-27 22:21
飘零丶
为你点赞~
2022-7-17 03:22
lpmjknj
为你点赞~
2022-4-10 09:23
dx苹果的心愿
为你点赞~
2022-1-10 15:56
cslime
为你点赞~
2020-2-27 22:25
xuebook
为你点赞~
2020-1-30 21:17
rwxaes
为你点赞~
2019-10-5 15:44
固件安全
为你点赞~
2019-6-2 21:04
黑手鱼
为你点赞~
2019-5-30 15:36
跳舞和kiss
为你点赞~
2019-5-30 15:26
gaoan
为你点赞~
2019-5-30 15:17
那么骄傲丶
为你点赞~
2019-5-29 20:35
我是哥布林
为你点赞~
2019-5-29 17:42
Mengluu
为你点赞~
2019-5-29 17:37
sxpp
为你点赞~
2019-5-28 20:23
万剑归宗
为你点赞~
2019-5-28 17:37
萌克力
为你点赞~
2019-5-28 16:48
aas102400
为你点赞~
2019-5-28 16:44
Foodie
为你点赞~
2019-5-27 18:41
二娃
为你点赞~
2019-5-27 16:51
打赏 + 12.00雪花
打赏次数 2 雪花 + 12.00
收起 
赞赏  Editor   +2.00 2019/05/31 精品文章~
赞赏  万剑归宗   +10.00 2019/05/28
最新回复 (50)
雪    币: 6313
活跃值: (1117)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
飞总牛逼
2019-5-27 16:49
1
雪    币: 9626
活跃值: (1848)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
3
支持飞总
2019-5-27 17:09
0
雪    币: 576
活跃值: (1163)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
牛逼,赶紧收藏
2019-5-27 17:14
0
雪    币: 4057
活跃值: (337)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
5
牛逼
2019-5-27 17:36
0
雪    币: 1176
活跃值: (1284)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
6
支持支持
2019-5-27 17:42
0
雪    币: 1140
活跃值: (102)
能力值: ( LV4,RANK:48 )
在线值:
发帖
回帖
粉丝
7
除了牛逼,无法形容
2019-5-27 18:29
0
雪    币: 4491
活跃值: (2494)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
飞总牛逼
2019-5-27 18:41
0
雪    币: 7136
活跃值: (2036)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2019-5-27 19:05
0
雪    币: 4038
活跃值: (4312)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
感谢分享!
2019-5-27 23:21
0
雪    币: 1694
活跃值: (2233)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
牛逼+1
2019-5-27 23:54
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢分享
2019-5-28 00:41
0
雪    币: 1140
活跃值: (102)
能力值: ( LV4,RANK:48 )
在线值:
发帖
回帖
粉丝
13
握草,一天了还没有精华?这帖子还比不上复制粘贴?
2019-5-28 14:49
0
雪    币: 3745
活跃值: (7764)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
14
飞总牛逼.这才是真心的精华内容.不过飞总的帖子没有一个精华...
2019-5-28 15:54
0
雪    币: 2235
活跃值: (1115)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
看雪的精华帖只给xxx培训的吗
2019-5-28 16:42
0
雪    币: 4709
活跃值: (1675)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
16
感谢分享!
2019-5-28 16:42
0
雪    币: 12876
活跃值: (9332)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
17
一键点赞素质三连
2019-5-28 16:44
0
雪    币: 914
活跃值: (2678)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
18
看雪的精华帖只给xxx培训的吗
2019-5-28 16:44
0
雪    币: 490
活跃值: (4466)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
19
飞总牛逼
2019-5-28 16:45
0
雪    币: 433
活跃值: (2100)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
20
飞总牛批
2019-5-28 16:46
0
雪    币: 1358
活跃值: (2030)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
飞总牛逼
2019-5-28 16:46
0
雪    币: 433
活跃值: (2100)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
22
Sprite雪碧 支持飞总
你家特别肥
2019-5-28 16:48
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
23
飞总牛逼
2019-5-28 16:50
0
雪    币: 6129
活跃值: (4941)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
24
飞总牛逼
2019-5-28 17:26
0
雪    币: 7
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
把自已的工作成果完整地提供下载,予后来人学习和使用,这是大师的风格和风范。大师辈出,最后都成了一座座丰碑。段纲,Tesla.Angela,小艾。。。。
2019-5-28 17:53
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册