hvor vigtigt er det i dag at sikre, at alle mine DLL ‘ er har ikke-modstridende baseadresser?
Raymond
20. januar, 2017
dengang, en af de ting, du blev formanet til at gøre, var at rebase dine DLL ‘ er, så de alle havde ikke-overlappende adresseområder, derved undgås omkostningerne ved flytning af runtime. Er det stadig vigtigt i dag?
denne situation er endnu en demonstration af, hvordan det er vigtigt for gode råd at komme med en begrundelse, så du kan fortælle, hvornår det bliver dårligt råd.
begrundelsen for rebasing går sådan: hvis en DLL er indlæst på sin foretrukne basisadresse, kan billedet sidestilles direkte fra backing store uden at kræve nogen rettelser. Dette betyder, at siderne kan deles mellem processer, da hver proces får en identisk kopi. (Selvfølgelig stopper delingen, når nogen skriver til siden og gør deres kopi forskellig fra den delte kopi.)
hvis en DLL ikke kan indlæses på den foretrukne adresse, flyttes billedet, og hele den flyttede DLL understøttes nu af sidefilen.1 Dette er en relativ dyr operation, da DLL ‘ en skal læses fra disken og fastgøres, og der opstår en forpligtelsesafgift til sidefilen for at sikre, at der er plads til at skrive de faste sider. Desuden, hvis to processer flytte DLL og ske ved en tilfældighed at flytte dem til det samme sted, vinduer NT forsøger ikke at dele de flyttede billeder. Der vil være flere kopier i sidefilen.
omkostningerne ved denne dynamiske flytning er, hvad rebasing forsøger at undgå. Lad os kalde dette ” flytningsstraf.”
indtast ASLR.
ASLR får DLL ‘ erne til at blive indlæst på pseudo-tilfældige adresser. Derfor indlæses en DLL kun på sin foretrukne basisadresse i tilfælde af en forbløffende tilfældighed.
Okay, så lad os gå tilbage til begrundelsen for at se, om det stadig gælder.
medfører en DLL, der indlæses væk fra sin foretrukne basisadresse, en flytningsstraf? Hvis du tænker over det, betyder ASLR, at ingen DLL nogensinde indlæses på sin foretrukne adresse, men vi så også, at kernen gør indkvartering til dette, så DLL ‘er, der udsættes for ASLR, stadig kan dele sider, og det gør det uden at tvinge hele DLL’ en til at blive flyttet ved indledende belastning. Så der er ingen flytningsstraf i det tilfælde, hvor DLL blev flyttet af ASLR.
men hvad nu hvis DLL flyttes af en anden grund? For eksempel kan det være, at den ASLR-valgte basisadresse ikke er tilgængelig i processen, fordi processen allerede tildelte noget andet på det sted. I så fald skal en traditionel flytning finde sted, og du betaler flytningsstraffen.
Ah, men her er sagen: når en DLL er indlæst, tildeler ASLR en basisadresse tilfældigt blandt de tilgængelige basisadresser, der ikke allerede bruges.2 så du kommer ikke ind i scenariet “den ASLR-valgte basisadresse er ikke tilgængelig”, fordi ASLR vælger DLL ‘ s basisadresse blandt den tilgængelige basisadresse.3
Okay, så du kan stadig komme ind i en konfliktsituation, men du skal virkelig arbejde på det. For eksempel kan du indlæse en DLL i en proces og få en ASLR-tildelt basisadresse. Du starter derefter en anden proces, med vilje tildele hukommelse på den adresse (for at tvinge kollisionen) og derefter indlæse DLL ‘ en. I dette tilfælde vil der være en flytning, fordi du sad på huk på det sted, hvor ASLR ønskede at sætte DLL. Men dette er ikke værre end hvad du havde før ASLR: i pre-ASLR-verdenen ville hukning på en dlls foretrukne basisadresse alligevel have tvunget en flytningsstraf.
så lad os se, hvad historien er. At rebase eller ikke at rebase?
i nærværelse af ASLR har rebasing dine DLL ‘er ingen effekt, fordi ASLR alligevel vil ignorere din baseadresse og flytte DLL’ en til en placering af dens pseudo-tilfældige valg.
husk dig, selvom rebasing ikke har nogen effekt, gør det heller ikke ondt.
hvis du er på et system uden ASLR (enten fordi det går forud for ASLR, eller fordi ASLR er blevet deaktiveret af en eller anden grund), vil rebasing hjælpe af de traditionelle grunde.
husk, systemer uden ASLR er virkelig svære at finde i dag, så rebasing giver ingen fordel i det overvældende flertal af tilfælde. Men i den forsvindende lille procentdel af tilfælde, hvor du ikke har ASLR, hjælper rebasing.
konklusion: Det gør ikke ondt at rebase, bare i tilfælde, men forstå, at udbetalingen vil være ekstremt sjælden. Byg din DLL med /DYNAMICBASE
aktiveret (og med /HIGHENTROPYVA
for godt mål), og lad ASLR gøre arbejdet med at sikre, at der ikke opstår nogen baseadressekollision. Det vil dække stort set alle de virkelige scenarier. Hvis du tilfældigvis falder ind i et af de meget sjældne tilfælde, hvor ASLR ikke er tilgængelig, fungerer dit program stadig. Det kan bare køre lidt langsommere på grund af flytningsstraffen.
1 mere præcist sættes alle de sider, der indeholdt rettelser, i sidefilen. Vi diskuterede dette finere punkt sidste gang.
2 Okay, der er et tredje tilfælde, hvor ASLR simpelthen er løbet tør for basisadresser. Men igen er dette ikke værre end hvad du havde før ASLR: hvis du løber tør for basisadresser, så er det hver mand for sig selv. Hver gang en ny DLL indlæses, skal kernen scrounge rundt for en stor nok del af tilgængelig adresserum til at indlæse DLL ‘ en.
3 som et resultat gør ASLR faktisk et bedre stykke arbejde med at undgå kollisioner end Manuel rebasing, da ASLR kan se systemet som helhed, mens manuel rebasing kræver, at du kender alle de DLL ‘ er, der er indlæst i din proces, og det er generelt ikke muligt at koordinere baseadresser på tværs af flere leverandører.
Raymond Chen
Følg
Leave a Reply