Запись в АП процесса до его старта

Тема в разделе "WASM.NT.KERNEL", создана пользователем SlyBit, 1 апр 2009.

  1. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Добрый день.

    Мне необходимо внести изменения АП процесса (его образ) до выполнения первичным потоком его точки входа. Для этого я регистрирую нотифирутин на создание процесса, получаю его валидную базу, аттачусь к нему. Читать его память могу, а вот писать нет. В чем проблема?

    Код (Text):
    1. VOID CreateProcessNotifyRoutine(IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create)
    2. {
    3.     PEPROCESS pEprocess = NULL;
    4.     PCHAR pModuleBase = NULL;
    5.     NTSTATUS Status;
    6.    
    7.     Status = PsLookupProcessByProcessId(ProcessId, &pEprocess);
    8.     if(NT_SUCCESS(Status))
    9.     {  
    10.         KeAttachProcess(pEprocess);
    11.        
    12.         pModuleBase = *(PULONG)((PCHAR)pEprocess->Peb + 0x08);
    13.        
    14.         __try
    15.         {
    16.             *(PUCHAR)pModuleBase = 0x90;
    17.         }
    18.         __except(EXCEPTION_EXECUTE_HANDLER)
    19.         {
    20.         }
    21.  
    22.         KeDetachProcess();
    23.  
    24.         ObDereferenceObject(pEprocess);        
    25.     }
    26. }
    minidump: http://www.everfall.com/paste/id.php?uqwbn1z4b8i1
     
  2. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Права на запись забыл выставить (NtProtectVirtualMemory()).
     
  3. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Возникла следующая проблема. Отказался от NtProtectVirtualMemory(), редактирую память секции кода образа функцией WriteProcessMem() (http://www.wasm.ru/forum/viewtopic.php?pid=264627). Но вот внесенные изменения также записываются в файл образа. Как это можно избежать?
    Спасибо.
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ну ты просто-напросто пишешь напрямую в буффера менеджера кеша походу, которые скидываются потом на диск, когда замечается, что они изменены.
    Избежать этого - отказаться от MDL и вернуться к ZwProtectVirtualMemory.
    Когда ты попробуешь через ZwProtectVirtualMemory поставить права на запись страницам таким, то тебе будет выдана частная копия страниц, в которую ты можешть вносить изменения сколько твоей душе угодно. А вот вносить изменения в оригинал с помощью MDL не стоит - будет записано на диск.
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    В CreateProcessNotify виртуальная память процесса лочится.
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    А вот я кстати не помню - в CreateProcess или в LoadImage.
     
  7. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Спасибо.

    Еще один вопрос. Если функция, например эта же ZwProtectVirtualMemory(), не экспортируется ядром и её адрес в SSDT похукан, есть возможность узнать её реальный адрес?
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    прочитать sdt из ядра на диске.
     
  9. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Верно. Не подумал. :/
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    PsLoadedModuleList очень геморно ищётся. Больше вроде как неоткуда извлечь имя ядра(ну системинфо не юзаем).
    Наверно нужно промапить:
    "ntoskrnl.exe"
    "ntkrnlpa.exe"
    "ntkrnlmp.exe"
    "ntkrpamp.exe"
    И сравнить чексумму из опционаьного заголовка с текущей в заголовке ядра. Или как есчо ?
     
  11. SlyBit

    SlyBit New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2008
    Сообщения:
    43
    Clerk

    На winXp SP2, winVista SP1 нормально работает:

    Код (Text):
    1. ULONG dwAddr = 0;
    2.  
    3. __asm {
    4.     mov eax, fs: [0x34]
    5.     mov eax, [eax + 0x70]
    6.     mov dwAddr, eax
    7.     }
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    SlyBit
    KdVersionBlock ?
    Нее, это слишком ненадёжно. Перечислять и мапить модуля альтернатива.
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Clerk
    Не понял? DBGKD_GET_VERSION64 одинакова по определению, оффсет KdVersionBlock в KPCR не меняется с 2k до Vista.
    Почему ненадежно?
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Там подставные данные могут быть, да и вообще юзать все легкодоступные структуры не желательно.
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Clerk
    KeCapturePersistentThreadState?
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (Text):
    1.     PUCHAR cPtr, pOpcode;
    2.     ULONG Length;
    3.  
    4.     // g_PsLoadedModuleResource
    5.     for (cPtr = (PUCHAR)MmGetSystemRoutineAddress; cPtr < (PUCHAR)MmGetSystemRoutineAddress + PAGE_SIZE; cPtr += Length){
    6.         Length = SizeOfCode(cPtr, &pOpcode);
    7.         if (!Length)
    8.             break;
    9.         // call ExAcquireResourceSharedLite
    10.         if ((*pOpcode == 0xE8) && (*(PLONG)(pOpcode + 1) + pOpcode + 5 == (PUCHAR)ExAcquireResourceSharedLite)){
    11.             g_PsLoadedModuleResource = *(PERESOURCE *)(pOpcode - 4);
    12.             break;
    13.         }
    14.     }
    15.     // g_PsLoadedModuleList
    16.     for (; cPtr < (PUCHAR)MmGetSystemRoutineAddress + PAGE_SIZE; cPtr += Length){
    17.         Length = SizeOfCode(cPtr, &pOpcode);
    18.         if (!Length)
    19.             break;
    20.         // mov reg32, [Offset32]
    21.         if ((*pOpcode == 0x8B) && ((*(pOpcode + 1) & 0xC7) == 0x05)){
    22.             g_PsLoadedModuleList = *(PMODULE_ENTRY *)(pOpcode + 2);
    23.             break;
    24.         }
    25.     }
    Я как-то так искал.
    Правда давно это было. win2k3 последняя тестируемая.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ну можно и так. Можно есчо из KdInitSystem() взять.
    Поросто неохота всюду дизасм длин таскать или трассировать код.
     
  18. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    тю, там пара кб дизасм.
    можно еще меньше.
     
  19. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Тут на форуме пробегала темка от Black Parrot, его дизасм весит 13448 байт всего, пикод, мне понравился.
     
  20. n0name

    n0name New Member

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