Получить EIP потока

Тема в разделе "WASM.NT.KERNEL", создана пользователем wasm_test, 30 июл 2007.

  1. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Требуется получить EIP потока, отработавшего свой квант времени. Ну то есть просто выдрать EIP из его контекста. Интересуют лишь те потоки, которые были прерваны во время выполнения в 0 кольце.

    Пробовал варианты:
    - PsGetContextThread(). Для всех потоков упорно EIP = ntdll!KiFastSystemCallRet
    - Получить адрес из KTRAP_FRAME Thread->Tcb.TrapFrame->Eip, снова EIP = ntdll!KiFastSystemCallRet либо -1 для потоков процесса System
    - Посмотрел сорсики ядра, нашел какието махинации с KTRAP_FRAME: (PKTRAP_FRAME)((PUCHAR)EThread->Tcb.InitialStack - PSPALIGN_UP(sizeof(KTRAP_FRAME),KTRAP_FRAME_ALIGN) - sizeof(FX_SAVE_AREA)) - получается какойто непонятный указатель на KTRAP_FRAME. Оттуда либо 0, либо -1 либо ntdll!KiFastSystemCallRet

    Соответственно вопросы:
    1) Относится ли KTHREAD.TrapFrame к сохраненному контексту потока?
    2) Что за махинации с адресом KTHREAD.InitialStack и относитчя ли это к сохраненному контексту потока?
    3) Где вообще сохраняется контекст?
    4) По поводу ntdll!KiFastSystemCallRet - может я чегото непонимаю в переключении контекста, но почему у всех потоков EIP указывает туда, как будто их прервали в юзермоде сразу после возврата по sysexit
    5) Не в тему и не особо интересует, но почему EIP = FFFFFFFF у потоков процесса System ? Это Worker Threads чтоли которые ожидают рабочих элементов или что?

    Смотрел код KiSwapThread;SwapContext не нашел ничего относящегося к переключению контекста потоков (плохо смотрел?)
     
  2. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    Ха, а вот как происходит переключение потока
    так вот возврат в стеке разве esp у них одинаковы (там адрес) а ntdll!KiFastSystemCallRet это что-то типа iretd

    Да еще, а что SoftIce не катит трассировка переключения потоков ??
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    это просто ret. А вообще смысл предложения твоего я не вкурил)

    Равносильно дизасмингу или просмотру асм сорсов KiSwapThread. Оставил этот вариант на крайняк.
    Вдруг кто знает в теории как переключается контекст потока в винде, точнее куда он сохраняется.
     
  4. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    Короче посмотри стек потока (он у каждого потока свой) и при прерывании при переходе в ring0 там сохраняется адрес возврата
     
  5. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    О а кстати это дельная мысль... при прерывании от таймера.. угу.. надо глянуть
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Кстати у всех потоков PreviousMode = 1, получается в ядре ни один поток не прервался? Что за чудеса.
     
  7. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    по поводу EIP = FFFFFFFF у потоков процесса System, тут все проще те сами высвобождают квант времени или в сосоянии hlt, т.е. при переключении на поток system (основной) адрес не совсем нужен
     
  8. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    Все драйверы это какбы dll для приложений и в большинстве случаев выполняются в контексте и потоке приложения user mode причем свои потоки создают крайне редко (я в нормальных драйверах не встречал, разве только в PnP) Т.е. в норме потоков в kernel mode - system и еще один два не более..
     
  9. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    PROFi
    Я не про то. Допустим, какойто поток от какогото приложения начал выполнять, ну скажем, NtSuspendProcess. Он перешел в ядро, выполнил там часть кода (допустим референснул объект по хендлу и уже подготовился саспенднуть процесс) и тут его планировщик прервал - мол хватит, твой квант истек. А поток выполнялся в ядре внутри NtSuspendProcess. Вот я и говорю - получается что ни один поток не прервался в режиме ядра. Мистика?

    ADDED:
    Вообще понятия "поток в kernel mode" довольно расплывчатое, ибо потоку без разницы где выполняться =) Сейчас он в юзермоде, потом вызвал какуюнить апишку и ускакал внутрь ядра.
     
  10. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great


    PreviousMode это не константа процессора, а лишь переменная Windows, посмотри в стеке сегмент возврата. А PreviousMode береттся из контекста текущего потока, а последний вызвал NtSuspendProcess, но ведь от этого он не стал потоком ядра, посто код ядра исполняется потоком пользовательского режима... Блин Во накрутил
     
  11. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Я имею в виду я ее не просто так взял, а из KTRAP_FRAME того же :)
    Ну в принципе достаточно просто старший бит EIP проверить, если установлен, значит адрес >2Gb. Хотя надежнее по сегменту - код ринг0 можно выполнять и ниже 2Гб...
    Ща попробую с просмотром стека повозиться.

    Кстати, KiFastSystemCallRet это просто RETN так что ни про какие сегменты тут речи быть не может..
     
  12. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    я ее не просто так взял, а из KTRAP_FRAME того же :)

    Ну и что поток то ослася user mode, это процессор теперь работает в ring0, но все структуры потока не изменились, а вних четко UserMode вот и получается, что даже при прерывании из режима ядра PreviousMode = 1
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Да ты прав.. туплю.

    И все же странновато что планировщик оставляет EIP=KiFastSystemCallRet. Хотя сегмент cs наверное перезагружается отдельно.. Хотя имхо было бы проще как ты сказал - оставить адрес на IRET и в стек пихнуть CS с EIP'ом. Ну.. что сделано то сделано=)
     
  14. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    И все же странновато что планировщик оставляет EIP=KiFastSystemCallRet

    Ничего странного если учесть, что Windows работает и на Itanium и на Alpha процессорах, там все немножко подругому, а поскольку Win использует Flat модель памяти, то ему не нужно значений cs для возврата :)
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Прога Sleeper:
    .code
    start:

    push -1
    call [Sleep]

    ; never reach here
    ret

    .end start

    Дров выдает для процесса Sleeper.exe

    EPROCESS = f8fabda0, Name = sleeper.exe
    Threads [1]:
    817a7878, proc f8fabda0, eip 7c90eb94, esp 0006ff50, [esp]: 7c90d85c 7c8023ed 00000000 0006ff80

    И правда, стек верный (это результат трейса. Sleep -> SleepEx -> ZwDelayExecution -> KiFastSystemCall с остановом на SYSENTER):

    0006FF50 7C90D85C RETURN to ntdll.ZwDelayExecution+0C
    0006FF54 7C8023ED RETURN to kernel32.SleepEx+51 from ntdll.ZwDelayExecution
    0006FF58 00000000
    0006FF5C 0006FF80

    Но этот поток был прерван принудительно вызовом ZwDelayExecution -> KeDelayExecutionThread -> KiSwapThread.
    Но если поток законно прерван по истечении кванта времени, то у него все равно в стеке какието адреса из kernel32 и/или ntdll.

    Попробую щас еще быстренько наваять другой дров, который создает девайс и в обработке io control'а засыпает навсегда.
    Чтобы юзермодный поток вызвал DeviceIoControl и уснул в режиме ядра.

    Еще попробую сделать JMP $ чтобы посмотреть как у потока принудительно отбирают квант времени..
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Для проги, у которой на точке входа EB FE (jmp $):

    EPROCESS = ffb71a20, Name = infloop.exe
    Threads [1]:
    ffb96418, proc ffb71a20, eip 00401000, esp 0006ffc4, [esp]: 7c816d4f 012dd728 7c90e1fe 7ffdf000

    Что-то тут не чисто=) Тут eip верный
     
  17. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    Что тут интересного, ведь даже task manager выдает, что такой поток завис :) а потому ему сразу резко урезается кванты времени (во всяком случае на 2х процессорной машине) Т.е. как только будет переход на другой процесс - поток будет отмечен как не отвечающий, и время его работы урежется ... С этим столкнулся впервые на XP.
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ну я про EIP говорю, тут он как ни странно вполне нормальный и указывает на команду EB FE.
     
  19. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Great

    А что тут странного, ведь я говорю что если нормальному потоку выделяется полный квант времени, то у зависшего большая часть кванта отбирается насильно и делается это в другм месте, видимо поэтому и eip сохраняется. Но лучше пройтись SoftIce ом для более подробного разбора, к сожалению тут мои знания пока туманны.
     
  20. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Я не думаю, что в этом "другом месте" переключение контекста так уж сильно отличается от принудительного переключения. Afaik, там тоже дергается та же KiSwapThread