Biblioteka linków dynamicznych - Dynamic-link library

Biblioteka linków dynamicznych
Dll png.png
Rozszerzenie nazwy pliku
.dll
Rodzaj mediów internetowych
application/vnd.microsoft.portable-executable
Jednolity identyfikator typu (UTI) com.microsoft.windows-dynamic-link-library
magiczny numer MZ
Opracowany przez Microsoft
Pojemnik na Udostępniona biblioteka

Dll ( DLL ) jest Microsoft implementacja jest z udostępnionej biblioteki koncepcji w systemie Microsoft Windows i OS / 2 systemów operacyjnych . Te biblioteki mają zwykle rozszerzenie pliku DLL , OCX(dla bibliotek zawierających formanty ActiveX ) lub DRV(dla starszych sterowników systemowych ). Formaty plików dla bibliotek DLL są takie same jak dla plików Windows EXE — to znaczy Portable Executable (PE) dla 32-bitowego i 64-bitowego systemu Windows oraz New Executable (NE) dla 16-bitowego systemu Windows. Podobnie jak w przypadku plików EXE, biblioteki DLL mogą zawierać kod , dane i zasoby w dowolnej kombinacji.

Pliki danych w tym samym formacie co biblioteka DLL, ale z różnymi rozszerzeniami i prawdopodobnie zawierające tylko sekcje zasobów, mogą być nazywane bibliotekami DLL zasobów . Przykładami takich bibliotek DLL są biblioteki ikon , czasami z rozszerzeniem ICL, oraz pliki czcionek z rozszerzeniami FONi FOT.

Tło

Pierwsze wersje systemu Microsoft Windows uruchamiały programy razem w jednej przestrzeni adresowej . Każdy program miał współpracować, udostępniając procesor innym programom, tak aby graficzny interfejs użytkownika (GUI) mógł wykonywać wiele zadań jednocześnie i był maksymalnie responsywny. Wszystkie operacje na poziomie systemu operacyjnego były dostarczane przez podstawowy system operacyjny: MS-DOS . Wszystkie usługi wyższego poziomu były dostarczane przez biblioteki Windows „Dynamic Link Library”. Rysunku API , urządzenia interfejsu graficznego (GDI) została wprowadzona w DLL zwany GDI.EXEinterfejs użytkownika w USER.EXE. Te dodatkowe warstwy na wierzchu systemu DOS musiały być współużytkowane przez wszystkie uruchomione programy Windows, nie tylko po to, aby umożliwić pracę systemu Windows na maszynie z mniej niż megabajtem pamięci RAM, ale także po to, aby umożliwić współpracę programów ze sobą. Kod w GDI potrzebny do przetłumaczenia poleceń rysowania na operacje na konkretnych urządzeniach. Na wyświetlaczu musiał manipulować pikselami w buforze ramki. Podczas rysowania na drukarkę wywołania interfejsu API musiały zostać przekształcone w żądania do drukarki. Chociaż możliwe było zapewnienie obsługi zakodowanej na sztywno dla ograniczonego zestawu urządzeń (takich jak wyświetlacz Color Graphics Adapter , język poleceń drukarki HP LaserJet ), firma Microsoft wybrała inne podejście. GDI działałoby poprzez ładowanie różnych fragmentów kodu, zwanych „ sterownikami urządzeń ”, do pracy z różnymi urządzeniami wyjściowymi.

Ta sama koncepcja architektoniczna, która umożliwiała GDI ładowanie różnych sterowników urządzeń, pozwalała powłoce systemu Windows na ładowanie różnych programów systemu Windows oraz na wywoływanie przez te programy wywołań API ze współdzielonych bibliotek USER i GDI. Tym pojęciem było „dynamiczne łączenie”.

W konwencjonalnej niewspółdzielonej bibliotece statycznej sekcje kodu są po prostu dodawane do programu wywołującego, gdy jego plik wykonywalny jest budowany w fazie „łączenia”; jeśli dwa programy wywołują tę samą procedurę, procedura jest zawarta w obu programach podczas etapu łączenia tych dwóch. Dzięki dynamicznemu łączeniu udostępniony kod jest umieszczany w pojedynczym, osobnym pliku. Programy wywołujące ten plik są z nim połączone w czasie wykonywania, a system operacyjny (lub, w przypadku wczesnych wersji systemu Windows, rozszerzenie systemu operacyjnego), wykonuje powiązanie.

We wczesnych wersjach systemu Windows (od 1.0 do 3.11) biblioteki DLL stanowiły podstawę całego GUI. W związku z tym sterowniki ekranu były jedynie bibliotekami DLL z rozszerzeniem .DRV, które zapewniały niestandardowe implementacje tego samego interfejsu API rysowania za pośrednictwem ujednoliconego interfejsu sterownika urządzenia (DDI), a interfejsy API rysunku (GDI) i GUI (USER) były jedynie eksportowanymi wywołaniami funkcji przez GDI i USER, systemowe biblioteki DLL z rozszerzeniem .EXE.

Koncepcja budowania systemu operacyjnego z kolekcji dynamicznie ładowanych bibliotek jest podstawową koncepcją systemu Windows, która obowiązuje od 2015 roku. Biblioteki DLL zapewniają standardowe korzyści bibliotek współdzielonych , takie jak modułowość . Modułowość umożliwia wprowadzanie zmian w kodzie i danych w jednej samodzielnej bibliotece DLL współdzielonej przez kilka aplikacji bez żadnych zmian w samych aplikacjach.

Kolejną zaletą modułowości jest użycie ogólnych interfejsów dla wtyczek. Można opracować pojedynczy interfejs, który umożliwia bezproblemową integrację starych i nowych modułów w czasie wykonywania z istniejącymi aplikacjami, bez żadnych modyfikacji samej aplikacji. Ta koncepcja dynamicznej rozszerzalności została doprowadzona do ekstremum w Component Object Model , które jest podstawą ActiveX .

W Windows 1.x, 2.x i 3.x wszystkie aplikacje Windows współdzieliły tę samą przestrzeń adresową, a także tę samą pamięć. Biblioteka DLL została załadowana tylko raz do tej przestrzeni adresowej; odtąd wszystkie programy korzystające z biblioteki miały do ​​niej dostęp. Dane biblioteki były udostępniane we wszystkich programach. Może to być używane jako pośrednia forma komunikacji między procesami lub może przypadkowo uszkodzić różne programy. Wraz z wprowadzeniem 32-bitowych bibliotek w Windows 95 każdy proces działał we własnej przestrzeni adresowej. Chociaż kod DLL może być udostępniany, dane są prywatne, z wyjątkiem sytuacji, w których biblioteka wyraźnie żąda udostępnionych danych. To powiedziawszy, duże połacie systemów Windows 95 , Windows 98 i Windows Me zostały zbudowane z 16-bitowych bibliotek, które ograniczały wydajność mikroprocesora Pentium Pro po uruchomieniu, a ostatecznie ograniczały stabilność i skalowalność wersji systemu Windows opartych na systemie DOS.

Chociaż biblioteki DLL są rdzeniem architektury systemu Windows, mają kilka wad, określanych zbiorczo jako „ DLL piekło ”. Od 2015 r. Microsoft promuje .NET Framework jako jedno rozwiązanie problemów z piekłem DLL, chociaż teraz promują rozwiązania oparte na wirtualizacji, takie jak Microsoft Virtual PC i Microsoft Application Virtualization , ponieważ oferują doskonałą izolację między aplikacjami. Alternatywnym rozwiązaniem łagodzącym skutki piekło DLL było zaimplementowanie zestawu side-by-side .

Cechy

Ponieważ biblioteki DLL są zasadniczo takie same jak pliki EXE, wybór, który należy utworzyć w ramach procesu łączenia, jest dla jasności, ponieważ możliwe jest eksportowanie funkcji i danych z obu.

Nie jest możliwe bezpośrednie wykonanie biblioteki DLL, ponieważ wymaga ona EXE dla systemu operacyjnego, aby załadować ją przez punkt wejścia , stąd istnieją narzędzia takie jak RUNDLL.EXE lub RUNDLL32.EXE, które zapewniają punkt wejścia i minimalną strukturę dla bibliotek DLL które zawierają wystarczającą funkcjonalność do wykonania bez większego wsparcia.

Biblioteki DLL zapewniają mechanizm współdzielonego kodu i danych, umożliwiając deweloperom współdzielonego kodu/danych uaktualnienie funkcji bez konieczności ponownego łączenia lub ponownej kompilacji aplikacji. Z punktu widzenia tworzenia aplikacji Windows i OS/2 można traktować jako zbiór uaktualnianych bibliotek DLL, które umożliwiają aplikacjom dla jednej wersji systemu operacyjnego pracę w nowszej, pod warunkiem, że dostawca systemu operacyjnego zapewnił, że interfejsy i funkcjonalność są kompatybilne.

Biblioteki DLL są wykonywane w przestrzeni pamięci procesu wywołującego iz tymi samymi uprawnieniami dostępu, co oznacza, że ​​ich użycie jest niewielkie, ale także, że nie ma ochrony dla wywołującego EXE, jeśli biblioteka DLL ma jakiś błąd.

Zarządzanie pamięcią

W Windows API pliki DLL są zorganizowane w sekcje . Każda sekcja ma swój własny zestaw atrybutów, takich jak możliwość zapisu lub tylko do odczytu, wykonywalny (dla kodu) lub niewykonywalny (dla danych) i tak dalej.

Kod w bibliotece DLL jest zwykle udostępniany wszystkim procesom korzystającym z biblioteki DLL; oznacza to, że zajmują jedno miejsce w pamięci fizycznej i nie zajmują miejsca w pliku stronicowania . System Windows nie używa kodu niezależnego od pozycji dla swoich bibliotek DLL; zamiast tego kod przechodzi relokację podczas ładowania, naprawiając adresy dla wszystkich jego punktów wejścia w lokalizacjach, które są wolne w przestrzeni pamięci pierwszego procesu do załadowania DLL. W starszych wersjach systemu Windows, w których wszystkie uruchomione procesy zajmowały jedną wspólną przestrzeń adresową, pojedyncza kopia kodu biblioteki DLL byłaby zawsze wystarczająca dla wszystkich procesów. Jednak w nowszych wersjach systemu Windows, które używają oddzielnych przestrzeni adresowych dla każdego programu, możliwe jest użycie tej samej przeniesionej kopii biblioteki DLL w wielu programach, jeśli każdy program ma te same adresy wirtualne, które mogą pomieścić kod biblioteki DLL. Jeśli niektóre programy (lub ich kombinacja już załadowanych bibliotek DLL) nie mają tych adresów wolnych, konieczne będzie utworzenie dodatkowej fizycznej kopii kodu biblioteki DLL przy użyciu innego zestawu przeniesionych punktów wejścia. Jeśli ma zostać odzyskana pamięć fizyczna zajmowana przez sekcję kodu, jej zawartość jest usuwana, a następnie w razie potrzeby ponownie ładowana bezpośrednio z pliku DLL.

W przeciwieństwie do sekcji kodu, sekcje danych biblioteki DLL są zwykle prywatne; oznacza to, że każdy proces korzystający z biblioteki DLL ma własną kopię wszystkich danych biblioteki DLL. Opcjonalnie sekcje danych mogą być współdzielone, umożliwiając komunikację między procesami za pośrednictwem tego obszaru pamięci współdzielonej. Jednakże, ponieważ ograniczenia użytkownika nie dotyczą korzystania ze współdzielonej pamięci DLL, tworzy to lukę w zabezpieczeniach ; mianowicie jeden proces może uszkodzić udostępniane dane, co prawdopodobnie spowoduje niepożądane zachowanie wszystkich innych procesów udostępniania. Na przykład proces działający na koncie gościa może w ten sposób uszkodzić inny proces działający na koncie uprzywilejowanym. Jest to ważny powód, aby unikać używania sekcji współdzielonych w bibliotekach DLL.

Jeśli biblioteka DLL jest skompresowana przez niektóre wykonywalne programy pakujące (np. UPX ), wszystkie jej sekcje kodu są oznaczone jako do odczytu i zapisu i nie będą udostępniane. Sekcje kodu do odczytu i zapisu, podobnie jak sekcje danych prywatnych, są prywatne dla każdego procesu. Dlatego biblioteki DLL ze współdzielonymi sekcjami danych nie powinny być kompresowane, jeśli mają być używane jednocześnie przez wiele programów, ponieważ każda instancja programu musiałaby nosić własną kopię biblioteki DLL, co powodowałoby zwiększone zużycie pamięci.

Importuj biblioteki

Podobnie jak biblioteki statyczne, biblioteki importu dla bibliotek DLL są oznaczone rozszerzeniem pliku .lib. Na przykład kernel32.dll , podstawowa biblioteka dynamiczna dla podstawowych funkcji systemu Windows, takich jak tworzenie plików i zarządzanie pamięcią, jest połączona za pośrednictwem kernel32.lib. Zwykłym sposobem odróżnienia biblioteki importu od właściwej biblioteki statycznej jest rozmiar: biblioteka importu jest znacznie mniejsza, ponieważ zawiera tylko symbole odnoszące się do rzeczywistej biblioteki DLL, która ma być przetworzona w czasie łączenia. Oba są jednak plikami w formacie ar Unix .

Łączenie z bibliotekami dynamicznymi jest zwykle obsługiwane przez łączenie z biblioteką importu podczas budowania lub łączenia w celu utworzenia pliku wykonywalnego. Utworzony plik wykonywalny zawiera następnie tabelę adresów importu (IAT), za pomocą której odwołuje się do wszystkich wywołań funkcji DLL (każda wywołana funkcja DLL zawiera własny wpis w IAT). W czasie wykonywania IAT jest wypełniany odpowiednimi adresami, które wskazują bezpośrednio na funkcję w oddzielnie załadowanej bibliotece DLL.

W Cygwin/MSYS i MinGW, biblioteki importu mają zwykle przyrostek .dll.a, łączący zarówno przyrostek Windows DLL, jak i przyrostek ar uniksowy. Format pliku jest podobny, ale symbole używane do oznaczania importów są różne (_head_foo_dll vs __IMPORT_DESCRIPTOR_foo). Chociaż jego łańcuch narzędzi GNU Binutils może generować biblioteki importu i łączyć się z nimi, szybsze jest bezpośrednie połączenie z biblioteką DLL. Eksperymentalne narzędzie w MinGW o nazwie genlib może być użyte do generowania bibliotek importu z symbolami w stylu MSVC.

Rozdzielczość i wiązanie symboli

Każda funkcja eksportowana przez bibliotekę DLL jest identyfikowana przez liczbę porządkową i opcjonalnie nazwę. Podobnie funkcje można importować z biblioteki DLL według liczby porządkowej lub nazwy. Liczba porządkowa reprezentuje pozycję wskaźnika adresu funkcji w tabeli adresów eksportu DLL. Często zdarza się, że funkcje wewnętrzne są eksportowane tylko według liczby porządkowej. W przypadku większości funkcji Windows API tylko nazwy są zachowywane w różnych wydaniach Windows; liczby porządkowe mogą ulec zmianie. Dlatego nie można niezawodnie importować funkcji Windows API według ich liczb porządkowych.

Importowanie funkcji według liczby porządkowej zapewnia tylko nieco lepszą wydajność niż importowanie ich według nazwy: tabele eksportu bibliotek DLL są uporządkowane według nazwy, więc wyszukiwanie binarne może być użyte do znalezienia funkcji. Indeks znalezionej nazwy jest następnie używany do wyszukiwania liczby porządkowej w tabeli Export Ordinal. W 16-bitowym systemie Windows tablica nazw nie była posortowana, więc narzut wyszukiwania nazw był znacznie bardziej zauważalny.

Możliwe jest również powiązanie pliku wykonywalnego z konkretną wersją biblioteki DLL, czyli rozwiązanie adresów importowanych funkcji w czasie kompilacji. W przypadku importów powiązanych konsolidator zapisuje sygnaturę czasową i sumę kontrolną biblioteki DLL, z którą powiązany jest import. W czasie wykonywania system Windows sprawdza, czy używana jest ta sama wersja biblioteki, a jeśli tak, system Windows pomija przetwarzanie importów. W przeciwnym razie, jeśli biblioteka różni się od tej, z którą była powiązana, system Windows przetwarza importy w normalny sposób.

Powiązane pliki wykonywalne ładują się nieco szybciej, jeśli są uruchamiane w tym samym środowisku, dla którego zostały skompilowane, i dokładnie w tym samym czasie, jeśli są uruchamiane w innym środowisku, więc nie ma wady wiązania importów. Na przykład wszystkie standardowe aplikacje Windows są powiązane z systemowymi bibliotekami DLL ich odpowiednich wersji Windows. Dobrą okazją do powiązania importów aplikacji z jej środowiskiem docelowym jest instalacja aplikacji. Dzięki temu biblioteki są „związane” do następnej aktualizacji systemu operacyjnego. Zmienia jednak sumę kontrolną pliku wykonywalnego, więc nie jest to coś, co można zrobić z podpisanymi programami lub programami zarządzanymi przez narzędzie do zarządzania konfiguracją, które używa sum kontrolnych (takich jak sumy kontrolne MD5 ) do zarządzania wersjami plików. Ponieważ nowsze wersje systemu Windows odeszły od stałych adresów dla każdej załadowanej biblioteki (ze względów bezpieczeństwa), zmniejsza się możliwość i wartość wiązania pliku wykonywalnego.

Jawne łączenie w czasie wykonywania

Pliki DLL mogą być jawnie ładowane w czasie wykonywania, proces zwany po prostu dynamicznym łączeniem w czasie wykonywania przez firmę Microsoft, za pomocą funkcji LoadLibrary(lub LoadLibraryEx) API. Funkcja GetProcAddressAPI służy do wyszukiwania wyeksportowanych symboli według nazwy oraz FreeLibrary– do wyładowania biblioteki DLL. Te funkcje są analogiczne do dlopen, dlsym, oraz dlclosew standardowym API POSIX .

Procedura jawnego łączenia w czasie wykonywania jest taka sama w każdym języku obsługującym wskaźniki do functions , ponieważ zależy od interfejsu API systemu Windows, a nie od konstrukcji językowych.

Opóźnione ładowanie

Zwykle aplikacja, która jest połączona z biblioteką importu biblioteki DLL, nie uruchomi się, jeśli nie można znaleźć biblioteki DLL, ponieważ system Windows nie uruchomi aplikacji, dopóki nie znajdzie wszystkich bibliotek DLL, których może potrzebować aplikacja. Jednak aplikacja może być połączona z biblioteką importu, aby umożliwić opóźnione ładowanie biblioteki dynamicznej. W takim przypadku system operacyjny nie będzie próbował znaleźć ani załadować biblioteki DLL podczas uruchamiania aplikacji; zamiast tego, linker dołącza do aplikacji kod pośredniczący, który spróbuje znaleźć i załadować bibliotekę DLL za pośrednictwem LoadLibrary i GetProcAddress, gdy zostanie wywołana jedna z jego funkcji. Jeśli nie można znaleźć lub załadować biblioteki DLL lub wywoływana funkcja nie istnieje, aplikacja wygeneruje wyjątek , który może zostać odpowiednio przechwycony i obsłużony. Jeśli aplikacja nie obsługuje wyjątku, zostanie on przechwycony przez system operacyjny, który zakończy działanie programu z komunikatem o błędzie.

Mechanizm ładowania opóźnionego zapewnia również zaczepy powiadomień , dzięki czemu aplikacja może wykonać dodatkowe przetwarzanie lub obsługę błędów, gdy biblioteka DLL jest ładowana i/lub wywoływana jest dowolna funkcja DLL.

Zagadnienia dotyczące kompilatora i języka

Delphi

W pliku źródłowym słowo kluczowe libraryjest używane zamiast program. Na końcu pliku funkcje do wyeksportowania są wymienione w exportsklauzuli.

Delphi nie potrzebuje LIBplików do importowania funkcji z bibliotek DLL; aby połączyć się z biblioteką DLL, externalsłowo kluczowe jest używane w deklaracji funkcji, aby zasygnalizować nazwę biblioteki DLL, a następnie namenazwać symbol (jeśli jest inny) lub indexzidentyfikować indeks.

Microsoft Visual Basic

W Visual Basic (VB) obsługiwane jest tylko łączenie w czasie wykonywania; ale oprócz korzystania LoadLibraryi GetProcAddressfunkcji API, deklaracje funkcji importowanych są dozwolone.

Podczas importowania funkcji DLL za pomocą deklaracji, VB wygeneruje błąd w czasie wykonywania, jeśli DLLnie można znaleźć pliku. Deweloper może wykryć błąd i odpowiednio go obsłużyć.

Podczas tworzenia bibliotek DLL w VB, IDE zezwala tylko na tworzenie bibliotek DLL ActiveX, jednak metody zostały stworzone, aby umożliwić użytkownikowi wyraźne poinformowanie konsolidatora, aby dołączył plik .DEF, który definiuje pozycję porządkową i nazwę każdej eksportowanej funkcji. Pozwala to użytkownikowi na utworzenie standardowej biblioteki DLL systemu Windows przy użyciu Visual Basic (wersja 6 lub niższa), do której można się odwoływać za pomocą instrukcji „Declare”.

C i C++

Microsoft Visual C++ (MSVC) udostępnia kilka rozszerzeń standardowego C++, które umożliwiają określanie funkcji jako importowanych lub eksportowanych bezpośrednio w kodzie C++; zostały one zaadoptowane przez inne kompilatory Windows C i C++, w tym wersje GCC dla Windows . Te rozszerzenia używają atrybutu __declspecprzed deklaracją funkcji. Zauważ, że kiedy funkcje C są dostępne z C++, muszą być również zadeklarowane jak extern "C"w kodzie C++, aby poinformować kompilator, że należy użyć powiązania C.

Oprócz określania importowanych lub eksportowanych funkcji za pomocą __declspecatrybutów, mogą one być wymienione w sekcji IMPORT lub EKSPORT DEFpliku używanego przez projekt. DEFPlik jest przetwarzany przez łącznik, zamiast kompilatora, a zatem nie jest specyficzne dla C ++.

Kompilacja DLL wygeneruje zarówno pliki DLLi LIB. LIBPlik (biblioteka import) służy do połączenia z DLL w czasie kompilacji; nie jest to konieczne do łączenia w czasie wykonywania. O ile biblioteka DLL nie jest serwerem Component Object Model (COM), DLLplik musi być umieszczony w jednym z katalogów wymienionych w zmiennej środowiskowej PATH, w domyślnym katalogu systemowym lub w tym samym katalogu, co program, który go używa. Biblioteki DLL serwera COM są rejestrowane przy użyciu programu regsvr32.exe, który umieszcza w rejestrze lokalizację biblioteki DLL i jej unikatowy identyfikator globalny ( GUID ). Programy mogą następnie użyć biblioteki DLL, wyszukując jej identyfikator GUID w rejestrze, aby znaleźć jego lokalizację lub utworzyć instancję obiektu COM pośrednio przy użyciu jego identyfikatora klasy i identyfikatora interfejsu.

Przykłady programowania

Korzystanie z importów DLL

Poniższe przykłady pokazują, jak używać powiązań specyficznych dla języka do importowania symboli do łączenia z biblioteką DLL w czasie kompilacji.

Delphi

{$APPTYPE CONSOLE}

program Example;

// import function that adds two numbers
function AddNumbers(a, b : Double): Double; StdCall; external 'Example.dll';

// main program
var
   R: Double;

begin
  R := AddNumbers(1, 2);
  Writeln('The result was: ', R);
end.

C

Plik Example.lib musi być dołączony (przy założeniu, że jest generowany plik Example.dll) w projekcie (opcja Dodaj istniejący element dla projektu!) przed połączeniem statycznym. Plik Example.lib jest automatycznie generowany przez kompilator podczas kompilowania biblioteki DLL. Niewykonanie powyższej instrukcji spowodowałoby błąd linkowania, ponieważ linker nie wiedziałby, gdzie znaleźć definicję AddNumbers. Może być również konieczne skopiowanie biblioteki DLL Example.dll do lokalizacji, w której plik .exe zostanie wygenerowany przez następujący kod.

#include <windows.h>
#include <stdio.h>

// Import function that adds two numbers
extern "C" __declspec(dllimport) double AddNumbers(double a, double b);

int main(int argc, char *argv[])
{
    double result = AddNumbers(1, 2);
    printf("The result was: %f\n", result);
    return 0;
}

Korzystanie z jawnego łączenia w czasie wykonywania

Poniższe przykłady pokazują, jak używać funkcji ładowania i łączenia w czasie wykonywania przy użyciu powiązań interfejsu API systemu Windows specyficznych dla języka.

Należy zauważyć, że wszystkie cztery próbki są podatne na ataki polegające na wstępnym ładowaniu biblioteki DLL , ponieważ plik example.dll może zostać przeniesiony do miejsca niezamierzonego przez autora (bieżący katalog roboczy poprzedza lokalizację biblioteki systemowej), a tym samym do złośliwej wersji biblioteki. Zobacz odniesienie do wskazówek firmy Microsoft dotyczących bezpiecznego ładowania bibliotek: należy użyć SetDllDirectoryWin, kernel32aby usunąć wyszukiwanie bieżącego katalogu przed załadowaniem jakichkolwiek bibliotek.

Microsoft Visual Basic

Option Explicit
Declare Function AddNumbers Lib "Example.dll" _
(ByVal a As Double, ByVal b As Double) As Double

Sub Main()
	Dim Result As Double
	Result = AddNumbers(1, 2)
	Debug.Print "The result was: " & Result
End Sub

Delphi

program Example;
  {$APPTYPE CONSOLE}
  uses Windows;
  var
  AddNumbers:function (a, b: integer): Double; StdCall;
  LibHandle:HMODULE;
begin
  LibHandle := LoadLibrary('example.dll');
  if LibHandle <> 0 then
    AddNumbers := GetProcAddress(LibHandle, 'AddNumbers');
  if Assigned(AddNumbers) then
    Writeln( '1 + 2 = ', AddNumbers( 1, 2 ) );
  Readln;
end.

C

#include <windows.h>
#include <stdio.h>

// DLL function signature
typedef double (*importFunction)(double, double);

int main(int argc, char **argv)
{
	importFunction addNumbers;
	double result;
	HINSTANCE hinstLib;

	// Load DLL file
	hinstLib = LoadLibrary(TEXT("Example.dll"));
	if (hinstLib == NULL) {
		printf("ERROR: unable to load DLL\n");
		return 1;
	}

	// Get function pointer
	addNumbers = (importFunction) GetProcAddress(hinstLib, "AddNumbers");
	if (addNumbers == NULL) {
		printf("ERROR: unable to find DLL function\n");
		FreeLibrary(hinstLib);
		return 1;
	}

	// Call function.
	result = addNumbers(1, 3);

	// Unload DLL file
	FreeLibrary(hinstLib);

	// Display result
	printf("The result was: %f\n", result);

	return 0;
}

Pyton

Wiązanie ctypes Pythona będzie używać POSIX API w systemach POSIX.

import ctypes

my_dll = ctypes.cdll.LoadLibrary("Example.dll")

# The following "restype" method specification is needed to make
# Python understand what type is returned by the function.
my_dll.AddNumbers.restype = ctypes.c_double

p = my_dll.AddNumbers(ctypes.c_double(1.0), ctypes.c_double(2.0))

print("The result was:", p)

Komponentowy model obiektowy

Component Object Model (COM) definiuje binarnego standardu gościć realizację obiektów w plikach DLL i EXE. Zapewnia mechanizmy lokalizowania i wersjonowania tych plików, a także niezależny od języka i czytelny dla komputera opis interfejsu. Hostowanie obiektów COM w bibliotece DLL jest bardziej uproszczone i umożliwia udostępnianie zasobów procesowi klienta. Dzięki temu obiekty COM mogą zaimplementować zaawansowane zaplecza do prostych interfejsów GUI, takich jak Visual Basic i ASP. Można je również programować z języków skryptowych.

Przejęcie DLL

Ze względu na lukę powszechnie znaną jako przejmowanie bibliotek DLL, spoofing, wstępne ładowanie bibliotek DLL lub umieszczanie plików binarnych, wiele programów ładuje i uruchamia złośliwą bibliotekę DLL zawartą w tym samym folderze, co plik danych otwierany przez te programy. Luka została odkryta przez Georgi Guninskiego w 2000 roku. W sierpniu 2010 roku zyskała światowy rozgłos po ponownym wykryciu jej przez ACROS Security i wykryciu wielu setek programów podatnych na ataki. Programy uruchamiane z niebezpiecznych lokalizacji, tj. folderów z możliwością zapisu przez użytkownika, takich jak Downloads lub katalog Temp , są prawie zawsze podatne na tę lukę.

Zobacz też

Bibliografia

  • Hart, Johnson. Programowanie systemu Windows trzecie wydanie . Addison-Wesley, 2005. ISBN  0-321-25619-0 .
  • Rektor, Brent i in. Programowanie Win32 . Addison-Wesley Developers Press, 1997. ISBN  0-201-63492-9 .

Zewnętrzne linki