COMMENT /*
Here is the code for a MBR password protection
A few remarks
- this one stealths itself, so windows 32 bits access will yell
- there is a backdoor built in for de-installation
- comments are partly in french, sorry
- there is a break point to debug the MBR loading process in our debugger
- CRTL-ALT-DEL is hooked, regardless of the national keyboard driver
- supports three users and passwords
- crashing the floppy boot is easily achieved when you know that "circular
partitions" will crash DOS > 3 at load time
Pierre
*/
page 60,200
.286
;*************************************************************************
; SAC - Simple Access Control
; Public Domain Version
; (c) 1995-1996 DataRescue sprl
; 110, route du condroz
; 4121 Neupre
; Belgium
; Tel : +32 41 729 110
; Fax : +32 41 729 114
; bbs : +32 41 720 237
; http://www.datarescue.com
; H.Carette and P.Vandevenne
;*************************************************************************
; segment bidon pour un saut FAR
farseg segment at 00000h
org 07c00h
farlabel label far
farseg ends
;**************************************************************************
cseg segment public byte 'code'
assume cs:cseg,ds:cseg,ss:cseg
org 0000h
SECTEUR_MBR equ 0002h
ctrl equ 0100b ; pour masquer alt-ctrl-del
alt equ 1000b ; pour masquer alt-ctrl-del
buffer equ 0200h ; adresse du buffer de saisie
start: jmp short debut
passe db 39,24,20,32,18,25,16,31 ; mots de passe
db 39,24,20,32,18,25,16,31
db 39,24,20,32,18,25,16,31
ID_nom db 25,23,18,19,19,18,0,0 ; utilisateurs
db 35,18,19,47,18,0,0,0
db 32,18,38,25,35,23,49,18
login db 'Nom?',0ah,0dh,00h ; 1 er message
mdpasse db 'Passe?',0ah,0dh ; 2 ième message
; le zéro de asciiiz = flag
stealthflag db 00 ; quand ce flag est a 0
; on stealthe
debut: int 3 ; pour SOFT-ICE
xor CX , CX ; BX = 0
mov DS , CX ; DS = 0
mov AX , DS:[0413h] ; taille mémoire var BIOS
dec AX ; réserver 1 Ko
mov DS:[0413h], AX ;
shl AX , 6 ; 80x86 -> 3 octets
mov ES , AX ; segment du K réservé
mov SI , 7C00h ; offset du MBR en mémoire
xor DI , DI ; offset zéro
mov CH , 01h ; 100 words
cld ; dans le bon sens
rep movsw ; on déplace
mov AX , OFFSET ici ; offset de retour
push ES ; pousser segment de retour
push AX ; pousser offset de retour
retf ; y aller
ici: cli
; détourne l'interruption 15h
LES AX , DS:054h ; offset du vecteur de l'int 15
mov CS:word ptr [adresse15h],AX
mov CS:word ptr [adresse15h+2],ES
mov DS:word ptr 054h, OFFSET int15
mov DS:word ptr 056h, CS
; Détourne l'interruption 13h
LES AX, DS:04Ch ; offset du vecteur de l'int 13
mov CS:word ptr [adresse13h],AX
mov CS:word ptr [adresse13h+2],ES
mov DS:word ptr 04Ch, OFFSET int13
mov DS:word ptr 04Eh, CS
push CS ; le DS est ici maintenant
pop DS ; demander ID et mot de passe
mov AX , 0003h ; pour effacer l'écran
int 10h ;
push DS ; DS=ES=SS=CS pour les cmp
pop ES ;
; (premier = 0)
mov DL , 03
push DX
next_essai: mov BP , 0002h ; nombre d'utilisateurs - 1
mov SI , offset login ; pointer le login
call printasciiz ; l'afficher
call saisie ; saisir l'ID
next_ID: mov DI , offset ID_nom ; pointer les utilisateurs
call newID ; pointer nom courant
call verification ; vérifier ID
jnc ID_OK ; pas d'erreur tout est OK
dec BP ; id suivant
jns next_ID ; ce n'est pas le cas
dec DL
jnz next_essai ; essai suivant
call hang ; arrêt
ID_OK:
pop DX
next_essai_mdp: mov SI , offset mdpasse ; pointer passe?
call printasciiz ; l'afficher
mov DI , offset passe ; pointer les mots de passe
call newID ; pointer le mot de l'ID
call saisie ; saisir le mot de passe
call verification ; vérifier le mot de passe
jnc tout_ok ; bon mot de passe
mov AX , 0E08h ; beep
int 10h
dec DL
jnz next_essai_mdp ; essai suivant
call hang ; arrêt
tout_ok: xor BX, BX ; charger le mbr et l'exécuter
mov ES , BX ; ES = 0000
mov BX , 7C00h ; offset buffer pour int 13h
mov DX , 0080h ; disque dur 1, tête 0
mov CX , SECTEUR_MBR ; cylindre 0 , secteur ?
mov DI , 0004h ; nombre d'essai ( lecture )
loop_1: xor AX , AX ; AX = 0000
int 13h
mov AX , 0201h ; lecture d'un secteur
int 13h
jnc lecture_ok ; pas de problème
dec DI ; décrémenter le cpt d'essai
jnz loop_1 ; si pas zéro, alors recommencer
int 18h ; appel de la ROM BASIC
lecture_ok: push CS
pop ES
jmp farlabel
; Gestionnaire INT13h
int13: cmp AH, 0CFh ; notre appel ?
jnz int13_1 ; non, on continue
not CS:byte ptr [stealthflag]; inverse le flag
iret ; retour
int13_1: cmp CS:byte ptr [stealthflag], 0 ; stealth
jnz real_int13 ; non, on laisse aller
cmp DX , 0080h ; disque C , tête 0
jne real_int13 ; non
test CX , 11111111000000b ; cylindre 0 ?
jnz real_int13 ; non, on laisse aller
test CL , 00111110b ; secteur 1 ?
jnz real_int13 ; non, on laisse aller
mov CL , SECTEUR_MBR ; modifier l'appel
real_int13: db 0EAh ; jmp far
adresse13h dd 0 ; adresse handler int 13
; Gestionnaire INT15h
int_15 proc ; nouveau gestionnaire
; de l'int 15
int15:
push AX ;
push DS ; save registers
cmp AH, 04Fh ;
jne go_ahead ;
xor AX,AX ;
mov DS,AX ;point DS to BIOS data area
mov AL,DS:(417h) ;get keyboard flags
and al,ctrl+alt ;clear non relevant bits
cmp al,ctrl+alt ;compare to our map
jne go_ahead ;NO CTRL+ALT keys pressed
and byte ptr ds:(417h),not alt ;CTRL+ALT pressed
;clear ALT key bit to simulate
;ALT key is not pressed
go_ahead:
pop DS
pop AX
db 0EAh
adresse15h dd 0
int_15 endp
; ************* HANG **********************************************************
hang proc
boucle: cli ; no interruptions
jmp short boucle
hang endp
; ************* PRINTASCIIZ ***************************************************
Printasciiz proc
pusha
cld ; memory up
Print: lodsb
OR AL,AL
JZ ExitPrint ;jmp to RET instr.
call print_one
JMP short Print
ExitPrint:
popa
ret
Printasciiz endp
; ************* NEWID *********************************************************
newID proc
push BP ; sauver le compteur d'ID
shl BP , 03
add DI , BP ; ajouter
pop BP ; récupérer le cpt d'ID
ret
newID endp
;************** SAISIE ********************************************************
saisie proc
xor BX , BX ; bx = 0
next_char: xor AX , AX ; lire caractère
push BX
int 16h ;
pop BX
mov [ buffer ] [ BX ] , AH ; stocker le caractère
cmp AL , 0Dh ; CR ?
jz fin_saisie ; oui
mov AL , '*' ; star
call print_one
inc BX ; next char
cmp BX , 0008 ; buffer plein ?
jnz next_char ; non, alors char suivant
fin_saisie: mov AL , 0Dh
call print_one
ret
saisie endp
; ************* PRINT_ONE *****************************************************
print_one proc
mov AH , 0Eh
int 10h
ret
print_one endp
; ************* VERIFICATION **************************************************
verification proc
mov SI , buffer
mov CX , 0008 ; nbr de char
repz cmpsb ; comparer buffer et ID/mdp
jcxz fin_verif ; 8 char et = tous
cmp byte ptr [ SI - 0001 ] , 28 ; = jusqu'au CR ?
jz cr_only ; oui, alors tester si CR seul
iz_no_goud: stc ; non, alors erreur
ret
cr_only: cmp CL , 07 ; un char = CR ?
jz iz_no_goud ; oui
fin_verif: clc ; pas d'erreur
ret
verification endp
; *****************************************************************************
db 84 dup (01h)
db 055h
db 0aah
cseg ends
end start ;end of program