Clerk Хм... действительно. Облом. И тем не менее для call'ов при trace over (или просто F8) Olly снимает TF и ставит int3 на следующую инструкцию после call (хотя можно в настройках указать, чтобы использовались hardware breakpoints). Подозреваю, что 2FED запускал trace over. Я для того и привёл в посте 56 "трассировка в обход под Olly", чтобы поверили. У меня ж результаты такие же: первый и второй MessageBox'ы выдают очень похожие результаты.
l_inc Я пробовал запуск множества потоков исполняющих данный код в цикле. Пока система не перегружена результаты идеальны. При перегрузке системы(запуск нескольких игр, использована вся оперативка) спустя несколько минут(миллионы итераций) возвращается некорректное значение, но думаю это не проблема - оно определяется условием, причём приоритет потоков - нормальный.
А хотя какая разница? С trace into получилось бы, что обе попытки измерения под трассировкой, а с trace over, что обе без трассировки. В любом случае числа получились бы похожими. Короче, сам ерунды наплёл, а теперь сам разгребаю.
Следует сказать есчо про один системный механизм, это является весьма эффективным способом обнаружить трассировку. Нормально контролировать поток после того как он сменит кольцо вызвав сервис из юзермода непредставляется возможным, это определяет всю безопасность и стабильность системы. Существует механизм, это обратные вызовы ядра. Когда после вызова сервиса ядро исполняя его передаёт управление обратно в юзермод для исполнения некоторых действий в юзермоде, после чего управление возвращается обратно в ядро, продолжая исполнять сервис. Этот механизм широко используется теневыме сервисами. На стороне ядра это KeUserModeCallback(), на стороне юзермода это KiUserCallbackDispatcher(), далее поток возвращается обратно в ядро посредством прерывания KiCallbackReturn(0x2B). Принцип в том, что поток вызывает теневой сервис, таких множество, к примеру NtUserCreateWindowEx, ядро в процессе обработки его передаёт управление в юзермод, вызывая определённую процедуру обратного вызова. Обработка начинается с KiUserCallbackDispatcher(),тут важный момент - некоторый регистры контекста потока, в частности регистр флагов имеют такое значение, которое было у них на момент вызова теневого сервиса, тоесть тотже NtUserCreateWindowEx вызванный с установленным TF, есчо до возвращения управления после обработки вызывает калбак и регистр флагов в контексте содержит взведённый TF. В случае с не теневыми сервисами вызов их с взведённым TF вызывет исключение только после возврата из сервиса, но вызванный теневой сервис с взведённым TF привидёт к разворачиванию исключения, при входе в ядерный калбак на стороне юзермода. TEB.Tib не изменяется при входе в KiUserCallbackDispatcher(), поэтому перехватывать ничего не нужно. Следует установить сех-фрейм и вызвать сервис, который вызовет калбак. Возникнет отладочное исключение, после исполнения первой инструкции калбака, обработчик установит флаг - признак трассировки, выполнит возврат для продолжения исполнения калбака, затем по возврату из сервиса считает этот флаг.
Clerk Один вопрос к вышесказаннному. При вызове сервиса, который вызывает callback, через int флаг TF будет снят. TF будет выставлен в KiUserCallbackDispatcher или вернётся на место только на следующей инструкции после int?
l_inc Не имеет значения как вызван сервис, через прерывание либо быстрый вызов. TF будет выставлен как только поток возвратится в юзермод, тоесть на KiUserCallbackDispatcher(), после исполнения первой инструкции возникнет отладочное исключение, в контексте потока сохранённом в стеке хэндлера исключений Eip будет указывать на следующую инструкцию.