Eine Dynamic-Link Library ( DLL ) ist eine gemeinsam genutzte Bibliothek im Microsoft Windows- oder OS/2 -Betriebssystem . Eine DLL kann ausführbaren Code (Funktionen), Daten und Ressourcen enthalten .

DLL-Dateien besitzen oft eine Dateiendung,.dll auch wenn diese nicht zwingend erforderlich ist. Die Dateiendung wird mitunter verwendet, um den Inhalt der Datei zu beschreiben. Beispielsweise .ocxist .dll eine gängige Endung für ActiveX- Steuerelemente und .drvältere (16-Bit-) Gerätetreiber .

Eine DLL, die ausschließlich Ressourcen enthält, wird als Ressourcen-DLL bezeichnet . Beispiele hierfür sind eine Symbolbibliothek mit der gängigen Dateiendung .icon .iclund eine Schriftartenbibliothek mit den gängigen Dateiendungen .font .fonund .font .fot. [ 1 ]

Das Dateiformat einer DLL-Datei ist identisch mit dem einer ausführbaren Datei ( EXE ). Der Hauptunterschied zwischen einer DLL- und einer EXE-Datei besteht darin, dass eine DLL nicht direkt ausgeführt werden kann, da das Betriebssystem einen Einstiegspunkt benötigt . Windows stellt hierfür ein Hilfsprogramm ( rundll.exe/ rundll32.exe) bereit, um eine von einer DLL bereitgestellte Funktion auszuführen. Da sie das gleiche Format haben, kann eine EXE-Datei prinzipiell wie eine DLL verwendet werden. Der aufrufende Code kann eine EXE-Datei über denselben Mechanismus laden wie eine DLL-Datei.

Hintergrund

Die ersten Versionen von Microsoft Windows führten Programme gemeinsam in einem einzigen Adressraum aus . Jedes Programm sollte durch die gemeinsame Nutzung der CPU durch andere Programme kooperieren, damit die grafische Benutzeroberfläche (GUI) Multitasking betreiben und maximal reaktionsschnell sein konnte. Alle Operationen auf Betriebssystemebene wurden vom zugrundeliegenden Betriebssystem MS-DOS bereitgestellt . Alle Dienste höherer Ebene wurden von der Windows-Bibliothek „Dynamic Link Library“ (DLL) bereitgestellt. Die Zeichen- API , die Graphics Device Interface (GDI), war in einer DLL namens „GDI“ implementiert GDI.EXE, die Benutzeroberfläche in USER.EXE„GDI“. Diese zusätzlichen Schichten über DOS mussten von allen laufenden Windows-Programmen gemeinsam genutzt werden, nicht nur um Windows auf Rechnern mit weniger als einem Megabyte RAM lauffähig zu machen, sondern auch um die Zusammenarbeit der Programme untereinander zu ermöglichen. Der Code in GDI musste Zeichenbefehle in Operationen auf bestimmten Geräten übersetzen. Auf dem Bildschirm musste er Pixel im Framebuffer manipulieren. Beim Drucken mussten die API-Aufrufe in Anfragen an den Drucker umgewandelt werden. Obwohl es möglich gewesen wäre, die Unterstützung für eine begrenzte Anzahl von Geräten (wie den Color Graphics Adapter -Bildschirm oder die HP LaserJet Printer Command Language ) fest zu programmieren , wählte Microsoft einen anderen Ansatz. GDI funktioniert, indem verschiedene Codeabschnitte, sogenannte „ Gerätetreiber “, geladen werden, um mit unterschiedlichen Ausgabegeräten zu arbeiten.

Dasselbe Architekturkonzept, das es GDI ermöglichte, verschiedene Gerätetreiber zu laden, erlaubte es auch der Windows-Shell , verschiedene Windows-Programme zu laden und dass diese Programme API-Aufrufe aus den gemeinsam genutzten USER- und GDI-Bibliotheken aufrufen konnten. Dieses Konzept nannte man „dynamische Verknüpfung“.

In einer herkömmlichen statischen Bibliothek werden Codeabschnitte beim Erstellen der ausführbaren Datei im Linker-Prozess einfach dem aufrufenden Programm hinzugefügt. Rufen zwei Programme dieselbe Routine auf, wird diese beim Linken in beide Programme eingebunden. Beim dynamischen Linken hingegen wird gemeinsam genutzter Code in einer separaten Datei gespeichert. Die Programme, die diese Datei aufrufen, werden zur Laufzeit vom Betriebssystem (bzw. bei älteren Windows-Versionen von der Betriebssystemerweiterung) mit ihr verknüpft.

In den frühen Windows-Versionen (1.0 bis 3.11) bildeten die DLLs die Grundlage für die gesamte grafische Benutzeroberfläche. Grafiktreiber waren daher lediglich DLLs mit der Dateiendung .DRV, die über eine einheitliche Gerätetreiberschnittstelle (DDI) benutzerdefinierte Implementierungen derselben Zeichen-API bereitstellten. Die Zeichen-API (GDI) und die GUI-API (USER) waren im Grunde nur die Funktionsaufrufe, die von den GDI- und USER-System-DLLs mit der Dateiendung .EXE exportiert wurden.

Das Konzept, das Betriebssystem aus einer Sammlung dynamisch geladener Bibliotheken aufzubauen, ist ein Kernprinzip von Windows, das auch 2015 noch Gültigkeit hatte. DLLs bieten die üblichen Vorteile gemeinsam genutzter Bibliotheken , wie beispielsweise Modularität . Dank Modularität können Code und Daten in einer einzigen, in sich geschlossenen DLL geändert werden, die von mehreren Anwendungen gemeinsam genutzt wird, ohne dass die Anwendungen selbst angepasst werden müssen.

Ein weiterer Vorteil der Modularität ist die Verwendung generischer Schnittstellen für Plug-ins. Es kann eine einzige Schnittstelle entwickelt werden, die es ermöglicht, sowohl alte als auch neue Module zur Laufzeit nahtlos in bestehende Anwendungen zu integrieren, ohne dass die Anwendung selbst verändert werden muss. Dieses Konzept der dynamischen Erweiterbarkeit wird im Component Object Model (COM) , dem Fundament von ActiveX , auf die Spitze getrieben .

In Windows 1.x, 2.x und 3.x teilten sich alle Windows-Anwendungen denselben Adressraum und Speicher. Eine DLL wurde nur einmal in diesen Adressraum geladen; anschließend griffen alle Programme, die die Bibliothek nutzten, darauf zu. Die Daten der Bibliothek wurden von allen Programmen gemeinsam genutzt. Dies konnte als indirekte Form der Interprozesskommunikation dienen , aber auch versehentlich die verschiedenen Programme beschädigen. Mit der Einführung von 32-Bit -Bibliotheken in Windows 95 lief jeder Prozess in seinem eigenen Adressraum. Obwohl der DLL-Code gemeinsam genutzt werden kann, sind die Daten privat, außer wenn die Bibliothek explizit auf gemeinsam genutzte Daten zugreift. Allerdings basierten große Teile von Windows 95, Windows 98 und Windows Me auf 16-Bit-Bibliotheken, was die Leistung des Pentium Pro- Mikroprozessors beim Start einschränkte und letztendlich die Stabilität und Skalierbarkeit der DOS-basierten Windows-Versionen beeinträchtigte.

Einschränkungen

Obwohl die DLL-Technologie ein Kernbestandteil der Windows-Architektur ist, weist sie auch Nachteile auf.

DLL-Hölle

DLL-Hölle beschreibt das fehlerhafte Verhalten einer Anwendung, wenn die falsche Version einer DLL verwendet wird. [ 2 ] Zu den Gegenmaßnahmen gehören:

Gemeinsamer Speicherbereich

Der ausführbare Code einer DLL läuft im Speicherbereich des aufrufenden Prozesses und mit denselben Zugriffsrechten, was bedeutet, dass bei ihrer Verwendung nur ein geringer Mehraufwand entsteht, aber auch, dass das aufrufende Programm nicht geschützt ist, falls die DLL irgendeinen Fehler aufweist.

Merkmale

Ausbaufähigkeit

Die DLL-Technologie ermöglicht es, eine Anwendung zu modifizieren, ohne dass die verwendeten Komponenten neu kompiliert oder verknüpft werden müssen. Eine DLL kann ersetzt werden, sodass die Anwendung beim nächsten Start die neue DLL-Version verwendet. Damit die DLL-Änderungen korrekt funktionieren, muss die Abwärtskompatibilität gewährleistet sein .

Sogar das Betriebssystem lässt sich aktualisieren, da es den Anwendungen über DLLs zugänglich gemacht wird. System-DLLs können ersetzt werden, sodass die Anwendungen beim nächsten Start die neuen System-DLLs verwenden.

Speicherverwaltung

In der Windows-API sind DLL-Dateien in Abschnitte unterteilt . Jeder Abschnitt verfügt über eigene Attribute, z. B. ob er beschreibbar oder schreibgeschützt, ausführbar (für Code) oder nicht ausführbar (für Daten) ist usw.

Der Code einer DLL wird üblicherweise von allen Prozessen, die die DLL verwenden, gemeinsam genutzt. Das heißt, er belegt einen einzigen Speicherplatz im physischen Speicher und wird nicht in der Auslagerungsdatei gespeichert . Windows verwendet für seine DLLs keinen positionsunabhängigen Code . Stattdessen wird der Code beim Laden verschoben , wodurch die Adressen aller Einstiegspunkte an freien Speicheradressen des ersten Prozesses, der die DLL lädt, festgelegt werden. In älteren Windows-Versionen, in denen alle laufenden Prozesse einen gemeinsamen Adressraum nutzten, reichte eine einzige Kopie des DLL-Codes für alle Prozesse aus. In neueren Windows-Versionen, die für jedes Programm einen separaten Adressraum verwenden, kann dieselbe verschobene Kopie der DLL nur dann in mehreren Programmen verwendet werden, wenn jedes Programm über dieselben freien virtuellen Adressen für den DLL-Code verfügt. Falls einige Programme (oder deren Kombination bereits geladener DLLs) diese Adressen nicht frei haben, muss eine zusätzliche physische Kopie des DLL-Codes mit einem anderen Satz verschobener Einstiegspunkte erstellt werden. Soll der von einem Codeabschnitt belegte physische Speicher freigegeben werden, werden dessen Inhalte verworfen und bei Bedarf später direkt aus der DLL-Datei neu geladen.

Im Gegensatz zu den Codeabschnitten sind die Datenabschnitte einer DLL üblicherweise privat; das heißt, jeder Prozess, der die DLL verwendet, besitzt eine eigene Kopie aller DLL-Daten. Optional können Datenabschnitte gemeinsam genutzt werden, wodurch die Kommunikation zwischen Prozessen über diesen gemeinsamen Speicherbereich ermöglicht wird. Da jedoch für die Nutzung des gemeinsam genutzten DLL-Speichers keine Benutzerbeschränkungen gelten, entsteht dadurch eine Sicherheitslücke : Ein Prozess kann die gemeinsam genutzten Daten beschädigen, was wahrscheinlich dazu führt, dass sich alle anderen Prozesse, die diese Daten gemeinsam nutzen, unerwünschtes Verhalten zeigen. Beispielsweise kann ein Prozess, der unter einem Gastkonto ausgeführt wird, auf diese Weise einen anderen Prozess beschädigen, der unter einem privilegierten Konto ausgeführt wird. Dies ist ein wichtiger Grund, die Verwendung gemeinsam genutzter Abschnitte in DLLs zu vermeiden.

Wird eine DLL mit bestimmten ausführbaren Packern (z. B. UPX ) komprimiert , werden alle ihre Codeabschnitte als les- und schreibbar markiert und nicht gemeinsam genutzt. Lese- und schreibbare Codeabschnitte sind, ähnlich wie private Datenabschnitte, für jeden Prozess privat. Daher sollten DLLs mit gemeinsam genutzten Datenabschnitten nicht komprimiert werden, wenn sie von mehreren Programmen gleichzeitig verwendet werden sollen, da jede Programminstanz eine eigene Kopie der DLL mitführen müsste, was zu einem erhöhten Speicherverbrauch führen würde.

Bibliotheken importieren

Wie statische Bibliotheken werden auch Importbibliotheken für DLLs durch ihre .libDateiendung gekennzeichnet. Beispielsweise kernel32.dllwird die primäre dynamische Bibliothek für Windows-Basisfunktionen wie Dateierstellung und Speicherverwaltung über die Dateiendung .dll verlinkt kernel32.lib. Üblicherweise unterscheidet man eine Importbibliothek von einer statischen Bibliothek anhand ihrer Größe: Die Importbibliothek ist deutlich kleiner, da sie nur Symbole enthält, die auf die eigentliche DLL verweisen und erst zur Linkzeit verarbeitet werden. Beide sind jedoch Dateien im Unix -AR- Format.

Die Einbindung dynamischer Bibliotheken erfolgt üblicherweise durch Importieren einer Bibliothek beim Kompilieren oder beim Linken zur Erstellung einer ausführbaren Datei. Die erstellte ausführbare Datei enthält dann eine Importadresstabelle (IAT), über die alle DLL-Funktionsaufrufe referenziert werden (jede referenzierte DLL-Funktion hat einen eigenen Eintrag in der IAT). Zur Laufzeit wird die IAT mit den entsprechenden Adressen gefüllt, die direkt auf eine Funktion in der separat geladenen DLL verweisen. [ 3 ]

In Cygwin/MSYS und MinGW erhalten Importbibliotheken üblicherweise die Endung `.dll` .dll.a, eine Kombination aus der Windows-DLL-Endung und der Unix-AR-Endung. Das Dateiformat ist ähnlich, die Symbole zur Kennzeichnung der Importe unterscheiden sich jedoch (` _head_foo_dll.dll` vs. `ar` __IMPORT_DESCRIPTOR_foo). [ 4 ] Obwohl die GNU Binutils- Toolchain Importbibliotheken generieren und verlinken kann, ist das direkte Verlinken der DLL schneller. [ 5 ] Mit dem experimentellen Tool `genlib` in MinGW lassen sich Importbibliotheken mit MSVC-ähnlichen Symbolen erzeugen.

Symbolauflösung und Bindung

Jede von einer DLL exportierte Funktion wird durch eine numerische Kennung und optional einen Namen identifiziert. Funktionen können aus einer DLL entweder über die Kennung oder über ihren Namen importiert werden. Die Kennung repräsentiert die Position des Adresszeigers der Funktion in der Exportadresstabelle der DLL. Interne Funktionen werden üblicherweise nur über die Kennung exportiert. Bei den meisten Windows-API-Funktionen bleiben jedoch nur die Namen über verschiedene Windows-Versionen hinweg erhalten; die Kennungen können sich ändern. Daher ist es nicht möglich, Windows-API-Funktionen zuverlässig über ihre Kennungen zu importieren.

Das Importieren von Funktionen über ihre Ordinalzahl bietet nur eine geringfügig bessere Performance als das Importieren über ihren Namen: Die Exporttabellen von DLLs sind nach Namen sortiert, sodass eine binäre Suche zum Auffinden einer Funktion verwendet werden kann. Der Index des gefundenen Namens wird dann verwendet, um die Ordinalzahl in der Export-Ordinaltabelle nachzuschlagen. Unter 16-Bit-Windows war die Namenstabelle nicht sortiert, wodurch der Overhead der Namenssuche deutlich spürbarer war.

Es ist auch möglich, eine ausführbare Datei an eine bestimmte Version einer DLL zu binden , d. h. die Adressen importierter Funktionen zur Kompilierzeit aufzulösen. Bei gebundenen Importen speichert der Linker den Zeitstempel und die Prüfsumme der DLL, an die der Import gebunden ist. Zur Laufzeit prüft Windows, ob dieselbe Bibliotheksversion verwendet wird. Ist dies der Fall, überspringt Windows die Verarbeitung der Importe. Andernfalls, wenn die Bibliothek von der gebundenen Version abweicht, verarbeitet Windows die Importe normal.

Gebundene ausführbare Dateien laden etwas schneller, wenn sie in derselben Umgebung ausgeführt werden, für die sie kompiliert wurden, und exakt gleich schnell, wenn sie in einer anderen Umgebung ausgeführt werden. Daher ergeben sich keine Nachteile durch das Binden der Importe. Beispielsweise sind alle Standard-Windows-Anwendungen an die System-DLLs ihrer jeweiligen Windows-Version gebunden. Eine gute Gelegenheit, die Importe einer Anwendung an ihre Zielumgebung zu binden, bietet sich während der Installation der Anwendung. Dadurch bleiben die Bibliotheken bis zum nächsten Betriebssystem-Update „gebunden“. Dies ändert jedoch die Prüfsumme der ausführbaren Datei. Daher ist dies nicht möglich bei signierten Programmen oder Programmen, die von einem Konfigurationsverwaltungstool verwaltet werden, das Prüfsummen (wie MD5 -Prüfsummen) zur Versionsverwaltung verwendet. Da neuere Windows-Versionen (aus Sicherheitsgründen) keine festen Adressen mehr für jede geladene Bibliothek verwenden, nimmt die Möglichkeit und der Nutzen des Bindens einer ausführbaren Datei ab.

Explizite Laufzeitverknüpfung

DLL-Dateien können zur Laufzeit explizit geladen werden – ein Vorgang, der von Microsoft als dynamisches Linken zur Laufzeit bezeichnet wird – mithilfe der API-Funktion ` LoadLibraryload()` (oder `load( LoadLibraryEx)`). Die GetProcAddressAPI-Funktion `load()` dient zum Auffinden exportierter Symbole anhand ihres Namens, und FreeLibrary`load()` zum Entladen der DLL. Diese Funktionen sind analog zu `load()` dlopen, ` dlsymload()` und ` load dlclose()` in der POSIX- Standard-API.

Das Verfahren für die explizite Laufzeitverknüpfung ist in jeder Sprache, die Zeiger auf Funktionen unterstützt , gleich, da es von der Windows-API und nicht von Sprachkonstrukten abhängt.

Verzögertes Laden

Normalerweise startet eine Anwendung, die mit der Importbibliothek einer DLL verknüpft ist, nicht, wenn die DLL nicht gefunden wird. Windows führt die Anwendung nämlich nur aus, wenn alle benötigten DLLs gefunden wurden. Eine Anwendung kann jedoch mit einer Importbibliothek verknüpft werden, um das verzögerte Laden der dynamischen Bibliothek zu ermöglichen. [ 6 ] In diesem Fall versucht das Betriebssystem nicht, die DLL beim Start der Anwendung zu finden oder zu laden. Stattdessen bindet der Linker einen Stub in die Anwendung ein, der versucht, die DLL zu finden und zu laden, LoadLibrarysobald GetProcAddresseine seiner Funktionen aufgerufen wird. Kann die DLL nicht gefunden oder geladen werden oder existiert die aufgerufene Funktion nicht, erzeugt die Anwendung eine Ausnahme , die abgefangen und entsprechend behandelt werden kann. Behandelt die Anwendung die Ausnahme nicht, wird sie vom Betriebssystem abgefangen, welches das Programm mit einer Fehlermeldung beendet.

Der Mechanismus für verzögertes Laden bietet außerdem Benachrichtigungs- Hooks , die es der Anwendung ermöglichen, zusätzliche Verarbeitungsschritte oder Fehlerbehandlungen durchzuführen , wenn die DLL geladen wird und/oder eine DLL-Funktion aufgerufen wird.

Compiler- und Sprachüberlegungen

Delphi

In einer Quelldatei librarywird das Schlüsselwort anstelle von verwendet program. Am Ende der Datei werden die zu exportierenden Funktionen in exportsder Klausel aufgelistet.

Delphi benötigt keine LIBDateien, um Funktionen aus DLLs zu importieren; um eine Verknüpfung mit einer DLL herzustellen, externalwird das Schlüsselwort in der Funktionsdeklaration verwendet, um den Namen der DLL anzugeben, gefolgt von nameeinem Namen für das Symbol (falls abweichend) oder indexeinem Index.

Microsoft Visual Basic

In Visual Basic (VB) wird nur die Laufzeitverknüpfung unterstützt; zusätzlich zur Verwendung LoadLibraryvon GetProcAddressAPI-Funktionen sind aber auch Deklarationen importierter Funktionen zulässig.

Beim Importieren von DLL-Funktionen über Deklarationen erzeugt VB einen Laufzeitfehler, falls die DLLDatei nicht gefunden wird. Der Entwickler kann diesen Fehler abfangen und entsprechend behandeln.

Beim Erstellen von DLLs in VB erlaubt die IDE standardmäßig nur die Erstellung von ActiveX-DLLs. Es wurden jedoch Methoden entwickelt [ 7 ] , mit denen der Benutzer dem Linker explizit mitteilen kann, eine .DEF-Datei einzubinden, die die Position und den Namen jeder exportierten Funktion definiert. Dadurch kann der Benutzer mit Visual Basic (Version 6 oder niedriger) eine Standard-Windows-DLL erstellen, auf die über eine „Declare“-Anweisung verwiesen werden kann.

C und C++

Microsoft Visual C++ (MSVC) bietet mehrere Erweiterungen für Standard -C++ , die es ermöglichen, Funktionen direkt im C++-Code als importiert oder exportiert anzugeben. Diese Erweiterungen wurden von anderen Windows- C- und C++-Compilern, einschließlich der Windows-Versionen von GCC , übernommen . Sie verwenden das Attribut `import` __declspecvor der Funktionsdeklaration. Beachten Sie, dass beim Zugriff auf C-Funktionen aus C++ diese ebenfalls extern "C"im C++-Code als `import` oder `export` deklariert werden müssen, um dem Compiler mitzuteilen, dass die C-Bindung verwendet werden soll. [ 8 ]

Neben der Angabe importierter oder exportierter Funktionen mithilfe von __declspecAttributen können diese auch im Abschnitt IMPORT oder EXPORTS der .defvom Projekt verwendeten Datei aufgeführt werden. Die .defDatei wird vom Linker und nicht vom Compiler verarbeitet und ist daher nicht C++-spezifisch.

Die DLL-Kompilierung erzeugt sowohl eine DLLals auch LIBeine Importbibliothek. Die LIBImportbibliothek wird zur Verknüpfung mit einer DLL zur Kompilierzeit verwendet; sie ist für die Verknüpfung zur Laufzeit nicht erforderlich. Sofern es sich bei der DLL nicht um einen COM-Server ( Component Object Model ) handelt, muss die DLLImportbibliothek in einem der in der Umgebungsvariablen PATH aufgeführten Verzeichnisse, im Standard-Systemverzeichnis oder im selben Verzeichnis wie das Programm, das sie verwendet, abgelegt werden. COM-Server-DLLs werden mit `registry.com` registriert regsvr32.exe, wodurch der Speicherort der DLL und ihre global eindeutige ID ( GUID ) in der Registrierung gespeichert werden. Programme können die DLL dann verwenden, indem sie ihre GUID in der Registrierung nachschlagen , um ihren Speicherort zu finden, oder indirekt eine Instanz des COM-Objekts mithilfe seiner Klassen- und Schnittstellenkennung erstellen.

Programmierbeispiele

Verwendung von DLL-Importen

Die folgenden Beispiele zeigen, wie man sprachspezifische Bindungen verwendet, um Symbole zum Verknüpfen mit einer DLL zur Kompilierzeit zu importieren.

Delphi

{$APPTYPE CONSOLE}Programmbeispiel ;​// Importfunktion zum Addieren zweier Zahlen function AddNumbers ( a , b : Double ) : Double ; StdCall ; external 'Example.dll' ;// Hauptprogramm var R : Double ;begin R := AddNumbers ( 1 , 2 ) ; Writeln ( 'Das Ergebnis war: ' , R ) ; end .

C

Die Datei Example.lib muss (vorausgesetzt, Example.dll wird generiert) vor dem statischen Linken in das Projekt eingebunden werden. Die Datei Example.lib wird beim Kompilieren der DLL automatisch vom Compiler erzeugt. Wird die obige Anweisung nicht ausgeführt, führt dies zu einem Linkerfehler, da der Linker die Definition nicht finden kann . Die DLL-Datei Example.dll muss möglicherweise auch in das Verzeichnis kopiert werden, in dem die ausführbare Datei durch den folgenden Code generiert wird: AddNumbers

#include <stdio.h> #include <windows.h>// Importfunktion, die zwei Zahlen addiert extern "C" __declspec ( dllimport ) double AddNumbers ( double a , double b );int main ( int argc , char * argv []) { double result = AddNumbers ( 1 , 2 ); printf ( "Das Ergebnis war: %f \n " , result ); return 0 ; }

Verwendung expliziter Laufzeitverknüpfung

Die folgenden Beispiele zeigen, wie die Laufzeit-Lade- und Verknüpfungsfunktionen mithilfe sprachspezifischer Windows-API-Bindungen verwendet werden.

Beachten Sie, dass alle vier Beispiele anfällig für DLL-Preloading-Angriffe sind , da example.dll zu einem vom Autor nicht vorgesehenen Ort aufgelöst werden kann (sofern nicht explizit ausgeschlossen, wird das Anwendungsverzeichnis vor den Systembibliotheksverzeichnissen durchsucht, und ohne HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode[ 9 ] oder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CWDIllegalInDLLSearch[ 10 ] wird das aktuelle Arbeitsverzeichnis vor den Systembibliotheksverzeichnissen durchsucht). Dadurch kann eine schädliche Version der Bibliothek gefunden werden. Hinweise von Microsoft zum sicheren Laden von Bibliotheken finden Sie in der Referenz: Verwenden Sie ` SetDefaultDllDirectoriesin`, kernel32um sowohl das Anwendungsverzeichnis als auch das aktuelle Arbeitsverzeichnis aus dem DLL-Suchpfad zu entfernen, oder ` SetDllDirectoryWin`, kernel32um das aktuelle Arbeitsverzeichnis aus dem DLL-Suchpfad zu entfernen. [ 11 ]

Microsoft Visual Basic

Option Explicit Declare Function AddNumbers Lib "Example.dll" _ ( ByVal a As Double , ByVal b As Double ) As DoubleSub Main ( ) Dim Result As Double Result = AddNumbers ( 1 , 2 ) Debug.Print "Das Ergebnis war: " & 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 <stdio.h> #include <windows.h>// DLL-Funktionssignatur typedef double ( * ImportedFunction )( double , double );int main ( int argc , char * argv []) { ImportedFunction addNumbers ; double result ; HINSTANCE hinstLib ;// DLL-Datei laden hinstLib = LoadLibrary ( TEXT ( "Example.dll" )); if ( ! hinstLib ) { printf ( "FEHLER: DLL konnte nicht geladen werden \n " ); return 1 ; }// Funktionszeiger abrufen addNumbers = ( ImportedFunction ) GetProcAddress ( hinstLib , "AddNumbers" ); if ( ! addNumbers ) { printf ( "FEHLER: DLL-Funktion konnte nicht gefunden werden \n " ); FreeLibrary ( hinstLib ); return 1 ; }// Funktion aufrufen. result = addNumbers ( 1 , 3 );// DLL-Datei entladen FreeLibrary ( hinstLib );// Ergebnis anzeigen printf ( "Das Ergebnis war: %f \n " , result );return 0 ; }

Python

Der Python-Interpreter verwendet das ctypes- Modul, welches eine Foreign Function Interface (FFI) bereitstellt, die Aufrufe von Funktionen in gemeinsam genutzten Bibliotheken ermöglicht.

Die Python-ctypes-Anbindung verwendet die POSIX-API auf POSIX-Systemen. [ 12 ]

import ctypesmy_dll = ctypes . cdll . LoadLibrary ( „Example.dll“ )Die folgende Spezifikation der "restype"-Methode ist erforderlich, damit Python versteht , welchen Typ die Funktion zurückgibt. my_dll.AddNumbers.restype = ctypes.c_doublep = my_dll.AddNumbers ( ctypes.c_double ( 1.0 ) , ctypes.c_double ( 2.0 ) )​​​​print ( "Das Ergebnis war:" , p )

Komponentenobjektmodell

Das Component Object Model (COM) definiert einen Binärstandard für die Implementierung von Objekten in DLL- und EXE-Dateien. Es bietet Mechanismen zum Auffinden und Versionieren dieser Dateien sowie eine sprachunabhängige und maschinenlesbare Beschreibung der Schnittstelle. Die Implementierung von COM-Objekten in einer DLL ist ressourcenschonender und ermöglicht die gemeinsame Nutzung von Ressourcen mit dem Clientprozess. Dadurch können COM-Objekte leistungsstarke Backends für einfache GUI-Frontends wie Visual Basic und ASP implementieren. Sie lassen sich auch aus Skriptsprachen heraus programmieren. [ 13 ]

DLL-Hijacking

Aufgrund einer Sicherheitslücke, die gemeinhin als DLL-Hijacking, DLL-Spoofing, DLL-Preloading oder Binary Planting bekannt ist, laden und führen viele Programme eine schädliche DLL aus, die sich im selben Ordner wie eine von diesen Programmen geöffnete Datendatei befindet. [ 14 ] [ 15 ] [ 16 ] [ 17 ] Die Sicherheitslücke wurde im Jahr 2000 von Georgi Guninski entdeckt. [ 18 ] Im August 2010 erlangte sie weltweite Bekanntheit, nachdem ACROS Security sie wiederentdeckt und Hunderte von Programmen als anfällig identifiziert wurden. [ 19 ] Programme, die aus unsicheren Verzeichnissen ausgeführt werden, z. B. aus beschreibbaren Ordnern wie dem Download- oder dem Temp- Verzeichnis, sind fast immer von dieser Sicherheitslücke betroffen. [ 20 ] [ 21 ] [ 22 ] [ 23 ] [ 24 ] [ 25 ] [ 26 ]

Siehe auch

  • Dependency Walker – ein Hilfsprogramm, das exportierte und importierte Funktionen von DLL- und EXE-Dateien anzeigt.
  • Dynamische Bibliothek  – Softwarebibliothek, die über dynamische Verknüpfung verwendet wird
  • Bibliothek (Informatik)  – Sammlung von Ressourcen, die zur Entwicklung eines Computerprogramms verwendet werden
  • Linker (Informatik)  – Programm, das Zwischendateien zu einer ausführbaren Datei zusammenfügt
  • Ladebares Kernelmodul  – Dynamisch ladbares Modul, das den laufenden Betriebssystemkernel erweitert.
  • Loader (Informatik)  – Teil eines Betriebssystems
  • Moricons.dll  – Grafische Benutzeroberfläche für frühe Windows-Systeme
  • Gemeinsam genutzte Bibliothek  – Eine Softwarebibliothek im Arbeitsspeicher, die von mehreren ausführbaren Dateien zur Laufzeit verwendet werden kann.
  • .exe  – Dateinamenserweiterung für ein natives ausführbares Programm

Referenzen

  1. ^ Microsoft Corporation (3. August 2021). „Erstellen einer reinen Ressourcen-DLL“ . Microsoft Developer Network Library .
  2. ^ „Das Ende der DLL-Hölle“ . Microsoft Corporation. Archiviert vom Original am 06.05.2008 . Abgerufen am 11.07.2009 .
  3. ^ „Die Importadresstabelle verstehen“ . Sandsprite.com . Archiviert vom Original am 7. November 2023. Abgerufen am 7. November 2023 .
  4. ^ „Erstellen und Verwenden von DLLs“ . Die Importbibliothek ist eine reguläre UNIX-ähnliche .a-Bibliothek, enthält aber nur die wenigen Informationen, die dem Betriebssystem benötigt werden, um die Interaktion des Programms mit der DLL („Importe“) zu steuern. Diese Informationen werden in die .exe-Datei eingebunden.
  5. ^ "ld und WIN32" . ld-Dokumentation .
  6. ^ „Linkerunterstützung für verzögert geladene DLLs“ . Microsoft Corporation . Abgerufen am 11.07.2009 .
  7. ^ Petrusha, Ron (26.04.2005). „Erstellen einer Windows-DLL mit Visual Basic“ . O'Reilly Media . Abgerufen am 11.07.2009 .
  8. ^ MSDN , Verwendung von extern zur Angabe der Verknüpfung
  9. ^ „Suchreihenfolge der Bibliothek mit dynamischen Verknüpfungen“ . Microsoft Developer Network . 9. Februar 2023. Abgerufen am 9. Februar 2023 .
  10. ^ „Ein neuer Registrierungseintrag namens CWDIllegalInDllSearch ist verfügbar, um den DLL-Suchpfadalgorithmus zu steuern . “ Microsoft Support .
  11. ^ „Sicheres Laden von Bibliotheken zum Schutz vor DLL-Vorladeangriffen“ . Microsoft Support . Abgerufen am 28. Oktober 2019 .
  12. ^ „ctypes – Eine Bibliothek für externe Funktionen in Python“ . Python-Dokumentation . Abgerufen am 9. Juli 2025 .
  13. ^ Satran, Michael (21. August 2020). „Component Object Model (COM)“ . msdn.microsoft.com .
  14. ^ Björklund, Andreas; Klövstedt, Johan; Westergren, Sven. „DLL-Spoofing in Windows“ (PDF) . Abteilung für Informationstechnologie, Universität Uppsala . Archiviert (PDF) vom Original am 7. November 2023 . Abgerufen am 7. November 2023 .
  15. ^ „DLL-Preloading-Angriffe“ . msdn.com . Abgerufen am 25. März 2018 .
  16. ^ „Weitere Informationen zum Remote-Angriffsvektor DLL-Preloading“ . technet.com . Abgerufen am 25. März 2018 .
  17. ^ „Ein Update zum Remote-Angriffsvektor DLL-Preloading“ . technet.com . Abgerufen am 25. März 2018 .
  18. ^ „Durch Doppelklicken auf MS Office-Dokumente im Windows Explorer können in manchen Fällen beliebige Programme ausgeführt werden . “ www.guninski.com . Abgerufen am 25. März 2018 .
  19. ^ „Binary Planting – Die offizielle Website einer vergessenen Sicherheitslücke. ACROS Security“ . www.binaryplanting.com . Abgerufen am 25. März 2018 .
  20. ^ Dormann, Will (4. September 2008). „Carpet Bombing and Directory Poisoning“ . Carnegie Mellon University – SEI Blog . Archiviert vom Original am 7. November 2023. Abgerufen am 7. November 2023 .
  21. ^ „Entwickler an Mozilla: Bitte entfernt die veralteten Windows-Installationsprozesse . “ theregister.co.uk . Abgerufen am 25. März 2018 .
  22. ^ „Gpg4win – Sicherheitshinweis Gpg4win 2015-11-25“ . www.gpg4win.org . Abgerufen am 25. März 2018 .
  23. ^ „McAfee KB – McAfee Security Bulletin: Sicherheitspatch für mehrere McAfee-Installations- und Deinstallationsprogramme (CVE-2015-8991, CVE-2015-8992 und CVE-2015-8993) (TS102462)“ . service.mcafee.com . Abgerufen am 25. März 2018 .
  24. ^ „fsc-2015-4 - F-Secure Labs“ . www.f-secure.com . Archiviert vom Original am 31. Juli 2017. Abgerufen am 25. März 2018 .
  25. ^ „ScanNow DLL Search Order Hijacking Vulnerability and Deprecation“ . rapid7.com . 21. Dezember 2015 . Abgerufen am 25. März 2018 .
  26. ^ Team, VeraCrypt. „oss-sec: CVE-2016-1281: TrueCrypt- und VeraCrypt-Windows-Installationsprogramme ermöglichen die Ausführung beliebigen Codes mit erhöhten Rechten“ . seclists.org . Abgerufen am 25. März 2018 .
  • Hart, Johnson. Windows-Systemprogrammierung, dritte Auflage . Addison-Wesley, 2005. ISBN 0-321-25619-0Die
  • Rector, Brent et al. Win32-Programmierung . Addison-Wesley Developers Press, 1997. ISBN 0-201-63492-9Die