Metropoli BBS
VIEWER: sac.asm MODE: TEXT (CP437)
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
[ RETURN TO DIRECTORY ]