jak důležité je v dnešní době zajistit, aby všechny mé DLL měly nekonfliktní základní adresy?

Raymonda

20. ledna, 2017

zpět v den, jedna z věcí, které jste byli nabádáni k tomu bylo rebase DLL tak, že všichni měli nonoverlapping rozsahy adres, čímž se zabrání náklady na runtime přemístění. Je to v dnešní době stále důležité?

tato situace je další ukázkou toho, jak je důležité, aby dobrá rada přišla s odůvodněním, abyste mohli říct, kdy se stane špatnou radou.

zdůvodnění rebasingu je následující: pokud je DLL načtena na preferovanou základní adresu, pak může být obrázek stránkován přímo z úložiště zálohování bez nutnosti oprav. To znamená, že stránky lze sdílet mezi procesy, protože každý proces získá identickou kopii. (Samozřejmě, sdílení se zastaví, jakmile někdo zapíše na stránku a jejich kopie se liší od sdílené kopie.)

pokud DLL nelze načíst na preferovanou adresu, bude obrázek přemístěn a celá přemístěná DLL je nyní podporována souborem stránky.1 Jedná se o relativně nákladnou operaci, protože DLL musí být čtena z disku a opravena, a vznikne poplatek za odevzdání souboru stránky, aby se zajistilo, že existuje prostor pro zápis opravených stránek. Pokud navíc dva procesy přemístí DLL a náhodou je přemístí na stejné místo, Systém Windows NT se nepokouší sdílet přemístěné obrázky. V souboru stránky bude více kopií.

náklady na toto dynamické přemístění se rebasing snaží vyhnout. Říkejme tomu ” přemístění trest.”

zadejte ASLR.

ASLR způsobí načtení dll na pseudonáhodných adresách. V důsledku toho se DLL načte na preferovanou základní adresu pouze v případě úžasné náhody.

dobře, vraťme se tedy k odůvodnění, abychom zjistili, zda stále platí.

způsobuje načtení DLL z preferované základní adresy pokutu za přemístění? Pokud o tom přemýšlíte, ASLR znamená, že se žádná DLL nikdy nenačte na preferovanou adresu, ale také jsme viděli, že jádro k tomu přizpůsobuje, takže DLL vystavené ASLR mohou stále sdílet stránky, a to bez vynucení přemístění celé DLL při počátečním zatížení. Neexistuje tedy žádný trest za přemístění v případě, kdy byla DLL přemístěna ASLR.

ale co když je DLL přemístěna z nějakého jiného důvodu? Může se například stát, že základní adresa zvolená ASLR není v procesu k dispozici, protože proces již na tomto místě přidělil něco jiného. V takovém případě musí proběhnout tradiční přemístění a zaplatíte pokutu za přemístění.

Ah, ale tady je věc: když je načten DLL, ASLR přiřadí základní adresu náhodně z dostupných základních adres, které se již nepoužívají.2 takže se nedostanete do scénáře” základní adresa zvolená ASLR není k dispozici”, protože ASLR si vybere základní adresu DLL ze základní adresy, která je k dispozici.3

dobře, takže se stále můžete dostat do konfliktní situace, ale musíte na tom opravdu pracovat. Můžete například načíst DLL do jednoho procesu a získat základní adresu přiřazenou ASLR. Poté spustíte druhý proces, úmyslně přidělíte paměť na tuto adresu (vynutíte kolizi) a načtete DLL. V takovém případě dojde k přemístění, protože jste dřepěli na místě, kde ASLR chtěl dát DLL. Ale to není o nic horší než to, co jste měli před ASLR: ve světě před ASLR by squatting na preferované základní adrese DLL stejně vynutil trest za přemístění.

takže se podívejme, jaký je příběh. Chcete-li rebase nebo ne rebase?

v přítomnosti ASLR nemá rebasing DLL žádný účinek, protože ASLR stejně ignoruje vaši základní adresu a přemístí DLL do umístění jejího pseudonáhodného výběru.

mějte na paměti, že i když rebasing nemá žádný účinek, ani to neublíží.

pokud jste v systému bez ASLR (buď proto, že předchází ASLR, nebo proto, že ASLR byl z jakéhokoli důvodu deaktivován), pomůže rebasing z tradičních důvodů.

myslete na to, že systémy bez ASLR jsou v dnešní době opravdu těžké najít, takže rebasing neposkytuje v drtivé většině případů žádnou výhodu. Ale v tom mizivě malém procentu případů, kdy nemáte ASLR, pak rebasing pomáhá.

závěr: není na škodu rebase, jen pro případ, ale pochopte, že výplata bude extrémně vzácná. Sestavte si svůj DLL s /DYNAMICBASE povoleno (a s /HIGHENTROPYVA pro dobrou míru) a nechat ASLR dělat práci zajistit, že nedojde ke kolizi základní adresy. To pokryje téměř všechny scénáře v reálném světě. Pokud se náhodou dostanete do jednoho z velmi vzácných případů, kdy ASLR není k dispozici, bude váš program stále fungovat. Kvůli trestu za přemístění to může běžet trochu pomaleji.

1 přesněji, všechny stránky, které obsahovaly opravy, jsou vloženy do souboru stránky. Minule jsme diskutovali o tomto jemnějším bodu.

2 dobře, je tu třetí případ, což je místo, kde ASLR jednoduše vyčerpala základní adresy. Ale opět to není horší než to, co jste měli před ASLR: pokud vám dojdou základní adresy, pak je to každý člověk pro sebe. Pokaždé, když se načte nová DLL, musí jádro hledat dostatečně velký kus dostupného adresního prostoru, do kterého může načíst DLL.

3 výsledkem je, že ASLR ve skutečnosti odvádí lepší práci při vyhýbání se kolizím než při ručním rebasingu, protože ASLR může zobrazit systém jako celek, zatímco ruční rebasing vyžaduje, abyste znali všechny DLL, které jsou načteny do vašeho procesu, a koordinace základních adres napříč více dodavateli obecně není možná.

Raymond Chen

Následovat

Leave a Reply