Антиотладочные трюки

Тема в разделе "WASM.RESEARCH", создана пользователем Osen, 17 май 2008.

  1. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    Я слышал тут много вопросов по антиотладке. Предлагаю вашему вниманию несколько антиотладочных приемов. Обсуждение и дополнительные приемы можно найти на http://www.virustech.org

    1) Проверяем контрольные суммы отдельных блоков кода, для обнаружения int3 проставленных в коде.

    2) Проверки на 0xCC в начале API-функций.

    3) Рандомизация хардварных отладочных регистров с помощью SuspendThread/GetThreadContext/SetThreadContext или с помощью SEH в SEH-обработчике

    4) Против SoftIce – перечисление загруженных драйверов EnumDeviceDrivers/GetDeviceDriverBaseName и поиск «ntice.sys» и «iceext.sys», попытка открыть устройства с помощь функции CreateFile, имя устройства зависит от ring0-отладчика, например, для SoftIce это - "\\.\NTICE"

    5) Если отладчик обнаружен, то делается рандомизация регистров, прыжок на рандомную страницу. Из-за рандомизации регистра стековый фрейм будет поврежден и сложно будет найти, где был прыжок, и где осуществлялась антиотладочная проверка. Или перейти на код с кучей багов, но все-таки, рабочего, чтобы исследователь попал в большую кучу ошибок и соответственно левых SEH-фреймов.

    6) Тайминговые атаки очень эффективны против отладчиков. Для замера времени необходимо использовать функцию GetTickCount(KeTickCount в ядре), для более точного измерения можно использовать функции QueryPerformanceFrequency / QueryPerformanceCounter, но чтобы они работали, им нужна соответствующая поддержка оборудования. Также, часто используют инструкцию RDTSC и как разновидность – поиск ее в системной и DLL и опосредованный ее вызов. Есть разновидность метода с RDTSC – делать RDTSC, потом генерить исключение, но без использования регистра EAX, и уже в предварительно поставленном обработчике исключения делать второй RDTSC и сравнивать со значением из CONTEXT.EAX. Не забываем при этом об использовании CPUID перед RDTSC. Разницу принимаем не больше E0000h – конечно необходимо использовать не точно это значение, а некоторый диапазон приемлемых значений – т.е. случайные числа.

    7) Динамическое вычисление адреса перехода на процедуру:
    Код (Text):
    1. push 1
    2. call sin
    3. xor eax,0x3334124
    4. xor eax,0x553242444
    5. sub eax,ecx
    6. call eax
    8) Иногда можно генерировать исключения с помощью некорректных операций или с помощью функции RaiseException. Справедливо можно заметить, что если исключение генерируется с помощью RaiseException, то при работе в отладчике OllyDbg не сможет передать управление на поставленный обработчик исключений – это придется делать вручную взломщику. Это позволяет запутать исследователя получить полные представление о коде, из-за постоянных остановок в процессе исследования. Саму установку SEH необходимо разбавить мусором, выстраивать многослойные ошибки.

    9) Шифровать куски по мере исполнения, шифровать куски которые выполняются только один раз – для защиты от дампа. Чтобы делать расшифровку по мере исполнения, можно использовать TF.

    10) Сделать, чтобы int3 бряк никогда не сработал – 1) не возвращаться из фейковых функций, которых будет нормальное количество:
    Код (Text):
    1. push param1
    2. push param2
    3. ..
    4. push paramn
    5. call function
    6. nop
    7. nop
    8. .............
    9. function:
    10. pop eax ; адрес возврата
    11. pop eax ; paramn
    12. ....
    13. pop eax ; param1
    14.  
    15. jmp point_that_we_nead
    16. ............
    17. point_that_we_nead:
    18. ..........
    11) Записывать оригинальные байты на точку входа их TLS-CALLBACK или из внешних DLL, т.к. обычно на EP записывают программный бряк.

    12) В качестве борьбы с плагинами для OllyDbg, рекомендуется использовать проверки на перехваченные процедуры и поиск присутствия плагинов, например, поисков DLL-файла плагина, Wnd-класса окна плагина и подобное. Например, чтобы сейчас обнаружать Phantom достаточно отсканить окна и найти в них строку Phant0m. Чтобы обнаружить последний OllyAdv надо проверить на хуки функции NtSetInformationThread и GetTickCount - но этих опций может и не быть в настройках, хотя часто кулхацкеры просто ставят все подряд галочки.

    13) Записываем мусор в ненужные поля PE-файла. Olly этому будет не очень рада. LoadFlags и NumberOfRvaAndSizes очень для этого подходят.

    14) Результат исполнения антиотладочного кода используем как ключ к расшифровке последующего кода для исполнения.

    15) Запихиваем некоторый код в DLL, и делаем вызов LoadLibrary(), из DllMain можно исполнять код, который необходимо скрыть от посторонных глаз. Например, после исполнения LoadLibrary() исполнение последовательности инструкций прекращается вызовом ExitThread()/ret, а в DllMain() создается поток вызовом CreateThread() с адресом, принадлежащим образу исполняемого файла, а не DLL. В итоге DLL будет крошечного размера. Конечно, DLL должна создаваться динамически. Исполнять код можно как при загрузке DLL, так и при выгрузке, а также при создании/завершении потоков.

    16) Пытаемся открыть CSRSS.EXE и если это получается, значит нас отлаживают. После открытия создаем поток в CSRSS, т.о. вызывая BSOD. PID CSRSS.EXE можно получить вызовом CsrGetProcessId().

    17) Использование функции CheckRemoteDebuggerPresent(), которая доступна только в XP. Эту функцию можно сэмулировать вызовом NtQueryInformationProcess. Подробности можно узнать в дизассемблированном листинге функции CheckRemoteDebuggerPresent()

    18) Процесс защищаемого приложения создается. В комбинации с другими антиотладочными приемами, мы создаем новый процесс для этого же файла, пишем переход в начале функции LdrInitializeThunk и в обработчике убираем расставленные бряки на EP, на TLS Callback, а также переинициализируем PEB.DebuggerPresent. Основная суть состоит в том, чтобы загрузить процесс раньше, чем это сделает отладчик. При этом можно начать исполнение не с EP, а любого другого участка. Также проверяем, что первый процесс был порожден вторым, для этого смотрим на, может быть, созданные флаги или проверяем тот же переход в функции LdrInitializeThunk. Этот же трюк можно проделать с DLL. И как кажется, это будет эффективней способа с EXE, т.к не надо будет порождать дополнительных процессов. Надо загрузить раньше чем отладчик остановиться на DllMain и убрать его хук, либо вообще изменить последовательность исполнения, перепрыгнув через DllMain.

    19) Делать два процесса, чтобы один отлаживал другой. Отладчик в этом случае генерирует исключения, и родитель за счет них выполняется.

    20) Создаем порт с помощью NtCreatePort, и делаем его отладочным - NtSetInformationProcess. Если этого сделать нельзя, то порт уже занят и нас отлаживают.

    21) Очень долгая расшифровка, чтобы трейсинг, даже, если он будет работать, был очень долгим, невозможно долгим.

    22) Использовать int3/int1 для расшифровки кода или для любых других жизненно-необходимых операций. Этот же метод можно использовать с целью антидамповой защиты.

    23) Если защищаемое приложение загружает DLL, имя которой имеет размер больше 200 символов, то Olly упадет.

    24) Вызываем ZwQueryObject с нулевым описателем и заполненной структурой OBJECT_ALL_TYPES_INFORMATION с типом объекта DebugObject. После вызова проверяем поля TotalNumberOfHandles и TotalNumberOfObjects объекта и если эти поля больше 0, то нас отлаживают.

    25) Если исключение происходит в Windows XP SP>=2, Windows 2003, Windows Vista есть несколько вариантов развития событий – 1) Передача управления установленному VEH-обработчику, 2) передача управления самому ближайшему SEH-обработчику, 3) если user-обработчики не установлены, то происходит вызов UnhandledExceptionFilter из kernel32. Характер поведения UnhandledExceptionFilter зависит от того отлаживается процесс или нет. Если он отлаживается, то процесс завершается, иначе происходит вызов функции заданной программистом через SetUnhandledExceptionFilter. Исходя из вышесказанного можно делать жизненноважные манипуляции в обработчике установленном функцией SetUnhandledExceptionFilter. При решении этой проблемы можно перехватить SetUnhandledExceptionFilter, и узнать адрес обработчика. Но код SetUnhandledExceptionHandler простой и его можно сэмулировать, и найти адрес топового обработчика вручную.

    26) Использование функции ZwSetInformationThread:
    Код (Text):
    1. push 0
    2. push 0
    3. push 11h ;ThreadHideFromDebugger
    4. push -2
    5. call NtSetInformationThread
    27) Породить дочерний процесс, который сделает вызов ZwDebugActiveProcess над процессом-родителем. Если вызов окажется неудачным, значит нас отлаживают.

    28) В FS засунуть 0,1,2 или 3 – что означает селектор нулевого сегмента. При обращении, например FS:[0], должно быть исключение, а его нет, т.к. обработчик исключения адресуется через регистр FS. Из прикладного режима такие исключения ловятся только через SetUnhandledExceptionHandler, а в приатаченном отладчике подобные исключения не обрабатываются, т.е. обработчик необработанных исключений не вызывается.

    29) Заполнение FS значением, например из DS, и активное использование префикса переопределения сегмента на FS может породить множество проблем исследователю.

    30) При трассировке и исполнении инструкции PUSHFD отладчики прозрачно вычищают TF. Но при MOV SS,X происходит реальная потеря трассировочного прерывания. Следующий код хорошо иллюстрирует этот трюк:
    Код (Text):
    1. MOV AX, SS
    2. PUSHFD
    3. MOV SS,AX
    4. POPFD
    В итоге POPFD сам же восстанавливает потертый TF. Более того(!) некоторые отладчики, находят например PUSHFD, но забывают затирать TF при REP PUSHFD При этом нельзя забывать, что дебагер, на следующей инструкции всегда выставляет TF заново, поэтому перепрыгивается только одна инструкция.

    31) Перечисляем все Debug-описатели в системе и насильно закрываем их.

    32) Если к процессу аттачатся, то в нем вызывается функция DbgUiRemoteBreakin. Перехватив ее можно спастить от аттача.

    33) Поиск ключей в реестре OllyDebug.

    34) CheckRemoteDebuggerPresent

    35) Вызов AnimateWindow -
    Код (Text):
    1. invoke WindowFromPoint,13ah,100h
    2. invoke  AnimateWindow,eax,701h,90000h
    36) Проверка ключа «SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug в HKEY_LOCAL_MACHINE»

    37) Использование прерывания int 2ch – под отладчиком после исполнения этого прерывания в edx будет -1, если без отладчика, то в edx будет адрес следующей инструкции.

    38) OllyDebug не поддерживает SSE-команды, недокументированные команды типа LOADALL. Его можно перехитрить командой MOV [0],eax или подобной, т.к. его коданалайзер посчитает такую команду неправильной и будет интерпретировать ее как данные. Также можно сделать несколько CALLов на данные, трех будет достаточно, тогда аналайзер тоже лопухнется.

    39) Можно изменить поток исполнения команд при выполнении WaitForSingleObjectEx. Ставим UserAPC на любой адрес для своего потока
    invoke QueueUserAPC,address,-2,0
    Потом хучим KiUserApcDispatcher с переходом на нужный нам код. Так, при выполнении WaitForSingleObjectEx будет переход на наш код магическим образом. Тоже можно сделать с CloseHandle на неправильном описателе и хук KiRaiseUserExceptionDispatcher. Интересно комбинировать эти трюки сделав WaitForSingleObjectEx внутри обработчика KiRaiseUserExceptionDispatcher. Обе функции отлично экспортируются ntdll. Эта же фича работает с функцией KiFastSystemCallRet и при исключениях.

    40) Устанавливаем TF например push -1/pop, после этого сразу генерим исключение нарушения доступа mov eax,[0] – или ud, то с отладчиком обработчик исключения, который был установлен, вызван не будет, а без отладчика будет вызван.

    (C) Osen / Independent Malware Authors, 2008
     
  2. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    И что же тут вашего авторства?
     
  3. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    asmfan

    Текст.
     
  4. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Osen
    по пункту 40 при активном сизере(1.93) будет БСОД
    надо это туда в коментарий добавить
    это тут не давно обсуждалось

    За идею респект!
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Osen
    Если надо систему завалить, достаточно в crsss вызвать сключение, зачем поток создавать ?
    Надо добавить что любая проактивка прибьёт попытку открытия csrss с полным доступом.
     
  6. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    А как удаленно это сделать? Вот мы делаем в нем исключение за счет создания потока.
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Гм. Контекст потока любого изменить, память уничтожить или ещё чтонибудь, есть более простые способы.
     
  8. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    Clerk
    ИМХО это проще всего. Чтобы изменить контекст нужен описатель потока. Память можно, но чем это будет проще. Само создание потока же тривиально, ну Вы и сами знаете ;)
     
  9. Hellspawn

    Hellspawn New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2006
    Сообщения:
    310
    Адрес:
    Москва
    хм asmfan прав, тут просто перечислены давно известные методы + парочка с изменениями или усложнениями :) не совсем понятно для чего, хоть бы описано было почему надо делать так, а не иначе.

    з.ы. а почему тема в вирусологии? чтобы юные дарования пихали эти приёмы в свои недо-вирусы? :)
     
  10. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    asmfan, Hellspawn
    Насчет юных дарований я бы не стал на Вашем месте быть столь самоуверенным, ведь эти юные дарования обгонят и перегонят стариков в два счета. Понимаю, когда проводишь на определенном информационном поле достаточно долгое время, то думаешь, что очень крут. Но боюсь это не правильный и плохой подход, потому как он не дает возможности развиваться. Я прекрастно понимаю то, что антиотладка не является панацеей защиты, но абсолютной истинной является то, что она затрудняет отладку для тех кто не достаточно силен в крекинге или для тех кто не умеет пользоваться нужными инструментами. Я искренне убежден в том, что наличие антиотладки лучше чем ее отсутствие в том коде, который нужно защитить от посторонних глаз. Я знаю, что помимо антиотладки существуют другие приемы защиты исследования, такие как морфинг, обфускация, выполнение кода в VM, аппаратные привязки, а также особые стратегии распространения программного обеспечения. Также я знаю то, что неломаемых защит или не существует или их количество чрезвычайно мало. Но говорить о том, что не надо обсуждать, а что надо обсуждать в очень большой мере по моему мнению просто не этично.
     
  11. Hellspawn

    Hellspawn New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2006
    Сообщения:
    310
    Адрес:
    Москва
    Я привёл вам аргумент, на который вы так и не ответили. Я сделал предложение описать каждый метод поподробнее, ведь как раз старичкам и так всё ясно про антиотладку, благо туторов в сети навалом, а новичкам большинство методов будет не понятно. уж если на то пошло, то сделали бы справочник аля "Peter Ferrie Senior Anti-virus Researcher 1 May, 2008" тока на русском.
     
  12. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    Hellspawn
    Я знаю Питера Фери, и знаю его справочник. Но свой текст я писал раньше. Как мне кажется, что суть вся именно в методах, и даже новички разберутся почему так или иначе. А если не разберутся, то эта тема именно для этих вопросов, именно технических вопросов по поводу написанных антиотладочных методов, дополнения того что было предложено, подводных камней и т.д., а не для идеологических обсуждений и причин написания постов.
     
  13. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    Hellspawn
    А идею расшиенного обсуждения методов я очень поддерживаю, ну тогда просто ждем тех, кто что-то не поймет.
     
  14. UTeX

    UTeX New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2007
    Сообщения:
    584
  15. Novi4ek

    Novi4ek New Member

    Публикаций:
    0
    Регистрация:
    3 авг 2007
    Сообщения:
    317
    Osen, спасибо за обзорчик, не слушай злых перцев, все нором.
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    41) NtSetLdtEntries
    42) аллокация памяти в нуле
    ольке это не очень нравится
     
  17. Flasher

    Flasher Member

    Публикаций:
    0
    Регистрация:
    31 янв 2004
    Сообщения:
    640
    По тематике можно много вкусностей найти тут unpack.cn и тут http://datasecurity-event.com/downloads.html
     
  18. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Какие интересные каки-трюки. Спасибо.
    Только пункт 18 какой-то сумбурный #)

    43) При загрузке модуля (dll/exe) с именем, содержащим юникодные символы, которые с использованием текущей AnsiCodepage мэппятся в виде "?", Olly плюётся сообщением и в Memory Map сливает все секции модуля в одну (мелочь, но может раздражать).


    Great
    Можно подробнее про аллокацию в нуле?
     
  19. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    Бред. Имена дров и создаваемые ими устройства могут отличаться. На кряклабе статья была. Я предложил бы просто брать путь, искать сам драйвер на винте и делать сигнатурный скан. Это относится в большей мере к iceext.sys, поскольку имя драйвера может быть каким угодно.
     
  20. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    Где гарантии что его можно открыть при отсутствии прав админа?