Путеводитель по написанию вирусов под Win32: 8. Антиотладка под Win32 — Архив WASM.RU

Все статьи

Путеводитель по написанию вирусов под Win32: 8. Антиотладка под Win32 — Архив WASM.RU

Здесь я перечислю некоторые приемы, которые можно использовать, чтобы защитить свои вирусы и/или программы против отладчиков (всех уровней, уровня приложения и системного). Я надеюсь, что вам понравится эта глава.

Win98/NT: обнаружение отладчиков уровня приложения (IsDebuggerPresent)

Этой API-функция нет в Win95, поэтому вам нужно будет убедиться в ее наличии. Также она работает только с отладчиками уровня приложения (например, TD32). И она работает прекрасно. Давайте посмотрим, что о ней написано в справочнике по Win32 API.

 -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
 Функция IsDebuggerPresent сообщает, запущен ли вызвавший ее процес в контексте
 отладчика. Эта функция экспортируется из KERNEL32.DLL.

 BOOL IsDebuggerPresent(VOID)

 Параметры
 ---------

 У этой функции нет параметров.

 Возвращаемое значение
 ---------------------

 ¤ Если текущий процесс запущен в контексте отладчика, возвращаемое значение
   не равно нулю.

 ¤ Если текущий процесс не запущен в контексте отладчика, возвращаемое значение
   равно нулю.
 -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·

Пример, демонстрирующий этот API, очень прост. Вот он.

;---[ 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'. Просто сделайте следующее:

        mov     ecx,fs:[20h]
        jecxz   not_being_debugger
        [...]   <--- делайте что угодно, нас отлаживают :)

Таким образом, если 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.

 -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-· 
         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. Поэтому нам нужно использовать следующий код:

        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.

 -·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·-·
 Ввод:
         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. Да, эта функция... разве не прекрасно? Ладно, мы должны попытаться сделать следующее:

        + SoftICE для Win9x : "\\.\SICE"
        + SoftICE для WinNT : "\\.\NTICE"

Если функция возвращает нам что-то, отличное от -1 (INVALID_HANDLE_VALUE), это значит, что SoftICE активен! Далее идет демонстрационная программа:

;---[ 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 (они наиболее часто используются отладчиками в качестве хардверных брикпоинтов). Поэтому следующим кодом вы доставите отладчику немного неприятностей:

        xor     edx,edx
        mov     dr0,edx
        mov     dr1,edx
        mov     dr2,edx
        mov     dr3,edx

Хаха, разве это не смешно? :)

Заключительные слова

Я надеюсь, что вы сможете использовать эти несколько простых антиотладочных приемов в ваших вирусах без особых проблем.

2002-2013 (c) wasm.ru