;▄▄                   ▄
;▀▀▀ STEALTH GROUP WW █ Mail:   BOX 15, 125080 MOSCOW   ████████ █████████ █▀▀█
;▀██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▐▀▀▀   ┌─┐┬ ┬┌─┤┬ ┬ ╥ ┬┐┌ █▄▄█
; ▐█ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▄█▄ ▄▀▀ █▀█   ▌ █ ▄▀█ █ ▄▀▀ █▄▄    ├┬┘│ │└─┐├─┤   │└┤ ▄  █
;  █ █ █ █▀  █▀  █    █  █▀  █ █   █ █ █ █ █ █   █      ┴└─└─┘└─┘┴ ┴   ┴ ┴ ▀▀▀▀
;  █ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀    ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄▄   ████  WINTER ' 96  ████
;  ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄   ███████████████████████
;
;   █████████████ ТРАССИРОВКА С ЗАЩИТОЙ ОТ ОБНАРУЖЕНИЯ ██████████████ 
;
;   Пояснения см. в файле TR_INTRO.IV9
;
.MODEL TINY
.CODE
 ORG 100h

beep macro fff			; отладочный макрос - выводит символ на экран
pushf
push ax
mov ah,0eh
mov al,fff
int 10h
pop ax
popf
endm

CLT MACRO			; Сброс TF
	PUSHF				
	POP  AX
	AND  AH,0FEh
	PUSH AX
	POPF
	ENDM

STT MACRO			; установка TF
	PUSHF
	POP  AX
	OR   AH,01
	PUSH AX
	POPF
	ENDM

;---------------------------------------
; Константы - HEX-представление комманд

@CS_PFX EQU 2Eh
@DS_PFX EQU 3Eh
@ES_PFX EQU 26h
@SS_PFX EQU 36h
@REP_PFX EQU 0F3h

@SUB_SI_BYTE EQU 0EE83h
@MOV_SS_REG  EQU 8EH
@PUSH_IMM    EQU 68H
@CALL_FAR    EQU 09Ah
@POP_SS      EQU 17H
@MOV_BL      EQU 0B3H
@PUSHF       EQU 09CH
@POPF        EQU 09DH
@IRET        EQU 0CFH
@INT         EQU 0CDH
@STI         EQU 0FBH

@JB	     EQU 72h
@JAE	     EQU 73h

START        EQU 0000H		; В коде вируса обращение ко всем
				; переменным в памяти идет от начала тела
				; (START)
;------------------------------------------------------------------------
_START:

;--------------------
 MOV AH,09
 MOV DX,OFFSET MSG
 INT 21H
 MOV AH,08
 INT 21H
 JMP OVERMSG

 MSG DB 'THE INTERRUPT PENETRATOR. Ver.2.0  (C) LovinGOD, SGMoscoW/SGWW, 1996'
     DB  0dh,0ah,0DH,0AH
     DB 'Условные обозначения: ',0dh,0ah
     DB '                         )  Выход из int13h ',0dh,0ah
     DB '			  !  Сегмент int13h >0F000h',0dh,0ah
     DB '			  -  Шаг окончен',0dh,0ah
     DB '			  P  Префикс CS: DS: ES: SS: REP ',0dh,0ah
     DB '			  S  POP SS ',0dh,0ah
     DB '			  s  MOV SS,<reg>',0dh,0ah
     DB '			 [ ] Вход и выход в прерывания',0dh,0ah
     DB '			 ^ v PUSHF и POPF',0dh,0ah
     DB '...Press any key...',0dh,0ah,'$'
 OVERMSG:
					; инициализация условий трассировки
MOV WORD PTR CS:[CMPSEG-START],0F000h	; условия, по достижении которых
MOV BYTE PTR CS:[CMPCMD-START],@JB	; запоминается адрес
					; Здесь (INT 13h):  Сег.>=0F000h
					; Для INT 21h:  0300h и @JAE

MOV AX,3513h			; получить вектор int13h
INT 21h
MOV CS:[OLD13-START],BX
MOV CS:[OLD13+2-START],ES

CLT

IN  AL,21h			; запрет клавиатуры и таймера (IRQ0,IRQ1)
OR  AL,00000011B
OUT 21h,AL

PUSH DS				; установка обработчика int01
XOR  AX,AX
MOV  DS,AX
MOV  DS:[01*4],OFFSET TRACER13-START
MOV  DS:[01*4+2],CS
POP  DS

STT

mov ah,30h			; демонстрация работы трассировщика с
int 21h				; коммандой INT XX. В вашей процедуре 
				; этот вызов нужно убрать


PUSHF				; вызов трассируемого int13h
MOV AX,0880h			; (Получить параметры винта)
DB  @CALL_FAR
OLD13  DW ?,?
						; отработали
MOV BYTE PTR CS:[TRACER13-START],@IRET		; закрываем обработчик int01

pushf
pop ax
and ah,0feh
push ax
popf

beep')'

IN  AL,21h			; восстановим запрещенные IRQ
AND AL,11111100B
OUT 21h,AL

MOV AX,4C00h			; конец программы
INT 21h

;----------------------------------------------------------------------------
REAL13 DW ?,?
;----------------------------------------------------------------------------

TRACER13 PROC
	DB   90H				; Сюда будет записан код IRET
						; по достижению результата

	MOV  WORD PTR CS:[BPSAVE-START],BP	; сохраним регистры
	MOV  WORD PTR CS:[SISAVE-START],SI
	MOV  WORD PTR CS:[DSSAVE-START],DS
	MOV  WORD PTR CS:[AXSAVE-START],AX

	PUSH SI ES
	PUSH CS CS
	POP  DS ES
	MOV  SI,OFFSET REFRESH-START
	MOV  DI,OFFSET TRACER13-START
	CLD
	MOVSW
	MOVSW
	MOVSW
	STD
	POP  ES SI

	POP  SI DS AX				; Все, необходимое для IRET
						; DS:SI = Адрес след. комманды
						;    AX = Flags

						; Восстановим начало TRACER'а
	PUSH AX					
	MOV  AX,DS				; Условие достижения ?
	CMPSEG EQU $+1
	CMP  AX,0F000H
	POP  AX
	CMPCMD EQU $
	JB   NOTREACHED

	;---------------------------------------  Трассировка достигла цели
	beep'!'

	MOV    CS:[REAL13-START],SI		; Оригинальный вектор int13h
	MOV    CS:[REAL13-START+2],DS

	AND  AH,0FEH				; снимает флаг трассировки
	MOV  BYTE PTR CS:[TRACER13-START],0CFH	; IRET в начало обработчика
	JMP  ALLBACK

	;--------------------------------------- Трассировка в процессе...
     NOTREACHED:				; BIOS не достигнут

       ;---------------------------------------- Очистка комманд от префиксов
	MOV  BYTE PTR CS:[PFX_ADD-START],00
    TEST_PFX:
	CMP  BYTE PTR DS:[SI],@CS_PFX
	JE   THE_PFX
	CMP  BYTE PTR DS:[SI],@DS_PFX
	JE   THE_PFX
	CMP  BYTE PTR DS:[SI],@ES_PFX
	JE   THE_PFX
	CMP  BYTE PTR DS:[SI],@SS_PFX
	JE   THE_PFX
	CMP  BYTE PTR DS:[SI],@REP_PFX
	JE   THE_PFX
						; проверить на LOCK

	JMP END_PFX_TEST	

    THE_PFX:					; убираем очередной префикс
	beep 'P'
	INC  BYTE PTR CS:[PFX_ADD-START]
	INC  SI
	JMP  TEST_PFX

    END_PFX_TEST:
       ;------------------------------ Эмуляция операций занесения в SS
	CMP BYTE PTR DS:[SI],@POP_SS
	JNE TEST_SS_REG

	beep 'S'

	INC SI
	CLI
	POP SS
	STI
	JMP SS_OUT

  TEST_SS_REG:
	CMP BYTE PTR DS:[SI],@MOV_SS_REG
	JNE SS_OUT

	beep 's'	

	CMP BYTE PTR DS:[SI+1],0D0h
	JB SS_OUT
	CMP BYTE PTR DS:[SI+1],0D8h
	JAE SS_OUT

	PUSH BX
	MOV BL,BYTE PTR DS:[SI+1]
	MOV BYTE PTR CS:[MOV_SS_OPERAND-START],BL
	POP BX

	XCHG AX,WORD PTR CS:[AXSAVE-START]
	XCHG BP,WORD PTR CS:[BPSAVE-START]
	XCHG SI,WORD PTR CS:[SISAVE-START]

	CLI
	JMP SHORT $+2
	MOV_SS_OPERAND EQU $+1
	MOV SS,AX
	STI

	MOV AX,WORD PTR CS:[AXSAVE-START]
	MOV BP,WORD PTR CS:[BPSAVE-START]
	MOV SI,WORD PTR CS:[SISAVE-START]

	INC SI
	INC SI

  SS_OUT:
       ;---------------------------------------
						; PUSHF ?
	CMP BYTE PTR DS:[SI],@PUSHF		
	JNE N0

	beep '^'

	INC  SI					; IRET на комманду после PUSHF
	PUSH AX					; Сами делаем PUSHF
	MOV  BP,SP
	AND  WORD PTR SS:[BP],0FEFFH		; Чистим TF во "флагах"
	JMP  ALLBACK

	;--------------------------------------- ------------------------------
     PFX_BACK:					; вернуть SI на начало, если
						; использовались префиксы
	DW @SUB_SI_BYTE				; SUB SI,PFX_ADD
	PFX_ADD DB ?

	PUSH AX DS SI
	CALL BACK_REGS
	beep '-'
	IRET

     ALLBACK:					; выход из этого прерывания 
	MOV CS:[ALLBACKADDR-START],SI
	MOV CS:[ALLBACKADDR+2-START],DS
	PUSH AX 				; набор для IRET - в стек

	PUSH CS
	DB @PUSH_IMM
	DW (OFFSET ALLBACK1-START)
	
	CALL BACK_REGS

	beep'-'
	RETF

     ALLBACK1:
	POPF
	DB 0EAh
	ALLBACKADDR DW ?,?

    BACK_REGS:
        SISAVE EQU $+1    			; восстанавливаем регистры
	MOV    SI,0000
	DSSAVE EQU $+1
	MOV    AX,0000
	MOV    DS,AX
	AXSAVE EQU $+1
	MOV    AX,0000
	BPSAVE EQU $+1
	MOV    BP,0000				
	RETN

     N0:					
	CMP BYTE PTR DS:[SI],@POPF
	JNE N1

	;----------------------------- Проверка 

	beep 'v'

	MOV BP,SP						
	OR  WORD PTR SS:[BP],0100H
	JMP PFX_BACK				

     N1:
	CMP BYTE PTR DS:[SI],@IRET
	JNE NXTT3
	beep'i'
						; след. комманда - IRET 
	MOV BP,SP
	OR WORD PTR SS:[BP+04],0100H		; Устанавливаем TF во флагах
	JMP ALLBACK
  
     NXTT3:
	;-------------------------------------  Вызов прерывания

	CMP BYTE PTR DS:[SI],@INT
	JE  INT_IT_IS
	JMP PFX_BACK
    INT_IT_IS:	
	beep '['

	INC SI		
	INC SI
	
	MOV WORD PTR CS:[IRET_CS-START],CS
	MOV WORD PTR CS:[IRET_IP-START],SI

	PUSH AX					; IRET для "INT_XX" (на нас)
	MOV  BP,SP
	AND  WORD PTR SS:[BP],0FEFFh		; Flags
	PUSH CS					; CS
	DB @PUSH_IMM
	DW (OFFSET AFTER_INT-START)  		; IP

	PUSH BX AX
	XOR  BH,BH
	MOV  BL,DS:[SI-1]			; INT#
	SHL  BL,1
	SHL  BL,1
	XOR  AX,AX
	MOV  DS,AX
	LDS  SI,DWORD PTR DS:[BX]		; Адрес начала обработчика
	POP  AX BX
	AND  AH,0FEh				; TF=0 внутри прерывания и
						; при возврате из него
	
	JMP  ALLBACK

TRACER13 ENDP
;---------------------------------------------
  REFRESH:					; код начала трассировщика
						; для восстановления начала
	DB   90H				
	MOV  WORD PTR CS:[BPSAVE-START],BP
;---------------------------------------------------------------------------
AFTER_INT:
	BEEP ']'
	STT
	DB 0EAh
	IRET_IP DW ?
	IRET_CS DW ?

;---------------------------
INSIDE_INT DB 0
just_cc db 0

END _START