Определение базы Ntoskrnl через KdVersionBlock на MP системах

Тема в разделе "WASM.NT.KERNEL", создана пользователем AntiFreeze, 3 июн 2009.

  1. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    Windows 2000 меня не интересует. Делаю:

    Код (Text):
    1.   mov eax, fs:[0x34]
    2.   mov eax, dword ptr [eax + 0x10]   // eax <- NtoskrnlBase
    Отлично работает на однопроцессорных системах. На многопроцессорных обламывается из-за того, что KPCR у каждого процессора свой, и _KPCR->KdVersionBlock = 0 на ядрах, отличных от нулевого.
    К примеру, на моей системе:

    Код (Text):
    1. lkd> !pcr 0
    2. KPCR for Processor 0 at ffdff000:
    3.     Major 1 Minor 1
    4.     NtTib.ExceptionList: ffffffff
    5.         NtTib.StackBase: b34eedf0
    6.        NtTib.StackLimit: b34eb000
    7.      NtTib.SubSystemTib: 00000000
    8.           NtTib.Version: 00000000
    9.       NtTib.UserPointer: 00000000
    10.           NtTib.SelfTib: 7ffd9000
    11.  
    12.                 SelfPcr: ffdff000
    13.                    Prcb: ffdff120
    14.                    Irql: 00000000
    15.                     IRR: 00000000
    16.                     IDR: ffffffff
    17.           InterruptMode: 00000000
    18.                     IDT: 8003f400
    19.                     GDT: 8003f000
    20.                     TSS: 80042000
    21.  
    22.           CurrentThread: 88e726a8
    23.              NextThread: 00000000
    24.              IdleThread: 8055be60
    25.  
    26.               DpcQueue:
    27. lkd> !pcr 1
    28. KPCR for Processor 1 at bab40000:
    29.     Major 1 Minor 1
    30.     NtTib.ExceptionList: ffffffff
    31.         NtTib.StackBase: b3c2edf0
    32.        NtTib.StackLimit: b3c29000
    33.      NtTib.SubSystemTib: 00000000
    34.           NtTib.Version: 00000000
    35.       NtTib.UserPointer: 00000000
    36.           NtTib.SelfTib: 7ffde000
    37.  
    38.                 SelfPcr: bab40000
    39.                    Prcb: bab40120
    40.                    Irql: 00000000
    41.                     IRR: 00000000
    42.                     IDR: ffffffff
    43.           InterruptMode: 00000000
    44.                     IDT: bab44590
    45.                     GDT: bab44190
    46.                     TSS: bab40d70
    47.  
    48.           CurrentThread: 8946b020
    49.              NextThread: 00000000
    50.              IdleThread: bab42e20
    Значения селектора FS различны на различных ядрах. И что хуже всего для меня, различны и DWORD'ы по FS:[0x34].

    Сначала было желание сделать:
    Код (Text):
    1.  mov eax, [0xFFDFF034]
    2.  mov KdVersionBlock, eax
    Но в таком случае теряется совместимость с Win Vista, Win 7.

    Можно в цикле выполнять код до тех пор, пока _KPCR.Number != 0, но это совсем через задницу и далеко не факт, что вообще когда-нибудь станет верно (например, если Affinity для текущего потока установлено таким образом, чтобы его код не выполнялся на 0м ядре)

    Была идея использовать _KPRCB.MultiThreadSetMaster, но его смещение различно на различных ОС, к тому же нет гарантии, что он указывает именно туда, куда нужно.

    Собственно задача: получить указатель на структуру _KPCR для нулевого ядра (без использования API). Реально ?
     
  2. SashaTalakin

    SashaTalakin New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2008
    Сообщения:
    261
    о какой совместимости может вообще идти речь если без использования апи
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Базы сегментов различны, сам селектор всюду одинаков, индексирует 6-й дескриптор в GDT, соответственно 0x30 в регистре Fs.
    Массив указателей на PCR каждого процессора находится в переменной хал HalpProcessorPCR(см. HalInitializeProcessor).
    PCR первого процессора находится по физическому адресу 0x40000, вероятно во всей линейке, нужно проверить с помощью MmGetVirtualForPhysical().
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Не то, я забыл что вам база ядра нужна :)
    Лучше классический способ - найти гденибудь указатель в ядро и просканить память вниз до хидера.
    Про KdVersionBlock вроде у Грита в блоге было.
     
  5. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    Да, конечно же у меня описка, селектор везде 0x30 - разная база сегмента.
    Насчёт массива указателей в HalpProcessorPCR я знаю, только до неё добраться ещё нужно.
    Дело в том, что KdVersionBlock даёт мне достаточно информации, а именно базу ядра, указатель PsLoadedModuleList, BuildNumber, номер сервис пака (критично для совместимости с Win2003 - в SP0/1(2) заметно отличаются структуры _KTHREAD/_ETHREAD и др.).
    У Great по теме фактически ничего нет.
     
  6. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    На Вирустехе нашёл коррелирующую тему (http://www.virustech.org/f/viewtopic.php?id=57), но решения нет.
    На самом деле задача сводится к выполнению кода на 0м процессоре (нужен аналог KeSetSystemAffinityThread, либо, что ещё хуже, использование DCP/IPI) - что фактически без API не реализуемо (на данном этапе выполения не известна ОС - универсального кода, работающего на XP - 7, думаю, не придумать); либо к поиску списка структур KPCR/KPRCB, что тоже не просто.
    В конце-концов топорный вариант с бесконечным циклом работает (как показала практика рано или поздно код выполняется на нужном процессоре), но такое решение меня не устраивает.
     
  7. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Я, вероятно, что-то не так понял, но чем DPC с указанным target processor не устраивает?
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    x64
    Проблемно без функционала ядра доставить DPC.
    AntiFreeze
    Зачем тебе нужен этот KdVersionBlock, он ищется сложнее чем само ядро, которое ты через эту инфу найти хочешь(он кстати в секции данных ядра находится). Если уж так нужно, то как и посоветовал мне Грит в том топике, реализуй все манипуляции с IPI в ручную. Можно есчо использовать прерывание 0x2e, тоесть сервисы, в таком случае где ядро знать не нужно, необходима таблица Version/ServiceId, например чтонибудь типа NtSystemDebugControl(не знаю как с совместимостью), или NtQuerySystemInformation.
    Не понятно только одно - зачем так усложнять.
     
  9. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    Clerk
    На самом деле просто обидно, что элегантное решение в несколько ассемблерных команд в итоге сведётся к банальному scandown, разбору таблицы экспорта и т.п.
    x64
    Использование DPC невозможно по той причине, что на данном этапе выполения кода не известны адреса нужных API (можно конечно самостоятельно реализовать KeInitializeDpc, KeSetTargetProcessorDpc (не сложно) и KeInsertQueueDpc (надо ковырять))
    Но это, ровно как и ручная реализация IPI, усложнит метод настолько, что про него можно будет сказать - цель не оправдывает средства.
    В общем ясно, повожусь ещё день с этой проблемой, и если ничего толкового не придумаю, буду использовать старые проверенные методы.
    Всем спасибо.
     
  10. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    Сегодня проверил. На XP-2003 действительно MmGetVirtualForPhysical() от 0x40000 возвращает правильный виртуальный адрес. На Vista и Win 7 - нет. Что именно не так, то ли PCR нулевого процессора находится в физической памяти не по тому адресу, то ли функция неверно преобразовывает этот адрес (что, думаю, маловероятно) - разбираться не стал.
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    AntiFreeze
    Можешь помотреть что возвратит MmGetPhysicalAddress для PCR[0] на Висте и 7 ?
     
  12. AntiFreeze

    AntiFreeze Дмитрий

    Публикаций:
    0
    Регистрация:
    26 июн 2008
    Сообщения:
    65
    Посмотрел на виртуалке и на реальной машине:

    На Вин7 виртуальный адрес 0x82952C00, физический, согласно MmGetPhysicalAddress - 0x2952C00
    Vista SP1, виртуальный 0x81D2F800, физический - 0x1D2F800

    Причём адреса "плавают" после перезагрузок.
     
  13. Clerk

    Clerk Забанен

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