Путеводитель по написанию вирусов под Win32: 8. Антиотладка под Win32 — Архив WASM.RU
Здесь я перечислю некоторые приемы, которые можно использовать, чтобы защитить свои вирусы и/или программы против отладчиков (всех уровней, уровня приложения и системного). Я надеюсь, что вам понравится эта глава.
Win98/NT: обнаружение отладчиков уровня приложения (IsDebuggerPresent)
Этой API-функция нет в Win95, поэтому вам нужно будет убедиться в ее наличии. Также она работает только с отладчиками уровня приложения (например, TD32). И она работает прекрасно. Давайте посмотрим, что о ней написано в справочнике по Win32 API.
Код (Text):
-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-· Функция IsDebuggerPresent сообщает, запущен ли вызвавший ее процес в контексте отладчика. Эта функция экспортируется из KERNEL32.DLL. BOOL IsDebuggerPresent(VOID) Параметры --------- У этой функции нет параметров. Возвращаемое значение --------------------- ¤ Если текущий процесс запущен в контексте отладчика, возвращаемое значение не равно нулю. ¤ Если текущий процесс не запущен в контексте отладчика, возвращаемое значение равно нулю. -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·Пример, демонстрирующий этот API, очень прост. Вот он.
Код (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 ; Если результат не равен нулю, нас 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 ; Показываем "Error! We're in Win95" push offset szTitle push offset msg3 push 0 call MessageBoxA jmp exit debugger_found: push 00001010h ; Показываем "Debugger found!" push offset szTitle push offset msg1 push 0 call MessageBoxA exit: push 00000000h ; Выходим из программы call ExitProcess end antidebug1 ;---[ CUT HERE ]-------------------------------------------------------------Разве не красиво? Micro$oft сделала за нас всю работу . Но, конечно, не ожидайте, что этот метод будет работать с SoftICE ;).
Win32: другой путь узнать, что мы находимся в контексте отладчика
Если вы взглянете на статью "Win95 Structures and Secrets", которая была написана Murkry/iKX и опубликована в Xine-3, вы поймете, что в регистре FS находится очень классная структура. Посмотрите поле FS:[20h]... Это 'DebugContext'. Просто сделайте следующее:
Код (Text):
mov ecx,fs:[20h] jecxz not_being_debugger [...] <--- делайте что угодно, нас отлаживают <img src="styles/smiles_s/smile3.gif" class="mceSmilie" alt=":smile3:" title="Smile3 :smile3:">Таким образом, если FS:[20h] равен нулю, нас не отлаживают. Просто наслаждайтесь этим маленьким и простым методом, чтобы обнаруживать отладчики! Конечно, это нельзя применить к SoftIce.
Win32: Остановка отладчиков уровня приложения с помощью SEH
Я еще не знаю почему, но отладчики уровня приложения падают, если программа просто использует SEH. Также как и кодоэмуляторы, если вызываются исключения . SEH, о котором я писал в DDT#1, используется для многих интересных вещей. Идите и прочитайте главу "Продвинутые Win32-техники", часть которой я посвятил SEH.
Вам потребуется сделать SEH-обработчик, который будет указывать на код, чье выполнение начнется после исключения, которого можно добиться, например, попытавшись записать что-нибудь по адресу 00000000h ;).
Хорошо, я надеюсь, что вы поняли это. Если нет... Гхрм, забудьте это ;). Также, как и методы, изложенные ранее, данный методы нельзя применить к SoftICE.
Win9X: Detect SoftICE (I)
Здесь я должен поблагодарить Super/29A, потому что это именно он рассказал мне об этом методе. Я разделил его на две части: в этой мы увидим, как это сделать из Ring-0. Я не буду помещать сюда весь исходный код вируса, потому что в нем много лишнего, но вы должны знать, что данный способ работает в Ring-0 и VxDCall должен быть восстановлен из-за проблемы обратного вызова (помните?).
Ок, мы собираемся использовать сервис VMM Get_DDB, т.е. сервис равен 00010146 (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'е, что мы можем использовать в качестве оружия против чудесного SoftIce, Его 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 = виртуальное устройство (VxD) ID (смотри #1921) ES:DI = 0000h:0000h Возврат:ES:DI -> входная точка VxD API или 0:0, если VxD не поддерживает API Обратите внимание: некоторые драйвера устройств предоставляют приложениям определенные сервисы. Например, Virtual Display Device (VDD) предоставляет API, используемый WINOLDAP. -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·Таким образом, вы помещаете BX в 202h и запускаете эту функцию. А затем говорите... "Эй, Билли... Как мне использовать прерывания?". Мой ответ... ИСПОЛЬЗУЙТЕ 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 ; Проверяем наличие SoftICE push 00000080h ; для среды окружения 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 ]-------------------------------------------------------------Это действительно работает, поверьте мне . Тот же метод можно применить к другим враждебным драйвером, просто сделайте небольшое исследование на этот счет.
Win9x: Убить хардверные брикпоинты отладчика
Если ваc беспокоят отладочные регистры (DR?), мы сталкиваемся с небольшой проблемой: они привилегированны в WinNT. Прием состоит в следующей простой вещи: обнулить DR0, DR1, DR2 и DR3 (они наиболее часто используются отладчиками в качестве хардверных брикпоинтов). Поэтому следующим кодом вы доставите отладчику немного неприятностей:
Код (Text):
xor edx,edx mov dr0,edx mov dr1,edx mov dr2,edx mov dr3,edxХаха, разве это не смешно?
Заключительные слова
Я надеюсь, что вы сможете использовать эти несколько простых антиотладочных приемов в ваших вирусах без особых проблем. © Billy Belcebu, пер. Aquila
Путеводитель по написанию вирусов под Win32: 8. Антиотладка под Win32
Дата публикации 31 окт 2002