Canvas not supported
Canvas not supported
Suchen
Bookmark
Canvas not supported
Shine Effekt
Direkt zum Seiteninhalt

Hauptmenü:

Windows Libraries I

 

Autor:

Oscar Kohler

Version:

0.11

Level:

Einfach

Sprache:

C/C++


 
Haftungsausschluss / Disclaimer
Kontakt / Contact
Drucken / Print

Windows Libraries im Allgemeinen


Libraries werden unter Windows seit Anfang an sehr häufig und für unterschiedliche Zwecke verwendet. Sei es um Platten.- oder Speicherplatz zu sparen, die Kompilierzeiten zu verbessern oder Programme zu modularisieren.

Alle Libs haben zumindest 3 Dinge gemeinsam:
  • Sie enden mit der Dateiendung: .dll ( ActiveX Elemente mit der Endung: .ocx, Control panels meist mit der Endung: .cpl )
  • Libs können nicht direkt ausgeführt werden, sie benötigen immer einen Host
  • Sie zählen zu den Executables und verwenden daher das ^ PE Format ( Portable executable )

Resource Lib / DLL


Beginnen wir mit der simpelsten Art, den Resource Libs.

Sie enthalten keinen Code ( Programmanweisungen ) sondern ausschliesslich Resourcen wie Bilder, Sounds und Strings.

Ein hervorragendes Beispiel für eine Resource Lib ist die imageres.dll, die man unter %SystemRoot%\System32 findet. Sie enthält eine ganze Menge an Windows Grafiken und hat die stattliche Grösse von fast 20 MB.

Verwendet werden Resource Libs vorallem für:

  • Internationalisierung:

    Für jede Sprache wird eine eigene DLL angelegt, die Strings und Bilder in der jeweiligen Sprache enthält.

  • Skinning:

    Pro Theme ( Grafische Oberfläche ) wird eine eigene DLL angelegt, die alle Grafiken für das Theme vereint.


Resource ToolMit speziellen Resource Tools kann man sich den Inhalt einer ( Resource ) Lib ansehen.

In dieser Beispiel DLL sind einige Resourcen, jedoch kein Programm Code untergebracht.

Programm Bibliothek / DLL


Sie sind die "klassischen" Windows Libraries. Ursprünglich vorallem aufgrund des knappen Speicherplatzes eingeführt, sind sie ein fester Bestandteil von Windows.

Da bei Programmen viele Aufgaben ähnlich sind, wie z.B.: eine Datei zu lesen oder zu beschreiben, die Registry zu bearbeiten, ein Bild auf dem Bildschirm anzuzeigen, Text auf dem Monitor auszugeben, ... macht es Sinn, diese Routinen in Bibliotheken zu bündeln und von allen Programmen gemeinsam zu nutzen.

  • ( Dynamische ) Libs werden nur einmal geladen und können von vielen Programmen gleichzeitig benutzt werden, spart daher Speicher und Festplattenplatz

  • Nützliche Routinen werden in Systembibliotheken zusammengefasst und mit dem System ( Windows ) ausgeliefert

  • Aufgrund der grossen Verbreitung werden Fehler oder Schwächen schnell entdeckt und meist rasch gefixed oder erweitert


Programm Bibliothek / Application Lib
Beispiel einer IO Lib:

System lädt die Lib und stellt sie dem Programm zur Verfügung,
Lib wird initialisiert,
Über die Adress Tabelle kann auf die Funktionen zugegriffen werden,
Wird die Lib nicht mehr benötigt, entfernt sie das System aus dem Speicher.

Binding / Linking


Damit ein Programm eine Lib benutzen kann, muss diese zuvor dem Programm zur Verfügung gestellt werden.
Diesen Vorgang nennt man "binding".


Je nach Art des "binding" unterscheidet man drei unterschiedliche Bibliothek Typen:

  • statische Libs ( .lib )

  • dynamische lib mit dynamic ( implizit ) binding ( .dll ),

  • dynamische lib mit runtime ( explizit ) binding ( .dll )



Bibliothek Bindung / Lib binding

Statische Bibliothek ( static lib )


Beginnen wir mit der einfachsten Programm-Lib und steigern uns langsam hoch :-)

Der Grund warum eine statische Lib so unkompliziert ist liegt darin, dass die Lib direkt in das Programm eingebunden ( gelinkt ) wird. Die Lib wird einmal entwickelt und kann danach zu jedem Programm gelinkt werden, um deren Funktionen und Resourcen zu nutzen.

Statische Bibliothek / Static Lib


Von "aussen" sieht man dem Programm nicht an, dass es mit einer Lib verlinkt wurde. Das Programm ist nach der Kompilierung praktisch "ein Guss".

Das ist allerdings auch der grosse Nachteil einer statischen Lib. Durch die direkte Einbindung in das Programm geht der Nutzen der Speicheroptimierung verloren.

Trotzdem bieten auch statische Libs viele Vorteile:

  • Wiederverwendbarkeit von Code, da die Funktionen nur einmal geschrieben werden müssen

  • Libs werden nur bei Änderung neu kompiliert, daher optimierte Kompilierzeiten

  • Vereinfachte Test Prozeduren

  • Modularer Programmaufbau

  • Weitergabe von Funktionen, ohne dass der Code offengelegt werden muss ( third party module )

Dynamische Lib ( DLL )


Dynamische Libs ( DLL's ) werden im Gegensatz zu den statischen nicht direkt in das Programm gelinkt, sondern liegen separat als .dll Datei vor und werden erst bei Bedarf nachgeladen.


Dynamische Bibliothek / Dynamic Lib / DLL


Dadurch bieten sie den grossen Vorteil der anfangs erwähnten Speicherersparnis:

  • DLL's müssen nur einmal auf der HD vorliegen,

  • Programmcode und shared Daten werden nur einmal in den Speicher geladen, können aber von vielen Programmen gleichzeitig genutzt werden !


Durch die Möglichkeit des dynamischen Ladens werden DLL's oft für folgende Zwecke eingesetzt:

  • Nachladen während der Laufzeit ermöglicht dynamische Nutzung von Plugins, Skins, Features
  • Installationen können während der Ausführung an das Zielsystem angepasst werden
  • Gezieltes Patch Management, ohne das komplette Programm auszutauschen zu müssen
  • Spezial Anwendungen wie z.B.: shared Memory zwischen verschiedenen Programmen

Dynamische Bibliothek Share / Dynamic Lib sharing


Die DLL wird je nach Bedarf geladen und auch wieder entladen.


Lebenszyklus einer DLL


Zuerst wird nachgeschaut, ob die DLL bereits zuvor in den Speicher geladen wurde. Wenn nicht wird die DLL nun in den Speicher geladen.

  • Der "Benutzungs" Zähler ( Referenz Counter ) wird inkrementiert ( +1 )
  • DLL wird in den Adressraum des Hostprogrammes gemapped.
    Code und shared Datasegmente werden in der Regel von allen ( Host ) Programmen gemeinsam genutzt
  • Daten Segmente werden in den Adressraum des Programms kopiert
  • Beim Programmende oder expliziter Freigabe der DLL wird der Referenz  Counter dekrementiert ( -1 ).
    Wird die DLL von keinem Programm mehr benötigt ( Ref Counter = 0 ), wird sie vom System aus dem Speicher entfernt

RunDll32


Wie bereits besprochen, können DLL's nicht einfach "mal so" gestartet werden, sondern benötigen immer eine Art Host um an deren Funktionen und Resourcen ran zukommen.

In solchen Fällen kann uns vielleicht rundll32.exe aus der Patsche helfen. RunDll32.exe und die 16 Bit Version RunDll.exe waren ursprünglich als interne Microsoft Tools konzipiert, um Funktion einer DLL ausführen zu können. Später wurden sie jedoch offiziell mit Windows ausgeliefert.

Windows selbst verwendet rundll32 recht häufig und auch in der Windows Gemeinde ist rundll32 sicher kein Geheimtipp mehr.

Vielleicht ist aber schon manchem aufgefallen, dass der Gebrauch des Tools recht tricky sein kann. Nicht immer funktioniert rundll32 so, wie manche sich es wünschen würden.
Der Grund liegt darin, dass eine DLL "speziell" für die Benutzung durch rundll32 angepasst werden muss. Es kann also nicht jede beliebige DLL benutzt werden.

Jede Funktion einer DLL, die durch rundll32 benutzt werden soll, muss die folgende Funktions Signatur aufweisen:

void CALLBACK NameDerFunktion(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

Nur dann kann rundll32 die Funktion korrekt aufrufen. Versucht man eine Funktion auszuführen, die nicht dieser Signatur entspricht, kann es unter Umständen sehr gefährlich werden.

Beispiel eine DLL "testdll" die eine Funktion "Hello" exportiert.


rundll32.exe Dll,Funktion Parameter

rundll32.exe testdll.dll,Hello Genau so soll es aussehen !

Test bei einer Dll die nicht für rundll32 geschrieben wurde:

Passiert das ...

Fehler rundll32 / Error rundll32

oder das ...

Fehler rundll32 / Error rundll32

Erst wenn die Funktion der korrekten Signatur entspricht funktioniert der Aufruf:

rundll32 functioniert / rundll32 works

Beispiele für RunDll32 Aufrufe findet man im Internet tonnenweise.


Darum hier nur ein paar Beispiele ...

Controls

RunDll32.exe shell32.dll,Control_RunDLL

Folder Optionen

RunDll32.exe shell32.dll,Options_RunDLL

Lock Computer:

RunDll32.exe user32.dll,LockWorkStation

Network Mapping

Rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL Connect

IE Favoriten:

Rundll32.exe shdocvw.dll,DoOrganizeFavDlg

Printers

Rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL PrintersFolder

Cached Credentials:

RunDll32.exe keymgr.dll,KRShowKeyMgr

Savely remove

Rundll32.exe shell32.dll,Control_RunDLL HotPlug.dll

Taskbar Properties

RunDll32.exe shell32.dll,Options_RunDLL 1

Windows About

RunDll32.exe shell32.dll,ShellAboutW

Fonts

Rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL FontsFolder

User Profile

Rundll32.exe sysdm.cpl,EditUserProfiles

Screen Saver

Rundll32.exe shell32.dll,Control_RunDLL desk.cpl,screensaver,@screensaver

Network Diagnostic

Rundll32.exe ndfapi,NdfRunDllDiagnoseIncident

Drucker hinzufügen

Rundll32.exe shell32.dll, SHHelpShortcuts_RunDLL AddPrinter


DLL Hell


Viele Programme sind an bestimmte Versionen einer DLL gebunden. Entweder weil sie Funktionen einer bestimmten Version, oder bestimmte Signaturen einer Funktion benötigen.
Oft werden mit neueren Versionen einer DLL neue Funktionen hinzugefügt, alte Funktionen rausgeschmissen, oder Funktionssignaturen geändert.
Dies führt zum Problem, wenn unterschiedliche Programme, unterschiedliche Versionen einer gemeinsamen DLL benötigen und erwarten. Gerade wenn diese DLL's zentral, z.B.: im System32, abgelegt wurden und durch verschiedene Installer überschrieben werden, sind Probleme aufgrund Versions Konflikten äusserst wahrscheinlich.
Derartige Fehler sind unter Umständen sehr schwer zu lokalisieren, daher gab man dieser Problematik die unheilvolle Bezeichnung: "DLL Hell"

DLL Hell / DLL Hölle

Es gibt unterschiedliche Möglichkeiten dieses Problem zu umschiffen, alle mit dem Nachteil des Verlustes der Speicherersparnis:

  • Einbeziehen der Version in den DLL Namen, z.B.: msvcr100.dll
  • Absolute Pfadangaben
  • Ausnutzung der DLL Suchreihenfolge
  • DLL Redirection
  • Manifest
  • side-by-side assemblies
  • Applikations Virtualisierung
  • ...

DLL Suchreihenfolge


Wurde eine DLL nicht bereits in den Speicher geladen, sucht Windows nach einer bestimmten Reihenfolge in den Verzeichnissen.
Die Reihenfolge kann durch verschiedene Faktoren wie absolute Pfadangabe, DLL Redirection, Manifest, SafeDllSearchMode beeinflusst werden.


DLL Redirection


Kommt es zu Konflikten aufgrund unterschiedlicher Versionen einer DLL, kann man sich u.U. mit einer DLL Redirection helfen.
Wird eine Redirection angelegt, so bevorzugt Windows das Applikations Verzeichnis beim Laden einer DLL.

  • Anlegen der Redirection Datei: Appname.local im Programm Verzeichnis. z.B.: myapp.exe.local wenn das Programm myapp.exe heisst 
  • Kopieren der gewünschten DLL's in das Programmverzeichnis

Known DLLs


Die Funktion der Known DLL Liste ist etwas mystisch, da sie sich abhängig der Windows Version immer wieder ändert.

Prinzipiell erfüllt sie, je nach Windows Version, folgenden Zweck:

  • Kernel lädt die DLL's in dieser Liste beim Systemstart ( Preloading )
  • Diese DLL's werden aus einem gemeinsamen Ordner geladen
  • Suchreihenfolge wird bei diesen DLL's ignoriert
  • DLL Redirection ist wirkungslos

Die Liste findet man unter folgendem Registry Hive:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ Session Manager\KnownDLLs

AppInit DLLs


Alle DLL's in der ^ AppInit_DLLs Liste werden beim Start jedes interaktiven Programmes, d.h. alle mit user32.dll gelinkten Programme, in deren Adressraum gemapped und haben somit Zugriff auf den gesamten Adressraum dieser Programme. Oft wird diese Möglichkeit verwendet um das System zu hooken.
DLL's in dieser Liste sind generell mit Vorsicht zu betrachten.

Die Liste findet sich unter folgendem Registry Value:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
AppInit_DLLs

Shared Memory


DLL's können auch zum Austausch von Daten zwischen verschiedenen Programmen "missbraucht" werden. Dazu wird in einer DLL ein shared data segment definiert und exportiert. Nun können alle Programme welche die DLL laden, dieses Segment lesen oder beschreiben. ( ^ How do i share data ... )
Von dieser Technik ist allerdings grundsätzlich abzuraten ! Vorallem aus Gründen der Sicherheit, da jedes Programm diese Daten unabhängig der Zugriffsrechte ändern kann. 

#pragma data_seg("SHARED")
   _declspec(dllexport) volatile int g_iTest   = 0;
#pragma data_seg()

#pragma comment(linker, "/SECTION:SHARED,RWS")

Function Forwarding


Will man Funktionen einer DLL in eine andere DLL umsiedeln, so kann man sich eventuell mit function forwarding behelfen. Dabei wird in einem Pragma definiert, dass sich die altbekannte Funktion nun unter neuem Namen in einer anderen DLL findet.

#pragma comment(linker, "/EXPORT:OldFunction=NewDLL.NewFunction")

Dadurch wird ein Eintrag in der Export Tabelle angelegt, der den Image Loader von OldFunction zu NewFunction in NewDLL.dll umleitet. Pro Funktion muss jeweils ein Pragma definiert werden. Im MSDN Artikel: "An In-Depth Look into the Win32 Portable Executable File Format, Part 2" wird dies im Abschnitt ^ Export Forwarding kurz erklärt.

Delay Loading


Wir haben uns bereits die Vorteile von explizitem gegenüber implizitem Linken angesehen. Der grosse Vorteil liegt darin, dass eine DLL erst dann geladen wird, wenn man Funktionen oder Resourcen aus ihr benötigt. Leider erkaufen wir uns diesen Vorteil durch mühsame Handarbeit:

  • DLL manuell laden
  • Funktions Adresse manuell ermitteln

Mit ^ Delay Loading hat Microsoft in Visual C++ ein nettes Feature eingebaut, das uns einiges an Handarbeit abnimmt.
Diese DLL's werden zwar implizit definiert, während der Laufzeit aber quasi explizit behandelt. Erst beim Aufruf der Funktion wird die DLL geladen, allerdings mit einigen Einschränkungen.

Hilfreiche Tools


dumpbinIst ein "COFF Binary File Dumper" der es ermöglicht, die verschiedenen PE Sektionen und Tabellen wie: Import, Section, Relocation, ... einer Executable zu untersuchen. Das Tool liegt Visual Studio bei.

Zeigt die Abhängigkeiten einer Executable hirarchisch an. Dabei werden alle abhängigen Module und deren exportierte / aufgerufene Funktionen aufgelistet.

 
Kein Kommentar
 
Letzte Änderung: 03.02.2015
button Canvas not supported button
Zurück zum Seiteninhalt | Zurück zum Hauptmenü