Трассировщик исполнен в режиме ядра, перехвачен ISR #DB. Также перехвачены в юзермоде KiRaiseUserExceptionDispatcher, KiUserExceptionDispatcher, KiUserApcDispatcher, KiUserCallbackDispatcher, при возврате на них управления ядром хэндлеры взводят TF. Возможные варианты детекта: 1. Получение регистра флагов инструциями pushf, pushfd Сохраняют в стеке регистр флагов, если установлен TF то выполняется отладка. 2. Получение контекста потока посредством NtGetContextThread. Если сервис вызван для текущего потока, то Context.regEFlags(EFLAGS_TF) такой как он был на момент вызова. Отладочное исключение возникнет после возврата из сервиса. Значения Context.regEdx и Context.regEcx не зависят от TF. 3. Содержимое регистров по возврату из сервиса(sysenter, int). - Если вызывается инструкция sysenter со сброшенным TF, то по возврату регистр Edx содержит указатель на KiFastSystemCallRet, регистр Ecx содержит указатель на стек(значение регистра Esp на момент вызова, тоже что и содержит Edx перед вызовом). - Если вызывается инструкция sysenter с установленным TF, то по возврату регистр Edx содержит -1, регистр Ecx содержит 1. - Если вызывается инструкция Int2E(KiSystemService) со сброшенным TF, то по возврату регистр Edx содержит указатель на инструкцию следующую за Int, регистр Ecx содержит указатель на стек(значение регистра Esp на момент вызова). - Если вызывается инструкция Int2E с установленным TF, то по возврату регистр Edx содержит -1, регистр Ecx содержит 0x101(поля PreviousMode, EnableStackSwap, LargeStack, ResourceIndex из ETHREAD.Tcb(четыре байта начиная с PreviousMode). Это имеет смысл только для прерываний KiSystemService(0x2E), KiDebugService(0x2D), KiSetLowWaitHighThread(0x2C) 4. Контекст потока при возникновении исключения. При возникновении исключения контекст содержит регистр флагов на момент исполнения инструкции. Если установлен TF то поток трассируется. 5. Сброс TF с помощью сервисов NtContinue и NtSetContextThread. При вызове с установленным TF управление передаётся на инструкцию по адресу Context.regEip, но TF сбрасывается, что приводит к выходу из под трассировки. 6. Установка и чтение TF. Поток устанавливает TF и затем считывает его. Если он окажется сброшен, то поток трассируется. Какие есчо есть способы обнаружить трассировку ?
staier Ненадёжно, неэффективно. Время исполнения незначительно больше. Нельзя однозначно судить что выполняется трассировка.
Это нето ? Код (Text): mov edx, 7FFE0000h mov eax, [edx] mul dword [edx+4] shrd eax, edx, 18h mov ebx, eax db 100 dup(90h) mov edx, 7FFE0000h mov eax, [edx] mul dword [edx+4] shrd eax, edx, 18h mov ebx, eax sub eax,ebx cmp eax,1000 jge nogood
Код (Text): mov edx, 7FFE0000h mov eax, [edx] mul dword [edx+4] shrd eax, edx, 18h Енто ж бубль.. GetTickCount
Угумс. Код (Text): ;Это и есть псевдокод GetTickCount mov edx,7FFE0000h ;Указатель на UserSharedData assume edx:PKUSER_SHARED_DATA mov eax,[edx].TickCountLow mul [edx].TickCountMultiplier shrd eax,edx,18h mov ebx,eax db 100 dup(90h) ;Задержка mov edx,7FFE0000h ;Указатель на UserSharedData assume edx:PKUSER_SHARED_DATA mov eax,[edx].TickCountLow mul [edx].TickCountMultiplier shrd eax,edx,18h ;mov ebx,eax <- Ето не нужно :) sub eax,ebx cmp eax,1000 jge nogood ;-------------- Аналогично ------------------- Call GetTickCount mov ebx,eax db 100 dup(90h) ;Задержка Call GetTickCount sub eax,ebx cmp eax,1000 jge nogood Не будет это детектить ничего, незря ведь трассировщик в режиме ядра пишется. Если взять не 100 dup а тысяч в 10 раз больше то может спалится. Временные зависимости не подходят.
blast Имел ввиду четыре точки, на которых в юзермод возвращается управление. Указатели на них в неэкспортируемых переменных ядра, там и подменяются. В ntdll ни один байт не меняется.
Изза установленного флага RF перед возвратом из сервиса вызванного с установленным TF(посредством iretd), исключение не возникает сразу после Int или Sysenter инструкций, а только после исполнения следующей за ними. Тоесть если вызвать с установленным TF код: Код (Text): Int 2Ah ;KiGetTickCount pushfd pop eax Исключение возникнет после исполнения инструкции pushfd(указатель на pop eax). (п.6) Установить TF можно не только инструкциями popf и popfd, но есчо и посредством iretd, к примеру так: Код (Text): IRETD_SET_TF macro Local delta_, return_ Call delta_ delta_: pop eax lea eax,dword ptr [eax + (offset return_ - offset delta_)] pushfd push cs push eax or dword ptr [esp + 8],EFLAGS_TF iretd return_: endm Никто не хочет помогать, как всегда :-(
Есть аналогичная ситуация с загрузкой селектора стека, прерывание не возникает на инструкции загрузки сегментного регистра. Об этом Касперский писал когдато. Я уже начал сомневаться в эффективности трассировки посредством TF. Если трассировать с помощью HB то сильно снизится быстродействие, да и возможно не на всех инструкциях срабатывает точка останова(в манах на P4 был описан этот баг).
Имхо hb эффективнее в разы, лучше перехватить ещё 3 точки NtContinue, NtSetContextThread, NtRaiseException чем эмулить pushf и так далее, правда нужен хороший дизасм длин инструкций хотя и это не проблема. Насчет быстродействие этаж трассировшик зачем нам высокое быстродействие?, что касается инструкций на который не срабатывает hb первый раз слышу и не думаю что их много, можно просто сделать список таких инструкций и в обработчике #DB проверять если та инструкция ставить бряк после неё.
blast Имхо трассировщик основанный на этом механизме легко будет сломан, ибо невозвожно использовать более четырёх точек останова одновременно. Код установивший сразу все четыре точки останова на один и тотже адрес выполнит обращение к нему а трассировщик будет использовать одну из них, останов должен будет произойти по всем 4-м точкам(по одинаковому для всех DRx адресу одновременно), но этого не произойдёт, и проэмулить это не удастся, на то они и аппаратные. 24919969.pdf Errata #37, 86. Что не срабатывают аппаратные точки останова на инструкциях загрузки регистра SS давно известно, также описано как баг:
Clerk Гы, советую на крэклабе поискать и слить аттачи с Elemental Protector by Smon(и на нем тестить), если твой движок асилит! и HeavyProtected.exe, Keygen.exe или ReverseMe.exe запустятся под ним, то ИМХО уже неплохо для начала! А так тебе надо разок(твоему движку) под мутаген попасть - там первый раз мысли посещают "кто я, где я" %)))
Demon666 Нашёл я ту тему, там линки битые, ничего не скачивается. В томже топике линк на статьи: http://www.openrce.org/reference_library/anti_reversing - гуан полный. Ыыы, да ты значит вообще смысла трассировки этой не понимаешь. Причём тут мутагены хз. Если ты имеешь ввиду траблы с хэшами в старых процессорах(очередь команд не сбрасывалась для self-modifyng частей прог), то это нынче некатит DD
Из документированных инструкций последняя которая не вызывает исключение это Lss, но судя по манам есть в P4 есчо одна fpu которая также не вызывает отладочное исключение, я уже много перебрал, не то. Ктонибудь может знает что за инструкция ?