NtCurrentTeb возвращает неправильный адрес структуры TEB, почему?

Тема в разделе "WASM.BEGINNERS", создана пользователем amvoz, 1 дек 2011.

  1. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    Друзья! Функция NtCurrentTeb () недокументирована, возвращает через раз неправильный адрес с тукруры TEB, это структура блока окружения потока (или как она там расшифроваывается), тоже недокументированная. Вот код:
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3.  
    4. using namespace std;
    5.  
    6.  
    7. int main() {
    8.  SetConsoleCP (1251);
    9.  SetConsoleOutputCP (1251);
    10.  
    11.  
    12.  printf ("%x\n", (unsigned int) NtCurrentTeb());
    13.  
    14.  getchar ();
    15.  return (0) ;
    16. }
    После чего приаттачиваемся OllyDbg к процессу и наблюдаем в регистре fs совсем другое значение. Типичные значения: программно получаю 0X7ffdf000, а в отладчике 7ffde000 (с различными варицацями: 0X7ffdd000), что делать? Спасибо, кто откликнется.
     
  2. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    Щас посмотрел реализацию NtCurrentTeb(), оказывается, вся-то реализация и заключается в:
    PUSH EBP
    MOV EBP,ESP
    PUSH EBX
    SUB ESP,10
    MOV EBX,DWORD PTR FS:[18]
    MOV DWORD PTR SS:[EBP-8],EBX
    MOV EAX,DWORD PTR SS:[EBP-8]
    ADD ESP,10
    POP EBX
    LEAVE
    RETN

    Вот и всё, и этот код выполняется в главном модуле, а не где-то в dll-ках. Вот я жирным выделил нахождение непосредственно адреса TEB, ну да, всё правильно. Немного смущает, зачем они берут fs:[18], а не fs:[0], там ведь одно и то же, ну да это их дела. То есть, получается NtCurrentTeb() железно не врёт. Но почему тогда врёт регистр fs? А ещё я заметил, что эта ложь наблюдается только при присоединении к потоку, а если сразу процесс запуситить в отладчике, то не наблюдается.
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    amvoz
    Адрес TEB и значение в fs — абсолютно разные вещи. Адрес TEB и должен колебаться где-то в районе 0x7ffde000, а fs содержит селектор сегмента (0x3b), база которого находится по адресу TEB. Кроме того, у каждого потока свой TEB, соответственно вручную получаете адрес одного TEB'а, а после аттача OllyDbg смотрите адрес другого.
    fs:[0] даже близко не содержит адрес TEB, он содержит указатель на продолжение связного списка SEH с адресами обработчиков исключений. Естесственно по fs:[18] и fs:[0] абсолютно разные значения.
    Он не врёт.
    Опять таки. Адреса TEB разных потоков видите.
     
  4. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    653
    у вас слишком мнго информации, поэтому я буду переспрашивать дозировано
    Очень интересно. ПРименим формальную логику тык скыть:

    1) Вначале структуры TEB лежит структура TIB? Лежит.
    2) Следовательно, адреса TEB и TIB равны
    3) Дословно: "На Intel Win32 платформе, регистр FS всегда указывает на текущий TIB." (Взял у Мэта Питрека, здесь: http://www.wasm.ru/article.php?article=Win32SEHPietrek1)
    4) Значит вывод: "На Intel Win32 платформе, регистр FS всегда указывает на текущий TEB"
    5) Следовательно утверждение о том, что "Адрес TEB и значение в fs — абсолютно разные вещи" неверно

    Просто скажите мне в каком из пунктов я неправ и это будет эффективнее, чемя щас буду узнавать, что такое селектор сегмента. Извините.
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    amvoz
    В том месте, где буквально понимаете слово "указывает" в приведенной цитате. В данном случае под "указывает" понимается то, что я написал касательно селектора и базы сегмента. Собственно, Вы, вероятно, и сами в курсе, что регистр fs имеет длину в 16 бит (надеюсь, мне по этому поводу сейчас никто не начнёт рассказывать про теневую часть), а значит не может содержать указатели вида 0x7ffde000. Если же хотите знать больше, то всё-таки придётся почитать про механизм сегментации в защищённом режиме и селекторы сегментов в частности.
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    amvoz
    Аттач отладчика к процессу происходит путем создания доп.потока, который вызывает DbgBreakpoint, на котором и происходит останов отладчика - соотв-но и fs:0 в момент останова указывает на TEB этого доп.потока, а не твоего основного. Глянь в View\Memory и увидишь рядом две строчки data block - of main thread это адрес TEB твоего основного потока, а второй of thread ??? - дополнительного, на котором в данный момент осуществлен останов и соотв-но fs:0 указывает именно на его TEB

    Ну, и не путай загрузку дворда, лежащего по адресу fs:[0], с самим линейным адресом fs:0, который в чистом виде просто так не получишь, поэтому и "придумали" хранить адрес TEB в нем самом по смещению fs:[18]