5

基本的に、ユーザーモードでできることをカーネルモードで実行できる関数を探していVirtualProtectます。

次の簡略化されたコードで例示されているロジックを使用して、メモリを割り当てています。

    PMDL mdl = MmAllocatePagesForMdl    
    (
        LowAddress,
        HighAddress,
        SkipAddress,
        size
    );

    ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
    PVOID ptr = MmGetSystemAddressForMdlSafe
    (
        mdl, 
        flags
    );

MdlMappingNoExecuteおよびフラグは、MdlMappingNoWriteWin8+ でのみ有効です。
また、MmGetSystemAddressForMdlSafeI のみを使用すると、たとえばNoAccessメモリ領域の保護を割り当てることができません。

割り当てられたメモリのページ保護を変更できるようにするために使用できる追加または代替の API はありますか?
現在、この機能は製品コードでは使用されていないため、ハッキングも行われます。

4

2 に答える 2

2
C:\Windows\System32>dumpbin /exports ntdll.dll | find "Protect"
        391  17E 0004C030 NtProtectVirtualMemory
       1077  42C 000CE8F0 RtlProtectHeap
       1638  65D 0004C030 ZwProtectVirtualMemory

カーネルモードから関数を呼び出すことができると思います。引数は通常、対応する関数Zwと同じです。文書化されていませんが、保護フラグを受け入れる文書化されたNtZwAllocateVirtualMemoryがあります。ZwProtectVirtualMemory

もう 1 つの方法は、ユーザー モードで仮想メモリを割り当てて保護し、バッファーをドライバーに渡し、対応する MDL をそこで作成することです。

于 2016-08-01T17:11:04.567 に答える
1

私が現在使用しているコードは以下のとおりです。
使用されるすべての API は公式です。
ここでは、割り当てられたメモリのサブ範囲用に別のmdlを作成し、そのサブ範囲の保護を変更します。

以下のこの方法で保護されたメモリにつまずいた場合:

  • エラーが発生しIRQL < DISPATCH_LEVELます(無効なシステム メモリが参照されました。これは、try-except によって保護することはできません。プローブによって保護する必要があります。通常、アドレスは単純に不良であるか、解放されたメモリを指しています。PAGE_FAULT_IN_NONPAGED_AREA )
  • エラーIRQL == DISPATCH_LEVELが 発生します (ページング可能な (または完全に無効な) アドレスに、高すぎる割り込み要求レベル (IRQL) でアクセスしようとしました。これは通常、ドライバーが不適切なアドレスを使用していることが原因です。)DRIVER_IRQL_NOT_LESS_OR_EQUAL

サブ範囲が大きなページ割り当ての一部である場合、保護の変更が失敗する可能性があることに注意してください。その後、status可能性がありSTATUS_NOT_SUPPORTEDます。 最初に割り当てられたメモリ領域のサイズと配置 (問題の変数によって異なります) が適切であり、私がよく知らないいくつかの追加の前提条件が満たされている場合 (おそらく特定の OS バージョンから)、
大きなページ割り当てが発生する可能性があります。SkipAddress

        PMDL guard_mdl = IoAllocateMdl
        (
            NULL, 
            PAGE_SIZE * guardPageCount, 
            FALSE,           
            FALSE,  
            NULL        
        );

        if (guard_mdl)
        {
            IoBuildPartialMdl
            (
                mdl,    
                guard_mdl,  
                (PVOID)(0),  // **offset** from the beginning of allocated memory ptr
                PAGE_SIZE * guardPageCount
            );

            status = MmProtectMdlSystemAddress
            (
                guard_mdl,
                PAGE_NOACCESS
            );
        }
于 2016-08-02T19:51:18.503 に答える