NtProtectVirtualMemory из kernel для юзерских страниц

Тема в разделе "WASM.NT.KERNEL", создана пользователем JamesB, 5 мар 2008.

Статус темы:
Закрыта.
  1. JamesB

    JamesB New Member

    Публикаций:
    0
    Регистрация:
    3 фев 2008
    Сообщения:
    66
    Появилась проблема. Надо при некотором событии (которое у меня отлавливается через хук ZwCreateSection) записать байт в юзермодное пространство, например int3 на EntryPoint в процессе.
    А там секция кода и.. PAGE_READONLY.
    Ловлю загрузку, скажем, test.dll (все отлично ловится) и делаю так: (NtProtectVirtualMemory находится в SST через Peb->loaderdata->ntdll export table->address of service, короче понятно, вообщем находится ; ))

    Код (Text):
    1. ULONG ProtectSize = PAGE_SIZE, OldProtection, ProtectVA;
    2.  
    3. ProtectVA = GetCurrentProcessEntryPoint();
    4.  
    5. KdPrint(("ProtectVA=%08x,ProtectSize=%08x",ProtectVA,ProtectSize));
    6.  
    7. NTSTATUS NtStatus = gNtProtectVirtualMemory(
    8.                     (HANDLE)-1,
    9.                     (PVOID*)&ProtectVA,
    10.                     &ProtectSize,
    11.                     PAGE_EXECUTE_READWRITE,
    12.                     &OldProtection
    13.                     );
    14. if (NT_SUCCESS(NtStatus))
    15. {
    16.     KdPrint(("NtProtectVirtualMemory() succeeded\n"));
    17.     // place int3 at entrypoint
    18.     *((PBYTE)ProtectVA) = 0xcc;
    19. }
    20. else
    21. {
    22.     KdPrint(("NtProtectVirtualMemory() failed with status %08x\n",NtStatus));
    23. }
    Failed with status C0000005 тобишь STATUS_ACCESS_VIOLATION

    Что такое может быть?
    Кстати, к этому я пришел т.е. не могу никак записать байт в юзермодное readonly пространство в обычном таком notepad.exe процессе (может я совсем отупел?) ...
    Пробовал и через IoAllocateMdl/MmProbeAndLockPages/MmMapLockedPagesSpecifyCache - вторая дает эксцепшон. WP bit сбрасывать пробовал, но он только для ядерных страниц, как я понимаю, не помогает короче ничего.
    Что посоветуете?
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    почему -1 ?
     
  3. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    n0name
    GetCurrentProcess() ?
     
  4. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    JamesB
    OldProtection,ProtectVA,OldProtection должны находиться в юзерском ап.

    И прежде чем вызывать с хендлом -1 - надо к процесу приатачиться.
     
  5. JamesB

    JamesB New Member

    Публикаций:
    0
    Регистрация:
    3 фев 2008
    Сообщения:
    66
    О. Спасибо. Я просто че-то KeAttachProcess забыл сделать)
    Кстати странно, дров то в этот момент времени в контексте юзермодного нужного процесса и так выполняется...
    Сейчас попробую и отпишу...

    asd, понял, сейчас что-нибудь придумаю..
    thx всем!
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    я юзаю таки функции:
    Код (Text):
    1. PVOID MapInUserSpace(PVOID pBuf, PMDL *pMdl, ULONG dwSize){
    2.     PVOID pUserModeBuf = NULL;
    3.     PMDL pBufMdl = NULL;
    4.  
    5.     if (!pMdl)
    6.         return NULL;
    7.     pBufMdl = IoAllocateMdl(pBuf, dwSize, FALSE, FALSE, NULL);
    8.     if (!pBufMdl)
    9.         goto exit;
    10.     MmBuildMdlForNonPagedPool(pBufMdl);
    11.     pUserModeBuf = MmMapLockedPagesSpecifyCache(pBufMdl, UserMode, MmCached, NULL, FALSE,
    12.         NormalPagePriority);
    13. exit:
    14.     *pMdl = pBufMdl;
    15.     return pUserModeBuf;
    16. }
    17.  
    18. VOID UnmapInUserSpace(PMDL pMdl, PVOID pPool, PVOID pUserModeBuf){
    19.     if (pUserModeBuf)
    20.         MmUnmapLockedPages(pUserModeBuf, pMdl);
    21.     if (pMdl)
    22.         IoFreeMdl(pMdl);
    23.     if (pPool)
    24.         ExFreePool(pPool);
    25. }
     
  7. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia
    SrcAddr - kernelMode source buffer
    DstAddr - usermode destination address
    юзается примерно так:
    WriteProcessMem(hProc, memBuf, (PVOID)0x401234, sizeof(memBuf));

    Код (Text):
    1. void WriteProcessMem(HANDLE hProcess, PVOID SrcAddr, PVOID DstAddr, ULONG Size)
    2. {
    3.     PEPROCESS process = NULL;
    4.     NTSTATUS  st;
    5.     PUCHAR cPtr, dPtr, mdlPtr = NULL;
    6.     KAPC_STATE ApcState;
    7.     ULONG i;
    8.     PMDL mdl;
    9.     BOOL pageLocked = FALSE;
    10.  
    11.     st = ObReferenceObjectByHandle(hProcess, 0, NULL, UserMode, &process, NULL);
    12.  
    13.     if (NT_SUCCESS(st))
    14.     {  
    15.         cPtr = (PUCHAR)SrcAddr;
    16.  
    17.         KeStackAttachProcess(process, &ApcState);
    18.  
    19.         mdl = IoAllocateMdl(DstAddr, Size, FALSE, TRUE, NULL);
    20.         if (mdl)
    21.         {
    22.             pageLocked = TRUE;
    23.             __try
    24.             {
    25.                 MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
    26.             }
    27.             __except(EXCEPTION_EXECUTE_HANDLER)
    28.             {
    29.                 //DbgPrint("MmProbeAndLockPages exception\n");
    30.                 pageLocked = FALSE;
    31.             }
    32.  
    33.             if (pageLocked)
    34.             {
    35.                 __try
    36.                 {
    37.                     mdlPtr = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);
    38.                 }
    39.                 __except(EXCEPTION_EXECUTE_HANDLER)
    40.                 {
    41.                     //DbgPrint("MmGetSystemAddressForMdlSafe exception\n");
    42.                 }
    43.  
    44.                 if (mdlPtr)
    45.                 {
    46.                     dPtr = mdlPtr;
    47.                     st = MmProtectMdlSystemAddress(mdl, PAGE_READWRITE);
    48.                     if (NT_SUCCESS(st))
    49.                     {
    50.                         __try
    51.                         {
    52.                             for (i = 0; i < Size; ++i)
    53.                             {
    54.                                 dPtr[i] = cPtr[i];
    55.                             }
    56.                         }
    57.                         __except(EXCEPTION_EXECUTE_HANDLER)
    58.                         {
    59.                             //DbgPrint("memcopy exception\n");
    60.                         }
    61.                     }
    62.                     else
    63.                     {
    64.                         //DbgPrint("MmProtectMdlSystemAddress error %x\n", st);
    65.                     }
    66.  
    67.                     MmUnmapLockedPages(mdlPtr, mdl);
    68.                 }
    69.                 else
    70.                 {
    71.                     //DbgPrint("MmGetSystemAddressForMdlSafe error\n");
    72.                 }
    73.                
    74.                 MmUnlockPages(mdl);
    75.             }
    76.             else
    77.             {
    78.                 //DbgPrint("MmProbeAndLockPages failed\n");
    79.             }          
    80.  
    81.             IoFreeMdl(mdl);
    82.         }
    83.         else
    84.         {
    85.             //DbgPrint("IoAllocateMdl failed\n");
    86.         }
    87.  
    88.         KeUnstackDetachProcess(&ApcState);
    89.  
    90.         ObDereferenceObject(process);
    91.     }
    92. }
     
  8. JamesB

    JamesB New Member

    Публикаций:
    0
    Регистрация:
    3 фев 2008
    Сообщения:
    66
    Ого. Всем спасибо, сейчас будем пробовать...
    UPD: заработало. succeeded. Вообщем, сделал KeAttachProcess/KeDetachProcess, + поместил IN-OUT переменные для NtProtectVirtualMemory в юзермодные страницы. Всем спасибо...

    Кстати, Attach делать не обязательно, без него тоже все ок ...

    UPD: Заюзал вышеописаную WriteProcessMem, так же работает на ура, за что ее автору отдельный респект...
     
  9. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    infern0
    А можно еще проще записать туда, где память только R, - сделать разделяемую RW память с помощью \\Device\\PhysicalMemory. Работает это и на Win XP SP2
    Вот примерно так:

    Код (Text):
    1. #include "ntddk.h"
    2. #define VER_PRODUCTBUILD 2600 // Windows XP build 2600
    3. #include "ntifs.h"
    4.  
    5.  
    6. #if DBG
    7. #define dprintf DbgPrint
    8. #else
    9. #define dprintf(x)
    10. #endif
    11.  
    12.  
    13. PVOID MapView(HANDLE  hProcess, PVOID Base, LONG * Size) //ПРИМЕР - РАЗДЕЛЯЕМАЯ ПАМЯТЬ !!!
    14. {
    15.     UNICODE_STRING ustrSectionName;
    16.     OBJECT_ATTRIBUTES ObjectAttributes;
    17.     HANDLE hSection = NULL;
    18.     NTSTATUS SectionStatus = 0UL;
    19.     PHYSICAL_ADDRESS PhysicalAddress1 = {0,0};
    20.     PHYSICAL_ADDRESS PhysicalAddress2 = {0,0};
    21.     PVOID virtualAddress = NULL;
    22.     ULONG length = 0;
    23.     PVOID virtualAddr = NULL;
    24.     LONG Rem = 0;
    25.  
    26.     if(!MmIsAddressValid(Size) || !MmIsAddressValid(Base)) return NULL;
    27.  
    28.  
    29.     RtlInitUnicodeString(&ustrSectionName, L"\\Device\\PhysicalMemory");
    30.  
    31.     InitializeObjectAttributes(&ObjectAttributes, &ustrSectionName, /* OBJ_KERNEL_HANDLE | */ OBJ_CASE_INSENSITIVE, NULL, NULL);
    32.  
    33.  
    34.     SectionStatus = ZwOpenSection(&hSection, SECTION_ALL_ACCESS , &ObjectAttributes);
    35.  
    36.     if ( NT_SUCCESS ( SectionStatus ) )
    37.     {
    38.         length = *Size;
    39.         virtualAddr = (ULONG)Base;
    40.  
    41.         PhysicalAddress1 = MmGetPhysicalAddress(virtualAddr);
    42.  
    43.  
    44.         SectionStatus = ZwMapViewOfSection(hSection, hProcess /* NtCurrentProcess( ) */, &virtualAddress, 0,  length, &PhysicalAddress1, &length, ViewShare, 0, PAGE_READWRITE /* | PAGE_NOCACHE */);
    45.  
    46.         if ( NT_SUCCESS ( SectionStatus ) )
    47.         {
    48.             PhysicalAddress2 = MmGetPhysicalAddress(virtualAddr);
    49.  
    50.             Rem = (ULONG)PhysicalAddress2.LowPart - (ULONG)PhysicalAddress1.LowPart;
    51.            
    52.             virtualAddress = (ULONG)virtualAddress + Rem;
    53.  
    54.             *Size = length - Rem;
    55.  
    56.             ZwClose(hSection);
    57.  
    58.             return virtualAddress;
    59.  
    60.         }
    61.  
    62.     }
    63.  
    64.     if(hSection)
    65.         ZwClose(hSection);
    66.    
    67.     return NULL;
    68. }
    Например, есть у Вас страничка только -R по адресу 0xБумБум, тогда с помощью вышеприведенного кода отображаешь её физич. стр. на свою новую, но уже -RW страницу по адресу, например, 0xЖуЖу и пишешь в ЖуЖу как бы, если писал в БумБум. Вот и всё!
     
  10. retmas

    retmas New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2005
    Сообщения:
    100
    Вопрос: а зачем MmGetSystemAddressForMdlSafe???

     
  11. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia
    видимо чтобы получить доступ на запись: MmProtectMdlSystemAddress(mdl, PAGE_READWRITE);
     
  12. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    У меня только один вопрос: почему ты ловишь загрузку модулей (test.dll или что там у тебя) посредством недокументированного хука вместо того, чтобы реализовать это документированными средствами?
     
  13. cpplamo

    cpplamo New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2009
    Сообщения:
    38
    x64
    некропостер детектед=)
     
  14. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Во-первых, мимо, а во-вторых, к счастью, это ничего не меняет. Этот вопрос по большому счёту относится ко всем современным драйверописателям.
     
  15. cpplamo

    cpplamo New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2009
    Сообщения:
    38
    Ой, обиделся что-ли? :)
    Тебе то какое дело как и почему он это делает так? Тем более полтора года назад.
    Ну хочет он вот так с хуками без нотифей и делает :) Может он правда драйверописец?
     
  16. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    К сожалению, обычная notify routine, предлагаемая ядром, здесь не поможет, всё чуть сложнее. Тем не менее 100% рабочее и документированное решение сделать можно. Только оно займёт страниц 10-20 кода.
     
  17. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Если вдруг кто будет читать этот старый топик с целью извлечения знаний, то:
    это неправда.
    И вообще, писать в ридонли пользовательские страницы, которые относятся к проекции секции, сбросом WP-бита или мапированием MDL нельзя. Только через ZwProtectVirtualMemory, как в итоге и сделал топикстартер.
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    MiProtectVirtualMemory(). Ищется дизасмом NtProtectVirtualMemory.
    x64
    Ничего сложного. Можно и нотификатор повесить если нравится, далее бактрейс, или например апк доставить, которая в конце загрузки будет вызвана. Смотря что именно отлавливать нужно.
     
  19. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    О, снова недокументированный ужос, ты неисправим, похоже. Нотификатор PsSetLoadImageNotifyRoutine(), к великому сожалению, не всегда выдаёт точный путь, - следовательно, есть вероятность промахнуться. Документированно, это писать файловый фильтр, хотя бы базовый функционал типа аттача к томам и т.п., плюс вешать колбеки файловых фильтров, после чего получать путь ручками из файлового объекта и радоваться жизни. Это единственный правильный путь, ибо надёжен и документирован.
     
  20. SashaTalakin

    SashaTalakin New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2008
    Сообщения:
    261
    Медленно до тебя это доходит %)
     
Статус темы:
Закрыта.