pascals.blog

Pascal Sauliere | Microsoft France | Infrastructure, sécurité, cloud, et plus si affinités

Bitlocker : analyse du MBR de Windows Vista

Bitlocker : analyse du MBR de Windows Vista

  • Comments 1
  • Likes

Quel rapport entre le Master Boot Record (MBR) d'un disque dur et Bitlocker ? Une des fonctions de Bitlocker est le Secure Startup. Cette fonction consiste à s'assurer que le système ne démarre que si le code de démarrage pré-OS (du BIOS jusqu'à bootmgr, avant winload.exe) n'a pas changé depuis l'activation de Bitlocker. Si un bit de cette chaîne de code a changé, le TPM ne déchiffrera pas la clé de chiffrement du disque système.

Dans cette chaîne de code pré-OS se trouve le MBR du disque : lors du démarrage d'un PC sur un disque dur, le BIOS charge le MBR (secteur 0) du disque et l'exécute. Celui-ci lit la table de partition qu'il contient, identifie la partition active, charge son secteur de boot (premier secteur de la partition) et l'exécute.

Avec Vista cette séquence est modifiée pour le Secure Startup : le BIOS charge le MBR, le hashe dans le PCR (Platform Configuration Register) 4 du TPM, puis l'exécute. A son tour, le MBR charge le secteur de boot de la partition active, le hashe dans le PCR 8 du TPM, puis l'exécute, et ainsi de suite.

A la fin du processus de boot, un certain nombre de PCR du TPM sont renseignés par les hashes des différents codes exécutés. Lorsque bootmgr demande au TPM de déchiffrer la clé Bitlocker (en fait la Volume Master Key - VMK) du disque système, le TPM ne répond favorablement que si les valeurs de tous ces PCR sont identiques à ce qu'elles étaient au moment de l'activation de Bitlocker.

Intéressons-nous aujourd'hui à cette phase durant laquelle, comme dit plus haut, le MBR charge le secteur de boot de la partition active, le hashe dans le PCR 8 du TPM, puis l'exécute. Il y a à peu près un an, j'étais en train de travailler sur Bitlocker pour une formation que je préparais, et toute cette théorie sur le Secure Startup me paraissait trop vague pour l'expliquer correctement. J'ai alors décidé de désassembler le MBR, pour voir et comprendre comment se faisait ce hash. Car je suis comme ça : je ne comprends que ce que je vois ! :)

Pour rappel, le MBR est écrit en assembleur et son code est assez court puisque dans 512 octets doivent tenir le code, les messages d'erreurs correspondants, et la table des partitions. Il s'agit de code Intel en mode réel. Pour ceux qui étaient nés et qui s'en souviennent, au début des années 80, c'est l'assembleur que l'on utilisait sous MS-DOS : la mémoire adressée sur 20 bits (donc 1 Mo adressable) mais avec segmentation. Une adresse mémoire est représentée par un segment et un offset, chacun de 16 bits, et l'adresse physique est déterminée par segment * 0x10 + offset.

Avant de continuer sur l'analyse du MBR, rappelons que le TPM répond à une spécification TCG v1.21 (Trusted Computing Group). Microsoft a publié en mai 2006 le document Windows Vista BitLocker Client Platform Requirements qui décrit en détail les interfaces que doit supporter le BIOS d'une machine équipée d'un TPM pour que Bitlocker fonctionne. Extrait : The BIOS must expose a TCG INT 1Ah, sub-function BBh interface to pre-operating system environment applications. C'est à dire que c'est à travers l'interruption 1AH, avec AH=BBh, que le code en mode réel accède aux fonctions du TPM.

Première étape : extraire le MBR sous la forme d'un fichier. N'importe quel Windows Vista installé fera l'affaire : même si Bitlocker n'est disponible qu'avec les versions Enterprise et Ultimate, le MBR est le même pour toutes les versions et comporte toujours ce code de hash du secteur de boot par le TPM.

Sector Inspector (SecInspect.exe) est un outil en téléchargement gratuit qui suffira amplement. Après l'avoir installé, utilisez simplement la commande suivante, dans une ligne de commande Administrateur :

secinspect.exe -backup PhysicalDrive0 mbr.bin 0 1

Le fichier mbr.bin contient maintenant la copie du MBR. Utilisons encore SecInspect.exe pour afficher en hexa le fichier mbr.bin (cette fois, il est inutile d'être administrateur puisque nous ne faisons que lire un fichier, et non le disque physique) :

secinspect.exe -dfile mbr.bin

Le résultat ressemble à ceci :

secinspect-dfile-mbr.bin

Le code se trouve de l'offset 0 à l'offset 0x0161. Les messages d'erreur de 0x0162 à 0x01b4, et finalement la table des partitions de 0x01be à 0x01fd. Les deux derniers octets (55 aa) forment la signature du MBR.

Si l'on regarde bien le code en hexa, on remarque deux instructions "cd 1a". Ces deux octets forment l'instruction INT 1Ah. Comme dit précédemment, cela doit correspondre aux instructions du TPM pour hasher le secteur de boot.

Deuxième étape : désassembler le MBR. Pour ce faire, j'ai utilisé IDA Pro Freeware Freeware v4.3, dernière version freeware de IDA Pro. Passons sur le processus de désassemblage : après un peu de renommage de variables et de labels, on arrive assez rapidement à quelque chose de clair. Concentrons-nous plutôt sur les sections de code les plus importantes.

Analyse du code du MBR

Le BIOS charge toujours le MBR à l'adresse 0000:7C00. Comme le MBR charge plus tard le secteur de boot à la même adresse, la première chose qu'il fait est de se copier à l'adresse 0000:0600 et de continuer son exécution à ce nouvel emplacement :

seg000	segment	byte public 'CODE' use16
	assume	cs:seg000
	;org 600h
	assume	es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
	xor	ax, ax		; Executing at 0000:C700h
	mov	ss, ax		; SS=0000
	assume	ss:seg000
	mov	sp, 7C00h
	mov	es, ax		; ES=0000
	mov	ds, ax		; DS=0000
	mov	si, 7C00h	; Source=0000:7C00h
	mov	di, 600h	; Target=0000:0600h
	mov	cx, 200h	; Length=0200h=512
	cld
	repe	movsb		; Copy MBR from 0000:C700h to 0000:0600h
	push	ax
	push	61Ch
	retf			; Jump at 0000:061Ch
	sti			; Now at 0000:061Ch

Il enchaîne directement sur la boucle d'analyse de la table des partitions à l'offset 0600+01be = 07be :

	mov	cx, 4
	mov	bp, 7BEh
check_entry:
	cmp	byte ptr [bp+0], 0
	jl	active_entry
	jnz	invalid_table
	add	bp, 10h		; Next entry
	loop	check_entry
	int	18h		; retour au BIOS
active_entry:

Le code précédent cherche la partition active en testant si le bit de poids fort est à 1 dans le 1er octet (0x80). Si aucune partition active n'est présente, alors on rend la main au BIOS (pour info l'instruction INT 18h, sur les premiers IBM-PC, donnait la main au BASIC en ROM...)

Une fois la partition active trouvée, on lit son secteur de boot en 0000:7C00. Le code est un peu trop long pour être présenté ici dans son intégralité, du fait d'une gymnastique un peu lourde en fonction de la présence ou non des extensions de l'INT 13h du BIOS pour lire le disque.

C'est une fois le secteur de boot chargé que les choses deviennent intéressantes.

Vérification de la signature 55 AA à la fin du secteur de boot :

check_boot_sect:
	cmp	word ptr ds:7DFEh, 0AA55h
	jnz	missing_os
	push	word ptr [bp+0]	; Sauvegarde du numéro lecteur

Suit ensuite un bout de code dont le but est d'activer la "ligne d'adresse A20" afin de gérer l'adressage au-delà d'1 Mo (requis par certains BIOS TCG). Ce bout de code gère le contrôleur clavier 8042 pour éviter les conflits. Tout ceci n'est pas extrêmement clair pour moi, mais peu importe, la suite est plus intéressante.

Arrive ensuite le test de présence du TPM. D'après Windows Vista BitLocker Client Platform Requirements, la fonction TCG_StatusCheck (INT 1Ah avec AX=BB00h) renvoie EBX=41504354h ("TCPA") si un TPM est présent et si le BIOS est compatible, et la version du BIOS TCG dans CX (0102h pour 1.2). Ce test est effectué ici :

check_TPM:
	mov	ax, 0BB00h
	int	1Ah		; TCG_StatusCheck
	and	eax, eax
	jnz	exec_boot_sect
	cmp	ebx, 41504354h	; "TCPA"
	jnz	exec_boot_sect
	cmp	cx, 102h
	jb	exec_boot_sect

Vient ensuite le hash du secteur de boot, grâce à la fonction TCG_CompactHashLogExtendEvent (INT 1Ah avec AX=0B07h) :

hash_boot_sect:			; AX=BB07h: TCG_CompactHashLogExtendEvent
	push	large 0BB07h
	push	large 200h	; ECX: length of buffer to be hashed=512
	push	large 8		; EDX: PCR Number=8
	push	ebx		; EBX: 41504354h
	push	ebx
	push	ebp		; BP
	push	large 0		; SI
	push	large 7C00h	; DI: offset of	buffer to be hashed = 7C00h
	popad
	push	0
	pop	es		; ES: segment of buffer	to be hashed = 0
	assume	es:seg000
	int	1Ah		; TCG_CompactHashLogExtendEvent

Comme on le voit, le hash est effectué par le TPM : le MBR lui fournit le numéro de PCR destination et le buffer à hasher, et le TPM effectue l'opération.

Puis vient l'exécution du secteur de boot, sans explication nécessaire :

exec_boot_sect:
	pop	dx
	xor	dh, dh
	jmp	far ptr	0:7C00h

Cet article montre de quelle façon le MBR de Vista participe à la chaîne de confiance du Secure Startup de Bitlocker en faisant hasher le secteur de boot par le TPM dans le PCR 8. Finalement, les vieux souvenirs d'assembleur peuvent toujours servir !

Pour en savoir plus

[03/12/2007 - quelques corrections et ajouté comme référence la spécification TCG 1.2]

Comments
Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment