Quelle est l’importance de nos jours de s’assurer que toutes mes DLL ont des adresses de base non conflictuelles ?

Raymond

20 Janvier, 2017

À l’époque, l’une des choses que vous étiez invité à faire était de rebaser vos DLL afin qu’elles aient toutes des plages d’adresses non superposées, évitant ainsi le coût de la relocalisation de l’exécution. Est-ce encore important de nos jours?

Cette situation est une autre démonstration de l’importance pour un bon conseil d’être accompagné d’une justification afin que vous puissiez savoir quand cela devient un mauvais conseil.

La justification du rebasage est la suivante: Si une DLL est chargée à son adresse de base préférée, l’image peut être paginée directement depuis le magasin de sauvegarde sans nécessiter de correctifs. Cela signifie que les pages peuvent être partagées entre les processus, car chaque processus obtient une copie identique. (Bien sûr, le partage s’arrête une fois que quelqu’un écrit sur la page et rend sa copie différente de la copie partagée.)

Si une DLL ne peut pas être chargée à son adresse préférée, l’image sera déplacée et la totalité de la DLL déplacée est maintenant sauvegardée par le fichier de page.1 C’est une opération relativement coûteuse, car la DLL doit être lue à partir du disque et corrigée, et des frais de validation sur le fichier de page sont engagés afin de garantir qu’il y a de l’espace pour écrire les pages corrigées. De plus, si deux processus relocalisent la DLL et se produisent par coïncidence pour les déplacer au même endroit, Windows NT ne tente pas de partager les images déplacées. Il y aura plusieurs copies dans le fichier de page.

Le coût de cette relocalisation dynamique est ce que le rebasage tente d’éviter. Appelons cela la “pénalité de relocalisation.”

Entrez ASLR.

ASLR provoque le chargement des DLL à des adresses pseudo-aléatoires. Par conséquent, une DLL ne se chargera à son adresse de base préférée qu’en cas de coïncidence étonnante.

D’accord, revenons donc à la justification pour voir si cela s’applique toujours.

Une DLL chargée loin de son adresse de base préférée entraîne-t-elle une pénalité de relocalisation ? Si vous y réfléchissez, ASLR signifie qu’aucune DLL ne se charge jamais à son adresse préférée, mais nous avons également vu que le noyau fait des aménagements pour cela afin que les DLL soumises à ASLR puissent toujours partager des pages, et cela sans forcer la DLL entière à être déplacée lors du chargement initial. Il n’y a donc pas de pénalité de relocalisation dans le cas où la DLL a été relocalisée par ASLR.

Mais que se passe-t-il si la DLL est déplacée pour une autre raison? Par exemple, il se peut que l’adresse de base choisie par ASLR ne soit pas disponible dans le processus, car le processus a déjà alloué autre chose à cet emplacement. Dans ce cas, une réinstallation traditionnelle doit avoir lieu et vous payez la pénalité de réinstallation.

Ah, mais voici la chose: Lorsqu’une DLL est chargée, ASLR assignera une adresse de base de manière aléatoire parmi les adresses de base disponibles qui ne sont pas déjà utilisées.2 Vous n’allez donc pas entrer dans le scénario “l’adresse de base choisie par ASLR n’est pas disponible” car ASLR choisit l’adresse de base de la DLL parmi l’adresse de base disponible.3

D’accord, donc vous pouvez toujours entrer dans une situation de conflit, mais vous devez vraiment y travailler. Par exemple, vous pouvez charger une DLL dans un processus et obtenir une adresse de base assignée par ASLR. Vous démarrez ensuite un deuxième processus, allouez intentionnellement de la mémoire à cette adresse (pour forcer la collision), puis chargez la DLL. Dans ce cas, il y aura un déménagement car vous vous êtes accroupi à l’endroit où ASLR voulait mettre la DLL. Mais ce n’est pas pire que ce que vous aviez avant ASLR: Dans le monde pré-ASLR, s’accroupir sur l’adresse de base préférée d’une DLL aurait de toute façon forcé une pénalité de relocalisation.

Voyons donc quelle est l’histoire. Pour rebaser ou ne pas rebaser?

En présence d’ASLR, le rebasage de vos DLL n’a aucun effet car ASLR va de toute façon ignorer votre adresse de base et déplacer la DLL dans un emplacement de son choix pseudo-aléatoire.

Attention, même si le rebasage n’a aucun effet, cela ne fait pas de mal non plus.

Si vous êtes sur un système sans ASLR (soit parce qu’il est antérieur à ASLR, soit parce qu’ASLR a été désactivé pour une raison quelconque), le rebasage aidera, pour les raisons traditionnelles.

Attention, les systèmes sans ASLR sont vraiment difficiles à trouver de nos jours, donc le rebasage n’apporte aucun avantage dans la très grande majorité des cas. Mais dans ce petit pourcentage de cas où vous n’avez pas d’ASLR, le rebasage aide.

Conclusion: Cela ne fait pas de mal de rebaser, au cas où, mais comprenez que le gain sera extrêmement rare. Créez votre DLL avec /DYNAMICBASE activé (et avec /HIGHENTROPYVA pour faire bonne mesure) et laissez ASLR s’assurer qu’aucune collision d’adresse de base ne se produit. Cela couvrira à peu près tous les scénarios du monde réel. S’il vous arrive de tomber dans l’un des très rares cas où ASLR n’est pas disponible, votre programme fonctionnera toujours. Il peut juste fonctionner un peu plus lentement en raison de la pénalité de relocalisation.

1 Plus précisément, toutes les pages contenant des correctifs sont placées dans le fichier de page. Nous avons discuté de ce point plus fin la dernière fois.

2 D’accord, il y a un troisième cas, où ASLR n’a tout simplement plus d’adresses de base. Mais encore une fois, ce n’est pas pire que ce que vous aviez avant ASLR: Si vous manquez d’adresses de base, alors c’est chacun pour soi. Chaque fois qu’une nouvelle DLL se charge, le noyau doit parcourir une partie suffisamment importante de l’espace d’adressage disponible pour charger la DLL.

3 En conséquence, ASLR évite mieux les collisions que le rebasage manuel, car ASLR peut visualiser le système dans son ensemble, alors que le rebasage manuel vous oblige à connaître toutes les DLL chargées dans votre processus, et la coordination des adresses de base entre plusieurs fournisseurs n’est généralement pas possible.

Raymond Chen

Suivre

Leave a Reply