Як написати простий інжектор DLL на C

Як написати інжектор DLL на C?

Інжекція DLL — це найпоширеніший спосіб змінити виконуваний файл (.exe) під час його роботи. Нижче наведено пояснення того, як написати інжектор DLL на мові програмування C.

Повний код для інжектора DLL на C (пояснення нижче)

// Написано [email protected]  
#include   
#include   

int main() {  
 STARTUPINFOA StartInfo = { sizeof(STARTUPINFOA) };  
 PROCESS_INFORMATION ProcessInfo = { 0 };  

 // Визначимо шлях до цільового виконуваного файлу  
 LPCSTR targetPath = "C:\\Users\\targetprocess.exe";  
 // Створимо цільовий процес в призупиненому стані  
 BOOL success = CreateProcessA(  
 targetPath, NULL, NULL, NULL, FALSE,  
 CREATE_SUSPENDED, NULL, NULL, &StartInfo, &ProcessInfo  
 );  
 if (!success) {  
 printf("Не вдалося створити процес!\n");  
 return 1;  
 }  

 // Визначимо шлях до спільної бібліотеки (DLL)  
 LPCSTR libraryPathUsers\\dlltoinject.dll";  

 // Отримаємо дескриптор модуля kernel32.dll  
 HMODULE kernel32Handle = GetModuleHandleA("kernel32.dll");  
 if (kernel32Handle == NULL) {  
 printf("Помилка при отриманні дескриптора kernel32.\n");  
 return 1;  
 }  

 // Отримаємо адресу функції LoadLibraryA  
 FARPROC loadLibraryAddr = GetProcAddress(kernel32Handle, "LoadLibraryA");  
 if (loadLibraryAddr == NULL) {  
 printf("Не вдалося знайти LoadLibraryA.\n");  
 return 1;  
 }  

 // Виділимо пам'ять в цільовому процесі для шляху до бібліотеки  
 LPVOID remoteMemory = VirtualAllocEx(  
 ProcessInfo.hProcess, NULL, strlen(libraryPath) + 1,  
 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE  
 );  
 if (remoteMemory == NULL) {  
 printf("Не вдалося виділити пам'ять в цільовому процесі.\n");  
 return 1;  
 }  

 // Запишемо шлях до бібліотеки у виділену пам'ять в цільовому процесі  
 BOOL memoryWritten = WriteProcessMemory(  
 ProcessInfo.hProcess, remoteMemory,  
 libraryPath, strlen(libraryPath) + 1, NULL  
 );  
 if (!memoryWritten) {  
 printf("Не вдалося записати в пам'ять процесу.\n");  
 return 1;  
 }  

 // Створимо віддалений потік, який викликає LoadLibraryA з шляхом до бібліотеки  
 HANDLE remoteThread = CreateRemoteThread(  
 ProcessInfo.hProcess, NULL, 0,  
 (LPTHREAD_START_ROUTINE)loadLibraryAddr, remoteMemory, 0, NULL  
 );  
 if (remoteThread == NULL) {  
 printf("Не вдалося створити віддалений потік.\n");  
 return 1;  
 } else {  
 // Чекаємо завершення віддаленого потоку  
 WaitForSingleObject(remoteThread, INFINITE);  
 CloseHandle(remoteThread);  
 }  

 // Продовжимо виконання основного потоку цільового процесу  
 ResumeThread(ProcessInfo.hThread);  

 // Очистимо дескриптори  
 CloseHandle(ProcessInfo.hThreadn");  
 return 0;  
}

Пояснення крок за кроком

Давайте розберемо код, щоб зрозуміти кожну частину детально.

1. Підключення необхідних заголовків

Ми підключаємо стандартні заголовки для вводу-виводу та заголовки Windows API для необхідних функцій та типів.

#include    
#include 

2. Ініціалізація структур інформації про процес

Ми ініціалізуємо STARTUPINFOA та PROCESS_INFORMATION, які необхідні для створення та управління цільовим процесом.

STARTUPINFOA StartInfo = { sizeof(STARTUPINFOA) };  
PROCESS_INFORMATION ProcessInfo = { 0 };

3. Визначення шляху та створення цільового процесу

Ми вказуємо шлях до цільового виконуваного файлу та використовуємо CreateProcessA для запуску процесу в призупиненому стані. Це дозволяє нам маніпулювати процесом до того, як він почне виконання.

// Визначимо шлях до цільового виконуваного файлу  
LPCSTR targetPath = "C:\\Users\\targetprocess.exe";  
// Створимо цільовий процес в призупиненому стані  
BOOL success = CreateProcessA(  
 targetPath, NULL, NULL, NULL, FALSE,  
 CREATE_SUSPENDED, NULL, NULL, &StartInfo, &ProcessInfo  
);  
if (!success) {  
 printf("Не вдалося створити процес!\n");  
 return 1;  
}

## Визначення шляху до DLL та отримання дескриптора kernel32

Ми встановлюємо шлях до спільної бібліотеки (DLL), яку хочемо завантажити, та отримуємо дескриптор для `kernel32.dll`, який містить функцію `LoadLibraryA`.

// Визначимо шлях до спільної бібліотеки (DLL)
LPCSTR libraryPath = "C:\Users\dlltoinject";

// Отримаємо дескриптор модуля kernel32.dll
HMODULE kernel32Handle = GetModuleHandleA("kernel32.dll");
if (kernel32Handle == NULL) {
printf("Помилка при отриманні дескриптора kernel32.\n");
return 1;
}
```

5. Отримання адреси LoadLibraryA

Ми отримуємо адресу функції LoadLibraryA в kernel32.dll, використовуючи GetProcAddress.

// Отримуємо адресу функції LoadLibraryA  
FARPROC loadLibraryAddr = GetProcAddress(kernel32Handle, "LoadLibraryA");  
if (loadLibraryAddr == NULL) {  
 printf("Не вдалося знайти LoadLibraryA.\n");  
 return 1;  
}

6. Виділення пам'яті в цільовому процесі

Ми виділяємо пам'ять в адресному просторі цільового процесу для зберігання шляху до DLL. Для цього використовуємо VirtualAllocEx.

// Виділяємо пам'ять у цільовому процесі для шляху до бібліотеки  
LPVOID remoteMemory = VirtualAllocEx(  
 ProcessInfo.hProcess, NULL, strlen(libraryPath) + 1,  
 MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE  
);  
if (remoteMemory == NULL) {  
 printf("Не вдалося виділn");  
 return 1;  
}

7. Запис шляху до DLL в виділену пам'ять

Ми записуємо шлях до DLL у виділену пам'ять цільового процесу за допомогою WriteProcessMemory.

// Записуємо шлях до бібліотеки у виділену пам'ять в цільовому процесі  
BOOL memoryWritten = WriteProcessMemory(  
 ProcessInfo.hProcess, remoteMemory,  
 libraryPath, strlen(libraryPath) + 1,n");  
 return 1;  
}

8. Створення віддаленого потоку для завантаження спільної бібліотеки

Ми створюємо віддалений потік у цільовому процесі, який викликає LoadLibraryA з шляхом до бібліотеки. Це ефективно завантажує спільну бібліотеку в цільовий процес.

// Створюємо віддалений потік, який викликає LoadLibraryA з шляхом до бібліотеки  
HANDLE remoteThread = CreateRemoteThread(  
 ProcessInfo.hProcess, NULL, 0,  
 (LPTHREAD_START_ROUTINE)loadLibraryAddr, remoteMemory, 0, NULL  
);  
if (remoteThread == NULL) {  
 printf("Не вдалося створити віддалений потік.\n");  
 return 1;  
} else {  
 // Чекаємо завершення віддаленого потоку  
 WaitForSingleObject(remoteThread, INFINITE);  
 CloseHandle(remoteThread);  
}

9. Очистка та відновлення цільового процесу

Після запуску віддаленого потоку ми закриваємо дескриптори потоку та процесу. Наприкінці відновлюємо цільовий процес, щоб він продовжив виконуватися.

// Відновлюємо основний потік цільового процесу  
ResumeThread(ProcessInfo.hThread);  

// Очистка дескрипторів  
CloseHandle(ProcessInfo.hThread);  
CloseHandle(ProcessInfo.hProcess);  

printf("Спільну бібліотеку успішно завантажено.\n");

Давайте перевіримо, чи це працює:

pic

Вітаємо!

Щоб використати цей простий інжектор, додайте код C до вашого проєкту в Visual Studio. Зовнішні бібліотеки не потрібні — просто встановіть шляхи до вашого цільового виконуваного файлу та DLL у скрипті. І все! Не соромтеся ставити питання, якщо вони виникнуть.

Перекладено з: How to write a simple DLL injector in C

Leave a Reply

Your email address will not be published. Required fields are marked *