Computer Emergency Response Center

DLL HiJack hücümları nədir və necə həyata keçirilir

DLL nədir?

“Dinamik kitabxana faylı” olaraq dilimizə tərcümə edilən bu fayl tipi “Windows” (bundan sonra ƏS) əməliyyat sisteminin ən kritik fayl tiplərindən biridir desək yəgin yanılmarıq. ƏS-nin ən kritik prosesləri bu fayl tipini istifadə edir və ondan (onlardan) asılıdırlar. “Paylaşıla bilən” kitabxana olaraqda bilinən bu fayl tipinin əsas üstünlüyü geniş istifadə edilməsi nəzərdə tutulan funksiyaları tək bir DLL içərisində saxlamaq və beləliklə həm performans həmdə maliyyə baxımından üstünlük əldə etməkdir. Misal:  A və B prosesləri eyni əməliyyatı aparacaq funksiya-nı çağırmaq istəyirlər. Belə olan halda A və B-nin hər birinin eyni funksiyanı öz içərisində yazmaq və çağırmaq əvəzinə ortaq (paylaşılan) DLL faylı içərisində bu funksiyanı yazmaq və onu çağırmaq daha məqsədə uyğundur. Bundan əlavə olaraq bir digər üstünlüyü paylaşıla bilən olmasıdır. A və B-nin ayrı ayrılıqda eyni kitabxananı yaddaşına yükləmək əvəzinə, kitabxananın bir dəfə yaddaşa yüklənməsi və sözü gedən funksiyanı çağırmaları kimi. Microsoft dinamik kitabxana fayllarının üstünlüyü haqqında:

Dynamic linking has the following advantages over static linking:

  1. Multiple processes that load the same DLL at the same base address share a single copy of the DLL in physical memory. Doing this saves system memory and reduces swapping.
  2. When the functions in a DLL change, the applications that use them do not need to be recompiled or relinked as long as the function arguments, calling conventions, and return values do not change. In contrast, statically linked object code requires that the application be relinked when the functions change.
  3. A DLL can provide after-market support. For example, a display driver DLL can be modified to support a display that was not available when the application was initially shipped.
  4. Programs written in different programming languages can call the same DLL function as long as the programs follow the same calling convention that the function uses. The calling convention (such as C, Pascal, or standard call) controls the order in which the calling function must push the arguments onto the stack, whether the function or the calling function is responsible for cleaning up the stack, and whether any arguments are passed in registers. For more information, see the documentation included with your compiler.

Dinamik kitabxana fayllarına qarşı istifadə edilən bəzi hücüm metodları

Əlbətdə ƏS-nin demək olar əsas funksionallığını aldığı bu cür kritik bir fayl pis niyyətli şəxslərində diqqətini cəlb etməkdədir. Zərərvericilər bu fayl tipi üzərindən qarşı tərəfə müdaxilə edə bilmək üçün müxtəlif metodlar araşdırıb tapıblar. Məqalədə bu metodların bəziləri haqqında məlumat veriləcəkdir.

Phantom DLL Hijacking

“Phantom DLL Hijack” adı verilən bu metod əməliyyat sistemində mövcud olmayan kitabxana faylının əvəzinə eyni adda lakin zərərli kitabxana faylınin yaradılması ilə həyata keçirilir. Hər hansı proqram təminatı sözü gedən proqramın ilk versiyasında istifadə etdiyi kitabxana faylının növbəti versiyasında istifadə etmir. Lakin sözü gedən kitabxana faylının yaddaşa yükləyən kodlar mövcud olduğu üçün sistem bu kitabxana faylının tapıb yükləməyə çalışır. Zərərli kitabxana faylı sözü gedən proqram təminatının sistemdə mövcud olmadığını aşkar edərsə bundan sui istifadə edərək sistemi yoluxdura və ya imtiyazların artırılması məqsədləri üçün istifadə edə bilər. Söze gedən metodu praktiki olaraq göstərə bilmək üçün kiçik bir test keçirək.

Ssenari:

DLLHiJack proqramı ilk versiyasında “mrl.dll” kitabxanasından istifadə etmişdir. Sözü gedən proqramın 2-ci versiyasında bu kitabxana faylına ehtiyyac duyulmamışdır və ya kitabxana faylı səhvən sistemdən silinmişdir.

mrl.c

#define DLL_EXPORT __declspec(dllexport)

DLL_EXPORT int __cdecl topla(int a, int b)
{
	return a + b;
}

BOOL WINAPI DllMain(HINSTANCE hInst,
	DWORD fdwReason,
	LPVOID lpReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		wprintf(L"mrl.dll: I'm loaded!\n");
		break;
	case DLL_PROCESS_DETACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	default:
		break;
	}

	return TRUE;
}

Burada mrl.dll kitabxanası 1 ədad topla adında funksiyası export etmişdir. Bu funksiya başqaları tərəfindən çağrılmaq üçün nəzərdə tutulmuşdur və özünə parametr olaraq gələn 2 ədad int tipində dəyəri toplayaraq nəticəni çağırana geri qaytarır.

DllHiJack.c

typedef int (__cdecl *pTopla)(int, int);

int main(void)
{

	HMODULE hModule = NULL;
	pTopla Topla = NULL;

	hModule = LoadLibraryA("mrl.dll");
	if (hModule == NULL)
	{
		printf("Error loading DLL [%d].", GetLastError());
		return -1;
	}

	Topla = (pTopla)GetProcAddress(hModule, "topla");
	if (Topla == NULL)
	{
		printf("Function topla not found.");
		FreeLibrary(hModule);
		return -1;
	}

	printf("Result: %d\n", Topla(5, 4));
	return 0;
}

DllHiJack proqramı isə mrl.dll kitabxana faylının yaddaşına yükləyərək topla funksiyasını (4,5) parametrlərini göndərərək çağırır və nəticəni ekrana yazdırır.

2-ci versiyada sözü gedən kitabxana mrl.dll olmadığı üçün kitabxana faylı yüklənməyəcək. Lakin DLLHiJack kitabxananı yükləyəcək olan kodları proqram daxilində saxladığı üçün zərərverici tərəf üçün açıq qapı saxlayır. Kitabxana faylını test üçün sistemdən silirik və proqramı işə salaraq müşahidə edirik.

DLL yükləyici kitabxana faylının sistemdə olmadığı üçün yüklədiyi anda xəta ilə qarşılaşır. Əgər bu məlumat zərər vermək istəyən şəxs tərəfindən anlaşılarsa “Phantom DLL Hijacking” metodu ilə yoluxdurma əməliyyatını icra edə bilər. Zərərverici mrl.dll adında zərərli dll yaradır və proqramın olduğu qovluğa yerləşdirir.

 

mrl.c (zərərli)

BOOL WINAPI DllMain(HINSTANCE hInst,
	DWORD fdwReason,
	LPVOID lpReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		printf("mrl.dll: Hello World!\n");
		printf("malware: Hello World!\n");
		break;
	case DLL_PROCESS_DETACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	default:
		break;
	}

	return TRUE;
}

Proqramı işə salıb nəticələrə baxırıq.

DllMain funksiyası:

Zərərverici kitabxana legitim kitabxananın hansı funksiyaları export etdiyini görə bilər lakin export edilən funksiyanın nə etdiyini bilməsi olduqca çətindir. Legitim kitaxaba faylı-nın export etdiyi funksiya.

Lakin funksiya-nın tam olaraq nı etdityini bilmədiyini üçün zərərli kitabxana içərisində bu funksiyanı istifadə etmir. Əvəzində DllMain funksiyası içərisində zərərli kodları icra edir.

Kitabxana faylı yaddaşa yükləndiyi zaman DLL yükləyici ilk olaraq DllMain funksiyası içərisində yerləşən kodları icra etməyə başlayır. Buna dll entrypoint-də deyilir. Yaradılna hər proses və axın (thread) üçün DllMain funksiyası içərisində lazım olan kod blokları icra edilir. Ətraflı məlumat üçün:  https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain

Zərərli export edilən funksiyanı bilmədiyi üçün isə bu funksiya içərisində zərərli kodları icra edir.

DLL Proxying (yönləndirmə)

Yuxarıdakı örnək üzərindən gedərsək qeyd edildiyi kimi hər hansı bir kitabxana faylının zərərli alternativi ilə dəyişdirildiyi zaman əsas problem export edilən funksiyanın çağrılması prosesidir. Düzğün yazılmayan və ya çağrılmayan export funksiyası proqramda xəta baş verməsinə səbəb ola bilər. Bu hissədə istifadə edilən bir başqa metod kitabxana yönləndirmə faylıdır. Zərərverici topla funksiyasının hansı məqsədlə istifadə edildiyi bilmir. Lakin sözü gedən legitim kitabxana içərisində olan legitim funksiya-ya yönləndirmə edə bilər.

Yəni proqram bilmədən zərərli kitabxana içərisində topla funksiyasını çağırmağa cəhd edir lakin sözü gedən funksiya zərərli kitabxana içərisində olmadığı anda qarşı tərəfin şübhəsini çəkə bilər. Bu məqamda zərərli kitabxana öz içərisindən legitim fayla yönləndirmə edə bilər.

Bu ssenaridə zərərvericinin köməyinə kompilyatorun təqdim etdiyi funksionallıq gəlir.

Zərərverici ilk olaraq orijinal kitabxana faylını (mrl.dll) mrl_orijinal olaraq dəyişdirir və ona aid export edilən funksiya adlarının götürür (topla). Daha sonra isə özü hazırladığı zərərli mrl.dll kitabxana faylının cari qovluğa yerləşdirir. Zərərli kitabxana içərisindən isə mrl_orijinal kitabxanasına körpü yaradır.

mrl.c (legitim)

#define DLL_EXPORT __declspec(dllexport)

DLL_EXPORT int __cdecl topla(int a, int b)
{
	return a + b;
}

BOOL WINAPI DllMain(HINSTANCE hInst,
	DWORD fdwReason,
	LPVOID lpReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		printf("mrl.dll: Hello World!\n");
		break;
	case DLL_PROCESS_DETACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	default:
		break;
	}

	return TRUE;
}

mrl.c (zərərli)

#define DLL_EXPORT __declspec(dllexport)
#pragma comment(linker, "/export:topla=mrl_orijinal.topla")


BOOL WINAPI DllMain(HINSTANCE hInst,
	DWORD fdwReason,
	LPVOID lpReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		printf("Evil code executed\n");
		break;
	case DLL_PROCESS_DETACH:
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	default:
		break;
	}

	return TRUE;
}

Proqramı işə salaraq nəticəyə baxırıq.

DLL Search Order

Başlamazdan öncə kiçik bir test edək. Proqramın istifadə etdiyi mrl.dll kitabxanası-nı silirik. Pproqramı işə salaraq fayl aktivliklərinə baxaq.

Yəgin diqqətinizi cəlb etmişdir. Proqram mrl.dll kitabxana faylı tapılmadığı təqdirdə başqa qovluqlarda da sozü gedən kitabxana faylını axtarır. Microsft dəqiq kitabxana yolu verilmədiyi təqdirdə sözü gedən kitabxana faylını öncədən təyin edilmiş qaydalar əsasında bəzi qovluqlarda axtarmağa çalışır. Microsoft bunu aşağıdakı şəkildə sıralayıb (istisnalar üçün istinadlar bölməsinə baxın).

  1. The directory from which the application loaded
  2. The system directory
  3. The 16-bit system directory
  4. The Windows directory
  5. The current directory
  6. The directories that are listed in the PATH environment variable

Yəni proqramı kitabxananı yükləmə əmrini verdiyi zaman (LoadLibrary) sistem sözü gedən kitabxana faylını ilk öncə cari proqramın işə salındığı qovluqda axtarır. Əgər tapmırsa system qovluğunda axtarmağa başlayır. Axtarış əməliyyatı yuxarıdakı ardıcıllıq ilə davam etdirilir.

İlk ssenari: Zərərverici zərərli kitabxana faylını proqramın olduğu qovluğa yazmaq istəyir lakin buna səlahiyyəti yoxdur.

Əgər zərərvericinin proqramın qovluğuna yazmaq səlahiyyəti yoxdursa bu zaman zərərverici zərərli kitabxana faylını yazma səaliyyəti olan yuxarıda qeyd edilən qovluqlardan birinin içərisində saxlaya bilər. Kitabxana faylını tapmayan sistem, bu qovluqları gəzərək sonunda zərərverici kitabxana faylının olduğu qovluqdan zərərli kitabxana faylını proses yaddaşına yükləyə bilər.

Bir başqa metod isə axtarış siyahısında zərərli kitabxana faylını orijinal kitabxana faylının olduğu qovluqdan önə yerləşdirməkdir. Proqram özünə lazım olan kitabxana faylını C:\Windows\system qovluğunda saxlayır. Əgər zərərverici sözü gedən qovluqdan əvvəl yazmaq imtiyazi olduğu qovluğa zərərli kitabxananı yerləşdirə bilərsə bu zaman ƏS orijinal kitabxananın olduğu qovluqdan öncə gələn qovluqda kitabxananı axtaracağı üçün zərərli kitabxana proses yaddaşına ilk olaraq yükləcəcəkdir.

Gəlin 2 ədəd kitabxana faylını eyni adda lakin fərqli qovuqlara yerləşdirək. Orijinal yəni təmiz kitabxana faylını c:\Windows\system32 qovluğuna, digər zərərli kitabxana faylının isə axtarış siyasında c:\Windows\system32 qovluğundan əvvəl axtarılan qovluğa (C:\Windows\SysWOW64) yerləşdirək. Proqramı kitabxana olmadan işə salırıq:

Kitabxana fayllarını lazımı qovluqlara yerləşdirib yenidən işə salırıq.

Gördüyünüz kimi ƏS ilk öncə search order əsasında SysWOW64 qovluğunda olan zərərli mrl.dll kitabxanasını proses yaddaşına yüklədi. Bu tip halların qarşısını almaq üçün LoadLibary kimi funksiyalara kitabxana faylının dəqiq yolunu parametr olaraq göndərmək məsləhət görülür.

Known DLLs

Bəs əməliyyat sisteminə aid kritik kitabxanalar üzərində oxşar hücüm metodları istifdə edilə bilər?

Cavab: Bəli və Xeyr

ƏS-nin fəaliyyəti zamanı problem yarada biləcək kritik kitabxana fayllarına KnownDlls adı verilir. Sözü gedən kitabxana faylları xüsusi mexanizm ilə qorunur və yalnız tək bir qovluqdan yükləyici tərəfindən yaddaşa yüklənir. Not: - Bura sistemdə mövcud olan bütün kitabxana faylları aid deyil. Əgər LodLibrary funksiyası zamanı daxil edilən kitabxana bu siyahı içərisində mövcud deyilsə standart search order qaydaları axtarış zamanı tətbiq edilir. Əgər kitabxana fayl adı siyahı içərisində mövcud olarsa bu zaman sistem kitabxana faylının statik qovluqdan (əksər hallarda bu system32) proses yaddaşına yükləyir.

 

 

 

İstinadlar

[1] https://www.mandiant.com/resources/blog/abusing-dll-misconfigurations
[2] https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain
[3] https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-libraries
[4] https://learn.microsoft.com/en-us/windows/win32/dlls/about-dynamic-link-libraries
[5] https://attack.mitre.org/techniques/T1574/001/
[6] https://kevinalmansa.github.io/application security/DLL-Proxying/
[7] https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order

Press ESC to close