Антиотладочные хитрости под Win32 — Архив WASM.RU
Здесь я расскажу о нескольких хитростях, которые можно использовать для защиты своих вирусов и/или своих программ против отладчиков всех уровней, уровня приложения и системы. Я надеюсь, что вам понравится эта статья.
[ Win98/NT: Обнаружение отладчиков уровня приложения с помощью функции IsDebuggerPresent ]
Этой функции нет в Win95, поэтому вам следует вначале выяснить, существует ли она, и работает только с отладчиками уровня приложения (таким как TD32). Она работает прекрасно. Давайте посмотрим, что написано о ней в справочнике по Win32 API.
Функция IsDebuggerPresent показывает, запущен ли вызывающий ее процесс в контексте отладчика. Эта функция экспортируется из KERNEL32.DLL.
Код (Text):
BOOL IsDebuggerPresent(VOID)- Аргументы
У этой функции нет аргументов.
- Возвращаемое значение
- Если текущий процесс запущен в контексте отладчика, возвращаемое значение не равно нулю.
- Если текущий процесс не запущен в контексте отладчика, возвращаемое значение равно нулю.
Пример, демонстрирующий эту функцию очень прост. Вот он:
Код (Text):
;---[ CUT HERE ]------------------------------------------------------------- .586p .model flat extrn GetProcAddress:PROC extrn GetModuleHandleA:PROC extrn MessageBoxA:PROC extrn ExitProcess:PROC .data szTitle db "IsDebuggerPresent Demonstration",0 msg1 db "Application Level Debugger Found",0 msg2 db "Application Level Debugger NOT Found",0 msg3 db "Error: Couldn't get IsDebuggerPresent.",10 db "We're probably under Win95",0 @IsDebuggerPresent db "IsDebuggerPresent",0 K32 db "KERNEL32",0 .code antidebug1: push offset K32 ; Получаем адрес базы KERNEL32 call GetModuleHandleA or eax,eax ; Проверяем на ошибки jz error push offset @IsDebuggerPresent ; Теперь проверяем, существует push eax ; ли IsDebuggerPresent. Если call GetProcAddress ; GetProcAddress возвращает or eax,eax ; ошибку, мы считаем, что мы jz error ; в Win95 call eax ; Вызываем IsDebuggerPresent or eax,eax ; Если она возвращает не 0, jnz debugger_found ; нас отлаживают debugger_not_found: push 0 ; Показываем "Debugger not found" push offset szTitle push offset msg2 push 0 call MessageBoxA jmp exit error: push 00001010h ; Show "Error! We're in Win95" push offset szTitle push offset msg3 push 0 call MessageBoxA jmp exit debugger_found: push 00001010h ; Show "Debugger found!" push offset szTitle push offset msg1 push 0 call MessageBoxA exit: push 00000000h ; Exit program call ExitProcess end antidebug1 ;---[ CUT HERE ]-------------------------------------------------------------Не правда ли, это красиво? Micro$oft сделал эту работу за нас . Но, конечно, не ждите, что этот метод будет работать с SoftIce'ом, богом отладки.
[ Win32: Другой путь, как узнать, что мы находимся в контесте отладчика ]
Если вы смотрели статью "Wub95 Structure and Secrets", которая была написана Murkry/iKX, и опубликована в Xin-3, вы сообразите, что в регистре FS находится очень крутая структура. Давайте взглянем в поле FS:[20h]... Это 'DebugContext'. Всего лишь сделаем следующее:
<--- делайте, что хотите, нас отлаживаютКод (Text):
mov ecx,fs:[20h] jecxz not_being_debugger [...]Потому, если FS:[20h] равен нулю, нас не отлаживают. Наслаждайтесь этим маленьким и простым методом для обнаружения отладчиков! Конечно, это не сработает против SoftICE...
[ Win32: Остановка отладчиков уровня приложения с помощью SEH ]
Я не знаю почему, но отладчики уровня приложения умирают, если программа использует SEH. Эмуляторы код, если мы делаем ошибки, умирают тоже . SEH, как я писал в своей статье для DDT#1, используется для многих интересных целей. Хорошо, так как я не хочу рассказывать все это заново, я просто скопирую и вставлю мое старое описание .
--[DDT#1.2_6]---------------------------------------------------------------
Хорошо, это очень простой туториал о Structured Exception Handler. Когда я увидел SEH, реализованный в вирусе, я подумал "Хорошо, это большая работа. Наверное, это было сложно реализовать". Поэтому я просто пропустил это. Но, как только мой Destiny сделал General Protection Fault'ы под NT, я понял, что я должен сделать что-то. И SEH - это единственный путь. Хорошо, мы можем сделать этоу очень сложным или очень простым для понимания. Конечно, я предпочитаю сделать это попроще .
% Установка фрейма SEH %
Сначала мы сохраняем его для нашей собственной безопасности простой строкой кода.
Код (Text):
push dword ptr fs:[0]А теперь надо установить указатель на наш обработчик (например, представьте, что мы используем call для вызова настройки SEH, а наш обработчик идет непосредственно после этой инструкции call: мы можем использовать смещение ret).
Код (Text):
push offset SEH_Handler mov fs:[0],espОк, просто как только возможно. Что насчет восстановления исходного SEH. Еще проще. Просто вызовите инструкцию, обратную первой.
Код (Text):
pop dword ptr fs:[0]Удивительно, что может сделать эта простая для реализации вещь для наших вирусов. Для меня (и мне было важно именно это использование SEH) наиболее главным было то, что я смог избежать всех этих отвратительных голубых экранов, когда мы запускаем наш Win95-вирус в среде NT.
% Пример использования SEH %
Мы можем скомпилировать данный пример следующим образом:
Код (Text):
tasm32 /m3 /ml sehtest,,; tlink32 /Tpe /aa sehtest,sehtest,,import32.lib
Код (Text):
;---[ CUT HERE ]------------------------------------------------------------- .386p .model flat ; 32 бита рулят extrn MessageBoxA:PROC ; Определенные API extrn ExitProcess:PROC .data szTitle db "Structured Exception Handler example",0 szMessage db "Intercepted General Protection Fault!",0 .code start: call setupSEH exceptionhandler: mov esp,[esp+8] ; Ошибка дает нам старый ESP ; в [ESP+8] push 00000000h ; Аргументы для MessageBoxA push offset szTitle push offset szMessage push 00000000h call MessageBoxA push 00000000h call ExitProcess ; Выходим из приложения setupSEH: push dword ptr fs:[0] ; Push'им оригинальный ; обработчик SEH mov fs:[0],esp ; И помещаем новый (который ; находится после первого ; call) mov ebx,0BFF70000h ; Пытаемся писать в ядро (что mov eax,012345678h ; вызовет исключение) xchg eax,[ebx] end start ;---[ CUT HERE ]-------------------------------------------------------------[...]
--[DDT#1.2_6]---------------------------------------------------------------
Я надеюсь, что вы поняли все это. Если нет... Ладно, забудьте об этом . Также как и другие методы, представленные выше, он не работает по отношению к SoftICE.
[ Win9X: Обнаружение SoftICE (I) ]
Здесь я должен поблагодарить Super/29A, потому что именно он рассказал мне об этом методе. Я разделил его на две части: в этой мы рассмотрим, как использовать его из вирусов Rin-0. Я не буду помещать здесь программу-пример целиком, потому что она займет лишнее место, но вы должны знать, что этот метод должен выполняться в Rin-0, а VxDCall должен быть восстановлен из-за проблемы обратного вызова (вы помните о ней?).
Ок, мы будем использовать сервис менеджера виртуальных машин (VMM) Get_DDB, поэтому сервис будет 00010146h (VMM_Get_DDB). Давайте посмотрим, что говорится об этом сервисе в SDK.
Код (Text):
mov eax, Device_ID mov edi, Device_Name int 20h ; VMMCall Get_DDB dd 00010146h mov [DDB], ecx
- Определяет, установлен или нет VxD определенного устройства, и если установлен, возвращает DDB для этого устройства.
- Использует ECX, флаги.
- Возвращает DDB для определенного устройства, если функция была выполнена успешно.
- В противном случае возвращает ноль.
- Device_ID: Идентификатор устройства. Этот параметр может быть равен нулю для именованных устройств.
- Device_Name: Восьмибуквенное имя устройства, которое дополнено (в случае необходимости) пустыми символами. Этот параметр требуется только тогда, когда Device_ID равен нулю. Имя устройства чувствительно к регистру.
Ладно, вы наверняка удивляетесь, о чем идет разговор. Очень просто, поле Device_ID VxD SoftICE постоянно для всех программ, а так как оно зарегистрировано в Micro$oft'е, у нас есть оружие против этого отладчика. Его Device_ID всегда равно 202h. Поэтому мы можем использовать следующий код:
Код (Text):
mov eax,00000202h VxDCall VMM_Get_DDB xchg eax,ecx jecxz NotSoftICE jmp DetectedSoftICEГде NotSoftICE должно быть продолжением кода вируса, а метка DetectedSoftICE должна обрабатывать тот случай, если наш враг жив . Я не предполагаю здесь никакой деструкции, так как, например, на моем компьютере SoftICE всегда активен .
[ Win9X: Обнаружение SoftICE (II) ]
Ладно, теперь идет другой метод для обнружения моего возлюбленного SoftICE'а, но основанный на той же самой идее, что и выше: 202h ;). Снова я должен поблагодарить Super . Ладно, в Ralph Brown Interrupt list мы можем найти очень крутой сервис: прерывание 2Fh, функция 1684h.
Код (Text):
На входе: AX = 1684h BX = virtual device (VxD) ID (see #1921) ES:DI = 0000h:0000h На выходе: ES:DI -> входная точка VxD API, или 0:0, если VxD не поддерживает этот API. N.B.: некоторые виртуальные устройства в улучшенном режиме Windows предоставляют сервисы, которые могут использовать приложения. Например, Virtual Display Device предоставляет API, используемый WINOLDAP.Поэтому вы поместите 202h в BX, запустите эту функцию. А потом скажете... "Эй, Билли... Через какое место я могу использовать прерывания?". Мой ответ... ИСПОЛЬЗУЙТЕ VxDCALL0!!!
[ Win32: Обнаружение SoftICE (III) ]
И наконец, чудесный трюк, которого вы ждали... Универсальный способ найти SoftICE и Win9x и в WinNT! Это очень просто, 100% основанно на API и без всяких "грязных" трюков, которые не идут на пользу совместимости. И ответ находится не так далеко, как вы думаете... ключ заключается в API, который вы уже использовали раньше: CreateFile. Да, именно эта функция... Разве это не прекрасно? Ладно, мы можем попытаться открыть следующее:
Код (Text):
+ SoftICE для Win9x : "\\.\SICE" + SoftICE для WinNT : "\\.\NTICE"Если функция возвращает нам что-нибудь, отличное от -1 (INVALID_HANDLE_VALUE), SoftICE запущен! Далее следует демонстрационная программа:
Код (Text):
;---[ CUT HERE ]------------------------------------------------------------- .586p .model flat extrn CreateFileA:PROC extrn CloseHandle:PROC extrn MessageBoxA:PROC extrn ExitProcess:PROC .data szTitle db "SoftICE detection",0 szMessage db "SoftICE for Win9x : " answ1 db "not found!",10 db "SoftICE for WinNT : " answ2 db "not found!",10 db "(c) 1999 Billy Belcebu/iKX",0 nfnd db "found! ",10 SICE9X db "\\.\SICE",0 SICENT db "\\.\NTICE",0 .code DetectSoftICE: push 00000000h ; Проверяем наличии push 00000080h ; SoftICE для среды Win9x push 00000003h push 00000000h push 00000001h push 0C0000000h push offset SICE9X call CreateFileA inc eax jz NoSICE9X dec eax push eax ; Закрываем открытый файл call CloseHandle lea edi,answ1 ; SoftICE найден! call PutFound NoSICE9X: push 00000000h ; А теперь пытаемся открыть push 00000080h ; SoftICE для WinNT... push 00000003h push 00000000h push 00000001h push 0C0000000h push offset SICENT call CreateFileA inc eax jz NoSICENT dec eax push eax ; Закрываем хэндл файла call CloseHandle lea edi,answ2 ; SoftICE для WinNT найден! call PutFound NoSICENT: push 00h ; Показываем MessageBox с push offset szTitle ; результатами push offset szMessage push 00h call MessageBoxA push 00h ; Завершаем программу call ExitProcess PutFound: mov ecx,0Bh ; Меняем "not found" на lea esi,nfnd ; "found"; адрес, где нужно rep movsb ; изменить, находится в EDI ret end DetectSoftICE ;---[ CUT HERE ]-------------------------------------------------------------Это действительно работает, поверьте мне . Тот же метод можно применить к "враждебным" драйверам, просто проведите небольшое исследование.
[ Заключительные слова ]
Ладно, вот я и рассказал о нескольких простых антиотладочных трюках. Я надеюсь, что вы сможете использовать их в своих вирусах без проблем. Пока! © Billy Belcebu/iKX, пер. Aquila
Антиотладочные хитрости под Win32
Дата публикации 27 июн 2002