jak ważne jest w dzisiejszych czasach, aby wszystkie moje biblioteki DLL miały niezakłócone adresy bazowe?

Raymond

20 stycznia, 2017

w dawnych czasach, jedną z rzeczy, do których zachęcano Cię, było rebase bibliotek DLL, aby wszystkie miały zakresy adresów nieoverlapping, unikając w ten sposób kosztów relokacji środowiska wykonawczego. Czy to nadal ważne w dzisiejszych czasach?

ta sytuacja jest kolejnym pokazem tego, jak ważne jest, aby dobra rada była uzasadniona, abyś mógł powiedzieć, kiedy stanie się zła rada.

uzasadnienie rebasingu jest następujące: Jeśli biblioteka DLL jest załadowana pod preferowanym adresem bazowym, wtedy obraz może być wywoływany bezpośrednio z magazynu kopii bez konieczności wprowadzania poprawek. Oznacza to, że strony mogą być współdzielone między procesami, ponieważ każdy proces otrzymuje identyczną kopię. (Oczywiście, udostępnianie kończy się, gdy ktoś pisze na stronie i sprawia, że jego kopia różni się od udostępnionej kopii.)

jeśli nie można załadować biblioteki DLL pod jej preferowanym adresem, obraz zostanie przeniesiony, a cała przeniesiona biblioteka DLL jest teraz wspierana przez plik strony.1 jest to stosunkowo kosztowna operacja, ponieważ DLL musi być odczytany z dysku i naprawiony, a opłata za zatwierdzenie pliku strony jest pobierana w celu zapewnienia miejsca na zapisanie naprawionych stron. Co więcej, jeśli dwa procesy przenoszą bibliotekę DLL i przypadkowo przenoszą je w to samo miejsce, Windows NT nie próbuje udostępniać przeniesionych obrazów. W pliku strony będzie wiele kopii.

koszt tej dynamicznej relokacji jest tym, czego próbuje się uniknąć. Nazwijmy to ” karą relokacji.”

wpisz ASLR.

ASLR powoduje ładowanie bibliotek DLL pod pseudolosowymi adresami. W związku z tym DLL załaduje się pod swoim preferowanym adresem bazowym tylko w przypadku zdumiewającego przypadku.

Ok, więc wróćmy do uzasadnienia, aby zobaczyć, czy nadal ma zastosowanie.

czy ładowanie biblioteki DLL z jej preferowanego adresu bazowego wiąże się z karą relokacji? Jeśli się nad tym zastanowić, ASLR oznacza, że żadna biblioteka DLL nigdy nie ładuje się pod swoim preferowanym adresem, ale widzieliśmy również, że jądro sprawia, że biblioteki DLL poddane ASLR mogą nadal udostępniać strony, i robi to bez zmuszania całej biblioteki DLL do przeniesienia przy początkowym obciążeniu. Tak więc nie ma kary relokacji w przypadku, gdy DLL został przeniesiony przez ASLR.

ale co, jeśli DLL zostanie przeniesiony z innego powodu? Na przykład, może się zdarzyć, że adres bazowy wybrany przez ASLR nie jest dostępny w procesie, ponieważ proces już przydzielił coś innego w tej lokalizacji. W takim przypadku musi nastąpić tradycyjna Relokacja, a ty płacisz karę relokacji.

Ah, ale chodzi o to: po załadowaniu biblioteki DLL, ASLR przydzieli losowo adres bazowy spośród dostępnych adresów bazowych, które nie są jeszcze używane.2 więc nie dostaniesz się do scenariusza “the ASLR-chosen base address is not available”, ponieważ ASLR wybiera adres bazowy DLL spośród dostępnych adresów bazowych.3

Ok, więc nadal można dostać się do sytuacji konfliktowej, ale trzeba naprawdę nad tym popracować. Na przykład, można załadować bibliotekę DLL do jednego procesu i uzyskać adres bazowy przypisany do ASLR. Następnie rozpoczynasz drugi proces, celowo przydzielasz pamięć pod tym adresem (aby wymusić kolizję), a następnie ładujesz bibliotekę DLL. W tym przypadku nastąpi przeniesienie, ponieważ przykucnąłeś na miejsce, w którym ASLR chciał umieścić bibliotekę DLL. Ale to nie jest gorsze niż to, co miałeś przed ASLR: w świecie pre-ASLR, kucanie na preferowanym adresie bazowym biblioteki DLL i tak wymusiłoby karę relokacji.

zobaczmy więc, co to za Historia. Rebase czy nie?

w obecności ASLR, zmiana rozmiaru bibliotek DLL nie ma wpływu, ponieważ ASLR i tak zignoruje Twój adres bazowy i przeniesie bibliotekę DLL w miejsce jej pseudolosowego wyboru.

zauważ, że mimo, że rebasing nie przynosi efektu, to też nie boli.

Jeśli korzystasz z systemu bez ASLR (albo dlatego, że jest on wcześniejszy niż ASLR, albo dlatego, że ASLR został wyłączony z jakiegokolwiek powodu), wtedy rebasing pomoże, z tradycyjnych powodów.

zauważ, że systemy bez ASLR są naprawdę trudne do znalezienia w dzisiejszych czasach, więc rebasing nie przynosi żadnych korzyści w przeważającej większości przypadków. Ale w tym znikającym małym odsetku przypadków, w których nie masz ASLR, wtedy rebasing pomaga.

wniosek: rebase nie zaszkodzi, na wszelki wypadek, ale zrozum, że wypłata będzie niezwykle rzadka. Zbuduj swoją bibliotekę DLL z włączoną /DYNAMICBASE (i z /HIGHENTROPYVA dla dobrej miary) i pozwól ASLR wykonać pracę, aby zapewnić, że nie dojdzie do kolizji adresu bazowego. To obejmie prawie wszystkie rzeczywiste scenariusze. Jeśli zdarzy ci się wpaść w jeden z bardzo rzadkich przypadków, w których ASLR nie jest dostępny, Twój program będzie nadal działać. Po prostu może działać trochę wolniej ze względu na karę relokacji.

1 dokładniej, wszystkie strony zawierające poprawki są umieszczane w pliku strony. Rozmawialiśmy o tym ostatnim razem.

3 w rezultacie, ASLR faktycznie lepiej radzi sobie z unikaniem kolizji niż ręczne zmienianie bazy danych, ponieważ ASLR może przeglądać system jako całość, podczas gdy ręczne zmienianie bazy danych wymaga znajomości wszystkich bibliotek DLL, które są ładowane do procesu, a koordynacja adresów bazowych u wielu dostawców zazwyczaj nie jest możliwa.

Raymond Chen

Obserwuj

Leave a Reply