;
;[1m[32m        ____     ___        ___     ___ ___ ___ ___ ____      ___ ___ ___[0m
;[1m[32m         /  /__//_         /__ /  //_ //__ /  //_    /  / / //_ //__//_  [0m
;[1m[32m        /  /  //__        ___//__//__/___//__//     /  /_/_//  //  \/__  [0m
;
;[1m[32m-----------------------------------------------------------------------------[0m
;   - FOR ABO'S CONTACT US AT:   BP:28 1170 WATERMAEL-BOITSFORT 1 BELGIUM!!...
;
;[1m[32m-----------------------------------------------------------------------------[0m
;                           - DON'T SEND ANY DISKS -
;
;[1m[32m-----------------------------------------------------------------------------[0m
;
;
;
;                      [33m THE LEGENDARY >> SUBSOFTWARE << IN 87/88/89/90/91!!...
;                      [1m[32m ------------------------------------------------------
;
;
*---
*--- Programme: traqueur.a
*---
*--- Fonction: traquer les virus de boot ou les virus
*---           coquilles au plus profond des programmes
*---
*--- Utilisation:
*---		- depuis le workench, boote en DF0:
*---		- depuis le CLI:
*---		- boote si pas de paramètre
*---		- teste le programme donné en paramètre
*---
*--- Remarques:	- Ne détruit pas le RAD:
*---		- Ne peut tester une commande DOS because BCPL
*---
*--- Auteur: F MAZUE pour ANT le 16/02/91
*---
*--- Assembleur: Devpac2 (the top !)
*---

 
 incdir "include:"
 include "exec/execbase.i"
 include "exec/libraries.i"
 include "exec/tasks.i"
 include "exec/io.i"
 include "exec/memory.i"
 include "exec/devices.i"
 include "exec/exec_lib.i"
 include "intuition/intuition.i"
 include "intuition/intuition_lib.i"
 include "libraries/dos.i"
 include "libraries/dos_lib.i"
 include "libraries/dosextens.i"
 include "devices/trackdisk.i"
 include "misc/easystart.i"	;pour workbench
 

main
 clr.l Segment
 clr.l Tampon
 clr.l rad
 clr.l prog
 
 movem.l d0/a0,-(sp)

*--- tester existence de rad:
 move.l _SysBase,a6
 move.l KickMemPtr(a6),a3
 cmp.l #$7fdb2,a3
 bne norad
 add.l #$104,a3
 cmpi.l #$52414400,(a3)	;Si le RAD: est présent, le mot RAD
			; (52414400) est ici pointé par a3
 bne norad
 move.l #$1,rad
 lea rad_data,a3		;sauvegarde des vecteurs
 move.l KickMemPtr(a6),(a3)+	;reset du RAD:
 move.l KickTagPtr(a6),(a3)+
 move.l KickCheckSum(a6),(a3)
 
norad
 clr.l CoolCapture(a6)		;nettoyage des vecteurs reset
 clr.l ColdCapture(a6)		;
 clr.l KickMemPtr(a6)		;
 clr.l KickTagPtr(a6)		;
 clr.l KickCheckSum(a6)		;


 moveq #0,d0		;ouverture
 lea dosname,a1		;de
 CALLEXEC OpenLibrary	;la
 move.l d0,_DOSBase	;dos.library
 
 sub.l a1,a1
 CALLEXEC FindTask	;recherche de sa propre adresse de tâche
 move.l d0,Task

 move.l $24,OldTrap	;l'execption Trace du 68000
 move.l #trap,$24	;passe par cette adresse
 
 move.l d0,a0		;ici l'on teste si le programme
 tst.l pr_CLI(a0)	;est lancé depuis le CLI
 beq WorkBench		;ou depuis le workbench
 

 movem.l (sp)+,d0/a0	;récupération de la chaîne
 			;de paramètres
 move.b #$0,-1(a0,d0.w) ;on remplace le CR par un 0
 			;de fin de chaine

 subq #1,d0		;y a-t-il un paramètre ?		
 beq wb1		;non donc aucun fichier à charger...

 move.l #$1,prog	;flag pour choix d'alerte.
 move.l a0,file		;nom de fichier sauvé
 move.l d0,len_file	;longueur du nom de fichier sauvée
 
 move.l a0,d1		;le nom de fichier est-il valide ?
 move.l #MODE_OLDFILE,d2
 CALLDOS Open
 tst.l d1
 beq NoFich 		;et bien non !

 CALLDOS Close
 
 move.l file,d1		;est-ce un fichier éxécutable ?
 CALLDOS LoadSeg
 move.l d1,Segment
 tst.l d1
 beq NoExec		;et bien non !
 
 move.l d1,8(a3)
 add.l d1,d1
 add.l d1,d1		;conversion bcpl
 addq #$4,d1		;cf article BackStart, CR 30 Janvier 91 
 move.l d1,a5		;valeur de saut au programme dans a5

 bra GO 		;est lent
 
WorkBench
 addq #8,sp		;ajustement de la pile
wb1
 move.l #$400,d0	;1024 octets pour le boot
 move.l #(MEMF_CLEAR|MEMF_CHIP),d1	en chip mem
 CALLEXEC AllocMem	;sont réservé
 move.l d0,Tampon
 beq NoMem
 
 lea ReplyPort,a1		;ici est initialisé
 move.l #portname,LN_NAME(a1)	;un (gros) port
 move.l Task,MP_SIGTASK(a1)	;
 CALLEXEC AddPort

 lea DiskIO,a1		;DiskIO est une structure ExtIORequest
 			;à laquelle on attache le port de reply
 			;précédement créé.
 			
 move.l #ReplyPort,MN_REPLYPORT(a1)

 move.l #$0,d0		;unité 0 donc df0:
 clr.l d1		;flag toujours nul
 lea td_name,a0		;nom du device
 CALLEXEC OpenDevice	;device ouvert


 lea DiskIO,a1
 move.w #CMD_CLEAR,IO_COMMAND(a1)	;commande clear pour
 					;forcer juste après la
 					;lecture à chaque fois
 					
 move.l #$400,IO_LENGTH(a1)	;$400 octets = 2 secteurs
 move.l Tampon,IO_DATA(a1)	;adresse buffer
 move.l #0,IO_OFFSET(a1) 	;à partir du secteur 0
 CALLEXEC DoIO

 lea DiskIO,a1
 move.w #CMD_READ,IO_COMMAND(a1)	;commande lire
 move.l #$400,IO_LENGTH(a1)	;$400 octets = 2 secteurs
 move.l Tampon,IO_DATA(a1)	;adresse buffer
 move.l #0,IO_OFFSET(a1) 	;à partir du secteur 0
 CALLEXEC DoIO			;lire
 
 move.b IO_ERROR(a1),FlagDisk	;problème ?

 lea DiskIO,a1				;ici
 move.w #TD_MOTOR,IO_COMMAND(a1)	;l'on arrête
 move.l #$0,IO_LENGTH(a1)		;le
 CALLEXEC DoIO				;moteur
 
 lea ReplyPort,a1	;effacement du port
 CALLEXEC RemPort	;

 lea DiskIO,a1		;fermeture du device
 CALLEXEC CloseDevice
 
 tst.b FlagDisk
 bne NoFormat		;si le secteur boot n'a pu être lu

checksum		;ici on fait le calcul du checksum
 move.l Tampon,a5	;du boot que l'on vient de lire
 move.l 4(a5),d2	;
 clr.l 4(a5)		;si le résultat est égal au
 move.l a5,a0		;checksum lu, c'est qu'il s'agit
 move.w #$00ff,d1	;bien d'un boot
 moveq #$00,d0
checksum1
 add.l (a0)+,d0
 bcc.s checksum2
 addq.l #1,d0
checksum2
 dbf d1,checksum1
 not.l d0
 cmp.l d2,d0
 
 bne NoBoot
 add.l #$0C,a5		;adresse de saut dans A5
 
GO
 CALLEXEC SuperState	;on passe en mode Superviseur
 or.w #$8000,sr		;on place le bit Trace
 CALLEXEC UserState	;et on revient au mode user
 
 pea exit		;on empile l'adresse de fin
 move.l a5,-(sp)	;on empile l'adresse de saut
 lea Dummy_A0,a0	;on fabrique un fausse chaîne
 			;de paramètres
 			;(c'est utile uniquement dans le cas du
 			;traitement d'un fichier éxécutable
 move.l #$1,d0		;
 
 rts		;c'est parti !

 
  
exit
 CALLEXEC SuperState	;mode Superviseur
 and.w #$7fff,sr	;on enlève le bit Trace
 CALLEXEC UserState	;mode User
 tst.l rad		;on reinstalle les vecteurs reset
 beq .exitnorad		;du RAd: si nécéssaire
 bsr repare_rad		;
.exitnorad		;on quitte
 tst.l Tampon		;proprement
 beq .exitnm		;
 move.l Tampon,a1	;
 move.l #$400,d0	;
 CALLEXEC FreeMem	;
.exitnm			;
 tst.l Segment		;
 beq .exitnoseg		;
 move.l Segment,d1	;
 CALLDOS UnLoadSeg	;
.exitnoseg 		;
 move.l _DOSBase,a1	;
 CALLEXEC CloseLibrary 	;
 move.l OldTrap,$24	;
 moveq #0,d0		;
 rts			;

trap			;ici est la routine effectuée en mode trace
 move.l a6,-(sp)
 move.l $4,a6		; on y teste si les vecteurs Reset sont
 tst.l ColdCapture(a6)	;attaqués
 bne virus
 tst.l CoolCapture(a6)
 bne virus
 tst.l KickMemPtr(a6)
 bne virus
 tst.l KickTagPtr(a6)
 bne virus
 tst.l KickMemPtr(a6)
 bne virus
 move.l (sp)+,a6
 rte			;ce n'était pas le cas

virus			;un des vecteurs reset est attaqué
 clr.l ColdCapture(a6)	;on efface tout
 clr.l CoolCapture(a6)	;
 clr.l KickMemPtr(a6)	;
 clr.l KickTagPtr(a6)	;
 clr.l KickCheckSum(a6)	;
 
 move.l (sp)+,a6
 move.l #alert,2(sp)	;on trafique subtilement la pile
 rte			;et on retourne en mode User déclencher
 			;l'alerte
 
*--- Ici est l'envoi de l'alerte en cas de virus
*--- Aucun commentaire n'est nécéssaire
alert
 CALLEXEC SuperState
 and.w #$7fff,sr
 CALLEXEC UserState
 
 move.l #0,d0
 lea intname(pc),a1
 CALLEXEC OpenLibrary
 move.l d0,_IntuitionBase
 
 move.l #RECOVERY_ALERT,d0
 lea alerte_boot,a0
 tst.l prog
 beq .alert1
 lea alerte_coquille,a0
.alert1 
 move.l #100,d1
 CALLINT DisplayAlert
 bne reset
 
 move.l _IntuitionBase,a1
 CALLEXEC CloseLibrary
 rts
 
reset			;routine Reset béton qui tue n'importe
			;quel virus en mémoire
 CALLEXEC Disable
 move.l #0,ColdCapture(a6) 	;a6 pointe ici sur execbase
 move.l #0,CoolCapture(a6)
 move.l #0,KickMemPtr(a6)
 move.l #0,KickTagPtr(a6)
 move.l #0,KickCheckSum(a6)

*--- Routine Reset officile (cf. RKM dernière version)
ABSEXECBASE	    EQU 4	    ;Pointer to the Exec library base
MAGIC_ROMEND	    EQU $01000000   ;End of Kickstart ROM
MAGIC_SIZEOFFSET    EQU -$14	    ;Offset from end of ROM to Kickstart size
V36_EXEC	    EQU 36	    ;Exec with the ColdReboot() function
TEMP_ColdReboot     EQU -726	    ;Offset of the V36 ColdReboot function

_ColdReboot:
	move.l	ABSEXECBASE,a6
	cmp.w	#V36_EXEC,LIB_VERSION(a6)
	blt.s	old_exec
	jmp	TEMP_ColdReboot(a6)     ;Let Exec do it...
	;NOTE: Control flow never returns to here

;--- manually reset the Amiga
old_exec:
	lea.l	GoAway(pc),a5           ;address of code to execute
	jsr	_LVOSupervisor(a6)      ;trap to code at (a5)...
	;NOTE: Control flow never returns to here

;--- MagicResetCode - DO NOT CHANGE-
	CNOP	0,4			;IMPORTANT! Longword align!
GoAway:	lea.l	MAGIC_ROMEND,a0 	;(end of ROM)
	sub.l	MAGIC_SIZEOFFSET(a0),a0 ;(end of ROM)-(ROM size)=PC
	move.l	4(a0),a0                ;Get Initial Program Counter
	subq.l	#2,a0			;now points to second RESET
	reset				;first RESET instruction
	jmp	(a0)                    ;CPU Prefetch executes this
	;NOTE: the RESET and JMP instructions must share a longword!

alerte_coquille
 dc.b 0,150,15,'ATTENTION les vecteurs Reset sont touchés !!!',0,1
 dc.b 0,150,30,"Il s'agit probablement d'un VIRUS COQUILLE",0,1
 dc.b 0,150,45,'Left = Tuer le virus de façon certaine',0,1
 dc.b 0,150,60,'Right = Continuer à vos risques et périls',0,1
 dc.b 0,150,80,"PS:  guru's name is F MAZUE   ( Yeaah !)",0,0
 
alerte_boot
 dc.b 0,150,15,'ATTENTION les vecteurs Reset sont touchés !!!',0,1
 dc.b 0,150,30,"Il s'agit probablement d'un VIRUS dans le BOOT",0,1
 dc.b 0,150,45,'Left = Tuer le virus de façon certaine',0,1
 dc.b 0,150,60,'Right = Continuer à vos risques et périls',0,1
 dc.b 0,150,80,"PS:  guru's name is F MAZUE   ( Yeaah !)",0,0

repare_rad
 move.l _SysBase,a6
 lea rad_data,a3
 move.l (a3)+,KickMemPtr(a6)
 move.l (a3)+,KickTagPtr(a6)
 move.l (a3),KickCheckSum(a6) 
 rts

NoFich
 pea exit
 CALLDOS Output
 move.l #nofich_msg,d2
 move.l #(fin_nofich_msg-nofich_msg),d3
 CALLDOS Write
 rts

NoExec
 pea exit
 CALLDOS Output
 move.l len_file,d3
 move.l file,d2
 CALLDOS Write
 
 CALLDOS Output 
 move.l #noexec_msg,d2
 move.l #(fin_noexec_msg-noexec_msg),d3
 CALLDOS Write
 rts
 
NoMem
 pea exit
 CALLDOS Output
 beq .exit
 move.l #nomem_msg,d2
 move.l #(fin_nomem_msg-nomem_msg),d3
 CALLDOS Write
.exit 
 rts

NoFormat
 pea exit
 CALLDOS Output
 beq .exit
 move.l #nofor_msg,d2
 move.l #(fin_nofor_msg-nofor_msg),d3
 CALLDOS Write
.exit 
 rts
 
NoBoot
 pea exit
 CALLDOS Output
 beq .exit
 move.l #noboot_msg,d2
 move.l #(fin_noboot_msg-noboot_msg),d3
 CALLDOS Write
.exit 
 rts 

**************************************
dosname DOSNAME
intname INTNAME
td_name TD_NAME

_DOSBase	dc.l 0
_IntuitionBase	dc.l 0
Dummy_A0	dc.b $0A,0
Task		dc.l 0
OldTrap		dc.l 0
Segment		dc.l 0
Tampon		dc.l 0
FlagDisk	dc.b 0,0
Pile		dc.l 0
file		dc.l 0
len_file	dc.l 0
prog		dc.l 0
rad		dc.l 0
rad_data	dcb.l 3,0 
portname	dc.b 'monport',0
		even
 

nomem_msg
 dc.b $0A,"Il n'y a pas suffisament de mémoire chip"
 dc.b $0A,'pour lire les secteurs boot'
 dc.b $0A,$0A,0
fin_nomem_msg
 even

nofich_msg
 dc.b $0A,"Il n'y a pas d'abonné au numéro"
 dc.b $0A,'que vous avez demandé'
 dc.b $0A,$0A,0
fin_nofich_msg
 even
 
noexec_msg
 dc.b $20,"n'est pas un éxécutable"
 dc.b $0A,$0A,0
fin_noexec_msg
 even

nofor_msg
 dc.b $0A,"Il y a un problème, cette disquette"
 dc.b $0A,"ne doit pas être formatée correctement"
 dc.b $0A,$0A,0
fin_nofor_msg
 even
 
noboot_msg
 dc.b $0A,"Cette disquette n'est pas AutoBoot !!"
 dc.b $0A,$0A,0
fin_noboot_msg
 even

DiskIO		dcb.b IOTD_SIZE	;structure IOrequest étendue
ReplyPort	dcb.b MP_SIZE 	;taille d'un message port

