Пишите пока Акуйла спит Medstrax Пожелания излишни, себе я уже доказал что трассировка ускоряет исполнение кода(ну не без вмешательства в планировщик). leo Именно планирование позволяет это обойти(гденибудь в чистом досе это невозможно).
именно по этой причине способ не надежен. Как-то хочется как всегда универсального способа Да и сама по себе оценки времени исполнения кажется не надежной, нельзя на нее точно положиться как раз изза случайной модели планирования. Я бы не отважился засунуть антитрассировочный код с замерами тиков исполнения в свою программу.
Кстати ребята скажите каким средсвом процессора или ОС сделать CPUID привигированной инструкцией. Я ведь не могу сделать MOV привилигерованной инструкцией, лень лесть в талмуд, тяжолый он, хоть и под рукой.
Clerk Я вас тоже! Вы на большой высоте в ваших технических работах, очень приятно видеть как вы развиваетесь. Но не подскажете ли вы мне как сделать CPUID привилигерованной инструкцией (сори за возможно глупый вопрос)?
Osen offtop по поводу ненадежности оценки времени исполнения и "случайной модели планирования": "Точно положиться" нельзя ни на что, но в каждой случайности есть своя закономерность Как тебе такой опус: "Как раз изза случайной модели планирования" дорожного движения и террористических операций Алькаиды "я бы не отважился" ездить на работу в свой небоскреб, т.к. нельзя точно сказать за какое время и каким маршрутом я доберусь до места и не окажется ли это "место на кладбище". Буду сидеть дома, зубрить тер.вер., мат.статистику и теорию обнаружения\фильтрации сигналов на фоне помех пока не наступит полное просветление
blast Спасибо, воткнул. leo Да, я согласен, там есть закономерность и можно взять значение, которое будет отличаться с отладчиком и без. Но решились бы вы использовать эту технику в программе, которая критична к запуску и работе без отладчика, ведь на вашем компьютере это может работать 100 раз из 100 запусков, но что будет на других, как там сработает это? Я лично не могу на 100% быть уверенным в таких способах антиотладки, поэтому никогда не буду использовать их в своих программах. А вы? Если используете, то поделитесь опытом и статистикой основанной на фидбеках пользователей вашей программы.
leo Далее под отладкой я понимаю автоматическое прерывание исполнения кода и передачу управления отладчику при определённых событиях, (в случае трассировки это не та которая исполняется щёлканьем F7 в отладчике). Чтобы обнаружить отладку по замедлению времени исполнения можно: 1. Сравнить участок кода исполняющийся без отладчика и под отладчиком. Исполнить отлаживаемый код без отладчика неполучится(можно использовать манипуляции с несколькими процессами, использовать потоки системных процессов и тд., но это всё бесполезно поэтому вариант отпадает). 2. Использовать зависимость скорости исполнения кода от производительности системы. Тут куча подводных камней возникает. Необходимо както определить реальную производительность системы, причём она непостоянна и изменяется в широких пределах. Производительность системы разумеется должна определяться вне отлаживаемого кода. Например. Считаем мы тск, сделаем цикл задержки и снова считаем тск, определим разницу в значениях счётчика, получим dv/n. Как узнать что нас отлаживают не зная в каких пределах должно изменяться это отношение без трассировки в этой системе ? - никак. В принципе можно сделать огромную задержку, измеряемую десятками секунд, минутами - тогда да, можно сказать что либо нас отлаживают, либо мы гденибудь на 386-м. А вдруг по каким либо причинам потоку станет выделяться мало процессорного времени, как например у меня киса временами подвешивает систему - как судить что нас не трассируют - никак. А ведь софт который может запускаться только под определенной осью - плохой, есчо хуже если будет временами выдовать непонятные сообщения типа 'обнаружена отладка'. 3. Исполняем определённый код в юзермоде и тотже код в режиме ядра. По задержке отладка будет обнаружена. 100% эффективно. Но только для отладчика который прекращает отладку при смене кольца защиты. К примеру юзермодные отладчики - отлаживается код в режиме пользователя, при переходе в режим ядра отладка прекращается до возврата обратно в юзермод. Разумеется в режиме ядра код исполниться быстрее. При этом ненужно исполнять свой собственный код в кернелмоде, достаточно ядра. Простейший пример: KiGetTickCount: cmp [esp+4],1Bh ;KGDT_R3_CODE OR RPL_MASK jnz short @f mov eax,dword ptr cs:[KeTickCount] mul dword ptr cs:[ExpTickCountMultiplier] shrd eax,edx,24 iretd @f: [...] - хэндлер 0x2A прерывания. Делаем теже инструкции в юзермоде(исключив iretd и Int, затем по числу тактов скорректируем время исполнения без них), разумеется никакие указатели в ядро не нужны. И юзаем допустим тысячу циклов нашего кода и тоже число Int2A. Получим dt и скорректируем(число тактов для каждой инструкции фиксировано). Разница без отладки будет совсем малой, вносимой планированием. Это только пример. Разумеется отладчик режима ядра этим не словить. Отсюда вывод - нет смысла защищатся от автоматической отладки отладчиком режима ядра.
Clerk Простой код исполняется не "системой", а процессором. Нормальная система вмешивается и прерывает исполнение кода потока не на каждой инструкции, а лишь периодически\ эпизодически. Существует масса инструкций, которые на всех процах исполняются за одинаковое или примерно одинаковое число тактов, поэтому если не брать в расчет HT, то определив время исполнения небольшого куска кода на одном проце, ты получишь примерно те же цифры и на других процах. Поэтому замерять контрольное значение в реал-тайме на конкретной тачке вовсе не обязательно, тем более, что автотрассировка и другие вмешательства отладчика (например, обработка исключения) вносят задержки, на порядки превышающие время "свободного полета". Поэтому если измерять не время, а такты процессора, и не на больших интервалах, а на коротких и затем анализировать массив измерений, отсекая выбросы за счет прерываний и сглаживая "шумы" за счет HT, то можно получить достаточно надежную оценку времени исполнения в тактах. При таком подходе отладчику нужно будет провести собственные измерения числа тиков, которые уходят у него на обработку трассировочного прерывания, копить сумму этих значений для каждого прерывания и затем корректировать результат каждого rdtsc и\или QueryPerf.. на это значение. Но от такой подмены можно\нужно юзать доп.способы контроля, например замер числа тиков обработки собственного исключения и контроль общего времени исполнения - тут уж у отладчика будет голова болеть о том, где и насколько корректировать значения rdtsc, GetTickCount и т.п. Морока одним словом PS: 100% защит ес-но не бывает, поэтому вопрос только в потраченном времени и усилиях на разработку защиты и на ее обход, ну и ес-но в целесообразности всех этих усилий, т.к. на чисто спортивном интересе далеко не уедешь
leo Чтото не пойму смысл что ты написал. А как определить ? Заюзать какойлибо счётчик - получится всеголишь дельта времени, чтобы однозначно обоснавать наличие отладки нужно сравнить это dT с известной величиной. А с чем сравнить ? Нужно знать скоко времени этот код будет выполняться без отладки, либо другой код с известным числом тактов. Необходима не относительная, а обсолютная точка отсчёта. Код который будет исполнен без отладки - единственный жизниспособный вариант это юзать прерывания. Например есть участок кода исполнение которого занимает 1000 тактов процессора(шины). Допустим на исполнение этого кода уйдёт 100 микросекунд. Ну и куда двигаться дальше, как узнать предел ?
Дальше читай: "Поэтому если измерять не время, а такты процессора, и не на больших интервалах, а на коротких". В отличие от времени, число тактов не зависит от частоты и для определенного набора инструкций слабо зависит от модели проца. И к тому же по rdtsc можно определять малые промежутки в десятки-сотни тактов (= наносекунд на нынешних гиговых частотах), и тем самым повышать надежность контроля, т.к. с одной стороны и вероятность вклинивания виндовых прерываний снижается на порядки и число измерений можно провести огромное кол-во пока юзер глазом не упел моргнуть В статистике есть такое понятие "априорные данные", т.е. полученные из теоретических соображений или на основе предыдущего опыта. Например, известно, что на всех процах команда add eax,edx выполняется за 1 такт (на первых P4 побыстрее- 0.5 в теории, но по жизни максимум 3 штуки за 2 такта, т.е. ~0.7). Тогда цепочка из 100 зависимых add eax,edx в нормальных условиях должна выполняться грубо говоря за 60-120 тактов. Если меньше, значит кто-то rdtsc "подкручивает", если существенно больше, значит или винда поток приостановила или трассировка рулит - проводим десяток-сотню таких измерений и видим, если редкие одиночные выбросы - списыаем на винду, если стабильное завышение - значит трассировка. (Как я уже говорил, эта идилия нарушается на P4 с включенным HT, поэтому нужны доп.навороты)
leo Да, ты прав. Нельзя про тск забывать. Ну с rdtsc проблем в отличае от cpuid нет. Если при трассировке мне известны все инструкции между двумя чтениями тск, как ты уже сказал: Пересчитать значение не будет проблемным.