По ходу обсуждения темы "Методика тестирования" решил наконец проверить давнюю идею о возможности обнаружения постороннего вмешательства в прогу по измерению времени доступа к странице памяти. Суть простая: при первом обращении к странице кода или данных возникает исключение page fault, которое винда обрабатывает не менее нескольких тысяч тактов (а в случае подкачки с диска на порядки больше). Если отладчик или дампер читают код и данные проги из загруженного образа, то соответсвующие страницы памяти оказываются инициализированными и при последуещем обращении к ним отказа не возникает и время чтения\записи или call\ret оказываются значительно меньше. "Любознательная" OllyDbg на эту удочку ловится (независимо от опций анализа, хотя все не проверял) и похоже читает и анализирует весь код или по крайней мере те страницы, куда ведут call и jmp. C данными Оля ведет себя скромнее и читает только первую страницу data (для отображения в окне дампа). Поэтому можно просто прочитать дворд или сделать вызов простенькой процедурки из заведомо неинициализированной страницы кода и замерить число тактов по RDTSC - если меньше ~2-3 тыс., значит кто-то тут уже побывал Справедливости ради нужно заметить, что не все отладчики такие любопытные, например со "скромным" W32Dasm такой трюк не проходит - он читает страницы только по мере обращения к ним (например после go to address). Метод в определенном смысле "одноразовый", т.е. к одной странице можно обратиться только один раз после чего она ес-но становится инициализированныой, но с другой стороны в "увесистой" проге таких страниц м.б.достаточно много. В dll ес-но от этого метода толку мало - (все ?) страницы с релоками инициализируются виндой при загрузке В аттаче тестовый примерчик (фасм), замеряющий число тиков на первое обращение к 1-й странице секции data? (неинициализированные данные - с диска не грузятся) и 2-й странице секции кода:
При первом запуске НЕ под отладчиком: --------------------------- IsDebuggerPresent by RDTSC --------------------------- Ticks for access to page 000000000000000000004249 <- data 000000000000000000002722 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: Yes --------------------------- ОК --------------------------- )
Имхо, это дело может осложняться наличием не менее любопытствующих антивирей/файволов, которые вполне могут просканировать адресное пространство свежезагрузившегося процесса. Так что способ назвать надежным нельзя. З.Ы. У меня по крайней мере показало отсутствие отладчика.
Asterix, alpet С антивирями это да ... Но все таки интересно было бы сравнительные цифры увидеть - без отладки и под Олей, т.к. порог в 3000 я поставил от балды - под 9х приподнял, а под XP под отладкой у меня стабильно меньше 1000 получается (поэтому и ОС желательно указывать)
без отладки: 000000000000000000012285 <- data 000000000000000000004962 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: No под олей: 000000000000000000000546 <- data 000000000000000000000288 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: Yes под pebrowse: 000000000000000000000563 <- data 000000000000000000000246 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: Yes ах да, тестировалось под xpmce sp2
Fry Chicken Вот образцовый тест, спасибо PS: А порог видать несколько завышен. Было бы 1500 и у Asterix'а не было бы повода так язвительно улыбаться )) Asterix Вобщем-то, ~2700 это нормальное значение. Желательно еще цифирьку увидеть под Олей
Хм, а меня под Олей: 000000000000000462725971 <- data 000000000000000493770394 <- code oooooooooooooooooooo3000 <- limit IsDeguggerPresent: No =) Оля v.1.10
Под OllyDbg: Код (Text): --------------------------- IsDebuggerPresent by RDTSC --------------------------- Ticks for access to page 000000000000000000000152 <- data 000000000000000000000308 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: Yes
Fry Chicken Думаю тут привелегии не должны влиять. Скорее влияют ОС, Hyper-Threading и случайные или умышленные факторы (как у mix_mix , ну и разумеется "шпионы", которые могут без спроса лезть в память процесса Asterix Вот видишь, разница то существенная. Нужно только порог оптимально выставить
без отладки: 000000000000000000025592 <- data 000000000000000000015884 <- code oooooooooooooooooooo3000 <- limit IsDebuggerPresent: No под олей: 000000000000000000000856 <- data 000000000000000000000242 <- code oooooooooooooooooooo3000 <- limit xp sp1 ollydbg 1.10 IsDebuggerPresent: Yes
mix_mix > "при трассировке rdtsc другие результаты показывать будет" Это же частный метод, проверяющий инициализацию страницы - если время доступа слишком маленькое, значит кто-то эту страницу уже читал. После него можно и трассировку проверить или время обработки исключения - тут нужно наоборот быть уверенным, что страница уже инициализирована и время доступа к ней д.б. заведомо меньше некоторой величины, поэтому завышенные значения будут сигнализировать о возможной отладке Asterix Кстати у DDA без отладки получаются те же цифры 15-25 тыс., что и у меня под XP SP2 на P4 с HT-on. При HT-off я еще не проверял - позже посмотрю. А вот твои 2.7 тыс - на минимальном пределе, интересно под какой ОС и на каком проце ? Что касается "сомнительный метод на голову реверсеров" и "прикручивать к криптору", то шила в мешке не утаишь и лучше знать\обсуждать возможные хитрости и думать как их обойти, чем надеятся на "авось пронесет" А вот о запрещении и перехвате rdtsc говорят много, но ничего конкретного кроме сырого дубового FakeRDTSC чего-то не видно на горизонте. Запретить то несложно, как говорит vоlodya - "сорцы есть, можно и нужно менять ". Но остается "мелочь" - решить как и какие результаты куда подсовывать, особенно если этих rdtsc десятки и цифры и условия больше\меньше у них могут быть разными. Может в данном случае с замером времени доступа к странице проще восстанавливать записи PTE, какими они были до чтения страниц или как-то извращаться с PAGE_GUARD...