• Nie Znaleziono Wyników

Biblioteki DLL, aplety panelu sterowania, haki

N/A
N/A
Protected

Academic year: 2021

Share "Biblioteki DLL, aplety panelu sterowania, haki"

Copied!
33
0
0

Pełen tekst

(1)

Biblioteki DLL

Jacek Matulewski

15 kwietnia 2015

(aktualizacja: 10 marca 2018) Programowanie Windows

http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/

(2)

Definicje

• DLL (ang. dynamic-link library) – biblioteki ładowane/łączone dynamicznie, skompilowane moduły kodu zawierające zasoby i funkcje, które mogą być współdzielone przez różne aplikacje

• Ładowanie biblioteki DLL oznacza włączenie jej do wspólnej przestrzeni adresowej procesu

• Bibliotekami DLL są m.in. pliki .dll, .cpl, .drv lub .ocx

• Biblioteka może eksportować część funkcji

• Możliwa jest zmiana (aktualizacja) biblioteki DLL bez

konieczności przebudowywania używających ją programów

• Biblioteka DLL może być jednocześnie używana przez wiele programów

(3)

Zalety bibliotek DLL

• Modularność – bezpieczeństwo, także ułatwia aktualizację

• Współdzielenie kodu między aplikacjami, także jednocześnie (zob. chociażby biblioteki systemowe)

• Dynamiczne ładowanie: oszczędność pamięci, ładowane są tylko potrzebne biblioteki; po użyciu mogą być usunięte z pamięci

• Scenariusz wtyczek (ang. plug-in)

• Wykorzystanie jednego kodu w różnych językach

programowania i środowiskach programistycznych Windows

(4)

Eksport funkcji z biblioteki DLL

Definicje funkcji w pliku .cpp:

#include <windows.h>

void WyswietlKomunikat(char* s) {

MessageBox(NULL, s, "Komunikat z biblioteki DLL", MB_OK);

}

void Test0() {

WyswietlKomunikat("DLL - Test0");

}

void Test1(int i) {

WyswietlKomunikat("DLL - Test1");

}

(5)

Eksport funkcji z biblioteki DLL

Dodajemy deklaracje funkcji w pliku .h z modyfikatorami eksportu:

#include <windows.h>

#define __export __declspec(dllexport) //makro obecne w BCB __export void Test0();

extern "C" __export void Test1(int i);

Modyfikator extern "C" użyty w C++ powoduje, że nazwa eksportowanej funkcji nie jest modyfikowana i zachowuje zgodność z C.

W funkcji bez argumentów ten modyfikator nie jest potrzebny.

W C++, w odróżnieniu od C, możliwe jest przeciążanie funkcji, dlatego kompilator dodaje do ich nazw informacje o argumentach np. dla funkcji Test1 będzie to _Test1@4 (VC++) gdzie 4 to liczba bajtów potrzebna dla wszystkich argumentów lub @Test@qv (BCB) .

(6)

Eksport funkcji z biblioteki DLL

Nie wszystkie funkcje muszą być wyeksportowane:

extern "C" __export void Test2();

void FunkcjaWewnetrzna();

...

void Test2() {

WyswietlKomunikat("DLL - Test2");

FunkcjaWewnetrzna();

}

void FunkcjaWewnetrzna() {

WyswietlKomunikat("DLL - Funkcja wewnetrzna");

}

(7)

Eksport funkcji z biblioteki DLL

Modyfikator __stdcall – konwencja x86 wywoływania funkcji stosowana w WinAPI (przekazywanie argumentów, pobieranie wartości, ustawienia stosu) Szczegóły: http://en.wikipedia.org/wiki/X86_calling_conventions

Użycie __stdcall daje pewność, że będziemy w stanie zaimportować funkcję w każdym języku i środowisku (dla Windows, także P/Invoke).

Plik .h

extern "C" __export int __stdcall Test3a(char* s);

extern "C" __export char* __stdcall Test3b(char* s);

extern "C" __export int __stdcall Test3c(int i);

Plik .cpp

int __stdcall Test3a(char* s) { return strlen(s); } char* __stdcall Test3b(char* s) { return s; }

int __stdcall Test3c(int i) { return i; }Testy za pomocą systemowego programu RunDLL32 np. rundll32 Biblioteka,Funkcja

(8)

Embarcadero: implib i impdef

Narzędzia jeszcze od Borlanda:

implib – tworzy bibliotekę .lib używaną do statycznego importu bibliotek DLL impdef – pozwala na wyświetlenie listy funkcji eksportowanych z biblioteki DLL

LIBRARY PROJECT1.DLL

EXPORTS

@Test0$qv @1 ; Test0() @Test1$qv @2 ; Test1() Test3a @4 ; Test3a Test3b @5 ; Test3b Test3c @6 ; Test3c _Test2 @3 ; _Test2

___CPPdebugHook @7 ; ___CPPdebugHook

(9)

Microsoft: dumpbin

Uniwersalne narzędzie Visual C++

c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\dumpbin.exe

m.in. pozwala na wyświetlenie listy funkcji eksportowanych z biblioteki DLL:

dumpbin /exports <ścieżka>\project1.dll

Microsoft (R) COFF/PE Dumper Version 14.00.23506.0

Copyright (C) Microsoft Corporation. All rights reserved.

Dump of file t:\Wykłady\WinProg\Project1.dll File Type: DLL

Section contains the following exports for Project1_Eksport.dll

00000000 characteristics 0 time date stamp 0.00 version

1 ordinal base

7 number of functions 7 number of names

(10)

Microsoft: dumpbin

Wydruk z dumpbin c.d.:

Microsoft (R) COFF/PE Dumper Version 14.00.23506.0

Copyright (C) Microsoft Corporation. All rights reserved.

...

ordinal hint RVA name

1 0 000015D0 @Test0$qv 2 1 000015E0 @Test1$qv 3 2 000015F0 Test2 4 3 00001618 Test3a 5 4 000017A8 Test3b 6 5 00001920 Test3c

7 6 0001E0F8 ___CPPdebugHook Summary

9000 .data 1000 .edata 1000 .idata 3000 .reloc 2000 .rsrc 1D000 .text 1000 .tls

(11)

Powiadamianie o załadowaniu

Biblioteka może być wyposażona w dwie funkcje

uruchamiane przez system: DllMain i DllEntryPoint (ta sama sygnatura, ale są między nimi subtelne różnice):

//int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) BOOL WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

switch(reason) {

case DLL_PROCESS_ATTACH:

WyswietlKomunikat("Biblioteka DLL załadowana do procesu procesu");

break;

case DLL_PROCESS_DETACH:

WyswietlKomunikat("Biblioteka DLL wyładowana z pamięci procesu");

break;

default:

WyswietlKomunikat("Inny powód wywołania DllMain/DllEntryPoint");

break;

}

return TRUE; //1 }

(12)

Powiadamianie o załadowaniu

Możliwe wartości parametru reason:

DLL_PROCESS_ATTACH – proces ładuje bibliotekę DLL DLL_THREAD_ATTACH – bieżący proces tworzy wątek DLL_THREAD_DETACH – wątek jest „zdrowo” kończony

DLL_PROCESS_DETACH – proces wyładowuje bibliotekę DLL Użycie TerminateProcess lub TerminateThread

nie spowoduje wywołania DllMain/DllEntryPoint.

W aplikacjach wielowątkowych – tylko jeden wątek na raz może wywoływać DllMain/DllEntryPoint.

(13)

Import funkcji – łączenie statyczne

Deklaracje funkcji w kodzie aplikacji lub innej biblioteki DLL:

#define __import __declspec(dllimport) __import void Test0();

__import void Test1(int i);

extern "C" __import void Test2();

extern "C" __import int __stdcall Test3a(char* s);

extern "C" __import char* __stdcall Test3b(char* s);

extern "C" __import int __stdcall Test3c(int i);

void KlasaAplikacji::Metoda() //użyte funkcje BCB {

Test0(); Test1(0); Test2();

ShowMessage((AnsiString)"EXE - "+IntToStr(Test3a("Test3a")));

ShowMessage((AnsiString)"EXE - "+Test3b("Test3b"));

ShowMessage((AnsiString)"EXE - "+IntToStr(Test3c(345)));

}

(14)

Import funkcji – łączenie statyczne

Zalety:

•łatwiejsze,

•nieco szybsze uruchamianie (ale nie udało mi się potwierdzić)

Wady:

•katastrofa w razie braku pliku DLL lub błędów,

•brak jakiegokolwiek wpływu programisty na linkowanie,

•tylko jeden scenariusz

(ładowanie automatyczne na cały czas działania aplikacji).

(15)

Łączenie „dynamiczne”

Ładowanie biblioteki:

HINSTANCE DllHandle = LoadLibrary(nazwaPlikuDll.c_str());

if(DllHandle != NULL)

ShowMessage("Wczytanie biblioteki DLL powiodło się") else

{

ShowMessage("Wczytanie biblioteki DLL nie powiodło się");

return;

}

Ten fragment możemy wstawić w dowolnym miejscu kodu (np. decyzja użytkownika, wykrycie pliku biblioteki).

(16)

Łączenie „dynamiczne”

Pobieranie adresów funkcji (wspólna przestrzeń adresowa):

//deklaracja w bibliotece DLL: __declspec(dllimport) void Test0();

//deklaracja typu

typedef void (*DllTestType)();

//pobieranie adresu funkcji DllTestType Test0 =

(DllTestType)GetProcAddress(DllHandle,"@Test0$qv");

//komunikat o błędzie lub uruchomienie if(Test0 == NULL)

Wyświetl("Pobranie adresu funkcji Test0 nie jest możliwe");

else

Test0();

(17)

Łączenie „dynamiczne”

Pobieranie adresów funkcji (wspólna przestrzeń adresowa):

//w bibliotece DLL: extern "C" __declspec(dllimport) void Test2();

//deklaracja typu

typedef void (*DllTestType)();

//pobieranie adresu funkcji DllTestType Test2 =

(DllTestType)GetProcAddress(DllHandle,"_Test2");

//komunikat o błędzie lub uruchomienie if(Test2 == NULL)

ShowMessage("Pobranie adresu funkcji Test2 nie jest możliwe");

else

Test2();

(18)

Łączenie „dynamiczne”

Pobieranie adresów funkcji (wspólna przestrzeń adresowa):

//extern "C" __declspec(dllimport) int __stdcall Test3a(char* s);

//deklaracja typu

typedef int (*DllTest3aType)(char* s);

//pobieranie adresu funkcji DllTest3aType Test3a =

(DllTest3aType)GetProcAddress(DllHandle,"Test3a");

//komunikat o błędzie lub uruchomienie if(Test3 == NULL)

ShowMessage("Pobranie adresu funkcji Test3 nie jest możliwe");

else

int wynik = Test3a("Test3a");

(19)

Łączenie „dynamiczne”

Wyładowanie biblioteki z bieżącego procesu:

if (FreeLibrary(DllHandle))

ShowMessage("Wyładowanie biblioteki powiodło się");

else

ShowMessage("Wyładowanie biblioteki nie powiodło się");

Biblioteka DLL tworzy licznik dla załadowań z danego procesu:

LoadLibrary go zwiększa, a FreeLibary – zmniejsza.

Gdy licznik spada do zera, biblioteka jest usuwana z przestrzeni adresowej procesu.

Wyładowanie biblioteki z bieżącego procesu w żaden sposób nie wpływa na jej obecność w pamięci innych procesów.

(20)

Ścieżka przeszukiwania

Biblioteki DLL, których cała nazwa nie jest podana szukane są kolejno w następujących miejscach:

1. katalog, w którym jest plik .exe bieżącego procesu, 2. bieżący katalog (katalog roboczy),

3. katalog systemowy Windows (por. GetSystemDirectory) np. C:\Windows\SysWOW64

4. katalog Windows (por. GetWindowsDirectory) np. C:\Windows

5. katalogi wymienione w zmiennej środowiskowej PATH

(21)

Aplet panelu sterowania

Aplety panelu sterowania to biblioteki DLL,

które zawierają funkcję CplApplet (trzeba ją eksportować):

long __stdcall CPlApplet(HWND hwndCPl, unsigned uMsg, long lParam1,long lParam2) {

CPLINFO* pCpli = NULL;

long wynik = 0;

switch(uMsg) {

//załadowanie biblioteki, otwarcie panelu sterowania case CPL_INIT:

wynik = TRUE;

break;

...

(22)

Aplet panelu sterowania

Aplety panelu sterowania to biblioteki DLL,

które zawierają funkcję CplApplet (trzeba ją eksportować):

//pytanie o ilość elementów panelu sterowania w bibliotece case CPL_GETCOUNT:

wynik = 1;

break;

//informacja o elementach (dla każdego osobny komunikat) case CPL_INQUIRE: //jest też CPL_NEWINQUIRE

pCpli = (CPLINFO*)lParam2;

pCpli->idIcon = 101;

pCpli->idName = 1;

pCpli->idInfo = 2;

pCpli->lData = 0;

wynik = 0;

break;

(23)

Aplet panelu sterowania

Aplety panelu sterowania to biblioteki DLL,

które zawierają funkcję CplApplet (trzeba ją eksportować):

//użytkownik kliknął ikonę elementu w panelu sterowania case CPL_DBLCLK:

StworzOkno();

wynik = 0;

break;

//zamykany panel sterowania case CPL_STOP:

wynik = 0;

break;

(24)

Aplet panelu sterowania

Aplety panelu sterowania to biblioteki DLL,

które zawierają funkcję CplApplet (trzeba ją eksportować):

//zamykany panel sterowania case CPL_EXIT:

UsunOkno();

wynik = 0;

break;

default:

wynik = 0;

break;

}

return wynik;

}

(25)

Aplet panelu sterowania

Od Windows XP należy elementy panelu sterowania

rejestrować (5 kroków), m.in. należy im przypisać kategorie Windows XP:

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\

Control Panel\\Extended Properties\\

{305CA226-D286-468e-B848-2B2E8E697B74} 2";

Windows Vista i późniejsze:

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\

Control Panel\\Extended Properties\\

System.ControlPanel.Category";

%SystemRoot%\\SysWOW64\\project1.cpl = numer kategorii

Kategorie: https://msdn.microsoft.com/en-us/library/windows/desktop/cc144183(v=vs.85).aspx Rejestracja: https://msdn.microsoft.com/en-us/library/windows/desktop/hh127454(v=vs.85).aspx

(26)

Haki

Przesyłanie komunikatów do aplikacji (mysz, klawiatura, debugowanie, wywoływanie procedury okna) może być

monitorowane poprzez haki. Oznaczają one wywołanie procedury haka zdefiniowanej przez programistę i wyeksportowanej z

biblioteki. Biblioteka DLL z hakiem jest niejawnie ładowana do przestrzeni adresowej każdego procesu, który otrzymuje

monitorowany komunikat. Haki mogą tworzyć łańcuchy.

Ustawianie haka: SetWindowsHookEx

Zwalnianie haka: UnhookWindowsHookEx Procedura haka:

LRESULT CALLBACK KeyboardProcEvent(

int code, WPARAM wParam, LPARAM lParam)

(27)

Haki

Do ustawienia haka potrzebny będzie uchwyt do instancji DLL:

#include <windows.h>

HINSTANCE uchwytDLL = NULL;

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

if(reason == DLL_PROCESS_ATTACH) uchwytDLL = hinst;

return 1;

}

Deklarujemy procedurę haka dla komunikatów dot. klawiatury:

extern "C" __declspec(dllexport) LRESULT CALLBACK KeyboardHookProc(

int kod, WPARAM wParam, LPARAM lParam);

(28)

Haki

Procedura haka:

#include <fstream.h>

LRESULT CALLBACK KeyboardHookProc(int kod, WPARAM wParam, LPARAM lParam) {

if(kod == HC_ACTION) {

if((lParam & 0x80000000)==0) Beep(150,50);

else Beep(50,50);

if((lParam & 0x80000000)==0) {

ofstream txt("C:\\Users\\keylogger.txt",ios::app);

if(wParam>32 && wParam<127) txt << (char)wParam;

else txt << "(" << wParam << ")";

txt.close();

} }

return CallNextHookEx(uchwytHaka, kod, wParam, lParam);

}

(29)

Haki

Ustawianie haka za pomocą funkcji wyeksportowanej z tej samej biblioteki (może być osobny loader):

HHOOK uchwytHaka=NULL;

extern "C" __declspec(dllexport) void __stdcall UstawHak() {

uchwytHaka = SetWindowsHookEx(

WH_KEYBOARD,

(HOOKPROC)KeyboardHookProc, uchwytDLL,

NULL);

if(uchwytHaka==NULL)

MessageBox(NULL, "Założenie haka nie powiodło się", "KeyHook", MB_OK|MB_ICONERROR);

else MessageBox(NULL,"Założenie haka powiodło się", "KeyHook", MB_OK|MB_ICONINFORMATION);

}

(30)

Haki

Zwalnianie haka:

extern "C" __declspec(dllexport) void __stdcall UsunHak() {

bool wynik=UnhookWindowsHookEx(uchwytHaka);

if(wynik) MessageBox(NULL,"Usuniecie haka powiodło się", "KeyHook", MB_OK|MB_ICONINFORMATION);

else MessageBox(NULL,"Usuniecie haka nie powiodło się", "KeyHook", MB_OK|MB_ICONERROR);

}

Zastosowania: debugowanie, nagrywanie i odtwarzanie makr, keylogger, generowanie liczb losowych, wsparcie dla klawisza pomocy (F1), imitowanie myszy i klawiatury, wspierane

komputerowo treningi dotyczące oprogramowania (CBT)

(31)

Dema

1. Dynamiczne ładowanie biblioteki DLL 2. Aplet panelu sterowania GetTicks.cpl 3. Hak

(32)

Przykładowe pytania

• Jakie są dopuszczalne nazwy funkcji entry point DLL?

• Dlaczego należy używać modyfikatora __stdcall w funkcjach eksportowanych z bibliotek DLL?

• Statyczne vs „dynamiczne” ładowanie biblioteki DLL.

• Jaka funkcja służy do załadowania biblioteki DLL w runtime?

Jaką funkcją pobieramy adres funkcji z biblioteki DLL?

Jaką funkcją biblioteka jest usuwana z pamięci?

• W jakiej sytuacji wywołanie funkcji FreeLibrary nie spowoduje usunięcia biblioteki z pamięci?

(33)

Przykładowe pytania

• Jaki program składowy Visual Studio pozwala na inspekcję funkcji eksportowanych przez bibliotekę DLL?

• W jakich czterech sytuacjach wywoływana jest funkcja DllMain/DllEntryPoint?

• Gdzie należy umieścić bibliotekę DLL pełniącą rolę apletu panelu sterowania? Jakie musi mieć rozszerzenie?

Jaka funkcja zwrotna musi być w niej zdefiniowana?

• Jak definiuje się i jak działają haki Windows?

Cytaty

Powiązane dokumenty

Konferencja Do biblioteki szkolnej nie tylko po książkę odbywała się pod patronatem medialnym serwisów interne- towych – InfoKatowice.pl i Elektronicznej Biblioteki Pedagogicznej

Bóg ukarał Izrael, poniew aż pow rócił on do idolatrii, ukarał także „now y Izrael” , lud chrześcijański, poniew aż pogrążył się w bałw ochw alstw ie,

&#34;Wagon pamięci&#34;, którym podróżuje grupa młodych osób ma przypomnieć Polakom o wydarzeniach, które zdecydowały o wolności..

* młodzież poznaje historię jednej rodziny (Arnsztajnów) na tle różnych epok i czasów oraz zdobywa kompleksową wiedzę na temat historii i kultury swojego kraju i regionu;?.

Jednym z zastosowanych w aplikacji tego projektu szablonów jest „Rozmowa o [rozpoznane słowo] przypomina mi wiersz zaczynający się od słów: [przykładowe zdanie

• Podanie starszej części adresu na linie adresowe pamięci DRAM jako adresu wiersza, a następnie wytworzenie aktywnego zbocza sygnału RAS#, powodującego zapamiętanie tego adresu

Licencje Creative Commons (tak jak inne licencje typu Open Content), mogą być skutecznie wykorzystywane jako narzędzie Open Access. Co więcej, wykorzystanie otwartych

- communicative abilities, communicative knowledge and communicative skills (Is. Sauvignon); language, substantive and pragmatic competences (D. Savchenko); -