DLL инъекция дает возможность выполнять свой код в адресном пространстве уже запущенного процесса. Многие используют инфицирования для написания читов для игр, выполнения вредоносных действий для системы и т.п. Но данный прием не обязательно применять для реализации коварных планов, а например, для обновления своего приложения.
Алгоритм работы очень просто, нам нужно создать поток в процессе и внедрить в него выполнения нашего кода. Для примера, мы инфицируем explorer.exe и выведем сообщение об этом.
Опишем структуру, через которую мы получим необходимые нам данные:
Теперь опишем точку входа нашего потока:
В нашем примере она довольно таки проста. В нем мы не выполняем подгрузку DLL, хотя для большинства задач вам это может быть необходимо, для этого необходимо передать указатели на ф-ции LoadLibrary и GetProcAddress, также как мы это делам для MessageBoxA, и при помощи их подгружать необходимые вам DLL.
Теперь нам нужно получить доступ к explorer.exe, записать наш код, данные в адресном пространстве процесса и создать поток в процессе для выполнения нашего кода.
Опишем ф-цию которая возвращает идентификатор процесса:
CreateToolhelp32Snapshot — возвращает нам фактически список процессов и их потоков. Обходим весь список и если найден наш процесс, то возвращаем его идентификатор или 0. Теперь, когда у нас есть идентификатор, мы можем получить доступ к процессу при помощи OpenProcess, но не сможем ни чего записать в его память. Для того, что бы наше приложение получило права, нам понадобиться следующая ф-ция:
Подробней о правах можете почитать здесь . Не смотря на то, что ответа за 1998 год он еще актуален для XP SP3 и насколько я знаю, для Windows 7, хотя лично еще не тестил.
Теперь у нас есть все для того, что бы получить доступ к процессу:
Нам не хватает указателя на ф-цию MessageBoxA, которая находиться в user32.dll:
Ну что ж, перейдем теперь к самому интересному, собственно к инфицированию, запишем наш данный и код в память и создадим поток, который все это запустит. Для модифицирования памяти нам понадобиться две ф-ции: VirtualAllocEx и WriteProcessMemory.
VirtualAllocEx — предоставляет физическую память в виртуальном адресном пространстве процесса, а WriteProcessMemory записывает наши данные в память процесса.
Теперь создадим поток в процессе, который воплотит наш коварный план в жизнь:
Вот исходник для полной картинки, повторюсь, что я не тестил под Window 7, но уверен, что тоже должен работать. Правда интересно, как поведет себя их новый firewall, в Windows XP он не определил изменения памяти. Данному методу не страшны антивирусники, ее враг только firewall, так как они оповещают о попытках изменения памяти. Но как показывает практика, многие забивают на такие сообщения, если еще и имя приложению, которое инфицирует, дать нормальное, то даже продвинутые пользователи пропускают, если конечно firewall не стоит в паранойном режиме.
Алгоритм работы очень просто, нам нужно создать поток в процессе и внедрить в него выполнения нашего кода. Для примера, мы инфицируем explorer.exe и выведем сообщение об этом.
Опишем структуру, через которую мы получим необходимые нам данные:
typedef FARPROC (WINAPI *LPMessageBox)(HWND, LPCWSTR, LPCWSTR, UINT);
typedef struct _InjectData {
char title[50];
char msg[50];
LPMessageBox MessageB;
} InjectData, *PInjectData;
InjectData injectData = {
"Test",
"Привет",
NULL
};
Теперь опишем точку входа нашего потока:
static DWORD WINAPI InjectionMain(LPVOID lpParams) {
PInjectData info = (PInjectData)lpParams;
info->MessageB(NULL, (LPCWSTR)info->msg, (LPCWSTR)info->title, MB_OK);
return 0;
}
В нашем примере она довольно таки проста. В нем мы не выполняем подгрузку DLL, хотя для большинства задач вам это может быть необходимо, для этого необходимо передать указатели на ф-ции LoadLibrary и GetProcAddress, также как мы это делам для MessageBoxA, и при помощи их подгружать необходимые вам DLL.
Теперь нам нужно получить доступ к explorer.exe, записать наш код, данные в адресном пространстве процесса и создать поток в процессе для выполнения нашего кода.
Опишем ф-цию которая возвращает идентификатор процесса:
DWORD getProcessID() {
DWORD processID = 0;
HANDLE snapHandle;
PROCESSENTRY32 processEntry = {0};
if( (snapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE ) {
return 0;
}
processEntry.dwSize = sizeof(PROCESSENTRY32);
Process32First(snapHandle, &processEntry);
do {
if ( wcscmp(processEntry.szExeFile, PROCESSNAME) == 0 ) {
return processEntry.th32ProcessID;
}
} while (Process32Next(snapHandle,&processEntry));
if ( snapHandle != INVALID_HANDLE_VALUE ) {
CloseHandle(snapHandle);
}
return 0;
}
CreateToolhelp32Snapshot — возвращает нам фактически список процессов и их потоков. Обходим весь список и если найден наш процесс, то возвращаем его идентификатор или 0. Теперь, когда у нас есть идентификатор, мы можем получить доступ к процессу при помощи OpenProcess, но не сможем ни чего записать в его память. Для того, что бы наше приложение получило права, нам понадобиться следующая ф-ция:
BOOL setPrivilege(HANDLE hToken, LPCTSTR szPrivName, BOOL fEnable) {
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, szPrivName, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
return((GetLastError() == ERROR_SUCCESS));
}
Подробней о правах можете почитать здесь . Не смотря на то, что ответа за 1998 год он еще актуален для XP SP3 и насколько я знаю, для Windows 7, хотя лично еще не тестил.
Теперь у нас есть все для того, что бы получить доступ к процессу:
DWORD processID = getProcessID();
HANDLE hCurrentProc = GetCurrentProcess();
if(!OpenProcessToken(hCurrentProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
addLogMessage("OpenProcessToken Error", GetLastError());
return 0;
} else {
if (!setPrivilege(hToken, SE_DEBUG_NAME, TRUE)) {
addLogMessage("SetPrivlegesSE_DEBUG_NAME Error", GetLastError());
return 0;
}
}
if(processID == 0) {
MessageBox(NULL, _T("Process not found!"), _T("Error"), MB_OK | MB_ICONERROR);
return 0;
}
processHandel = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
Нам не хватает указателя на ф-цию MessageBoxA, которая находиться в user32.dll:
HINSTANCE userHinstance = LoadLibrary(_T("user32.dll"));
injectData.MessageB = (LPMessageBox) GetProcAddress(userHinstance, "MessageBoxA");
Ну что ж, перейдем теперь к самому интересному, собственно к инфицированию, запишем наш данный и код в память и создадим поток, который все это запустит. Для модифицирования памяти нам понадобиться две ф-ции: VirtualAllocEx и WriteProcessMemory.
LPVOID lpProc = VirtualAllocEx(processHandel, NULL, ProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
LPVOID lpParams = VirtualAllocEx(processHandel, NULL, 1024, MEM_COMMIT, PAGE_READWRITE );
DWORD dwWritten;
if(WriteProcessMemory(processHandel, lpProc, InjectionMain, ProcSize, &dwWritten ) == 0) {
addLogMessage("WriteProcessMemory error", GetLastError());
return 0;
}
if(WriteProcessMemory( processHandel, lpParams, &injectData, sizeof(injectData), &dwWritten ) == 0) {
addLogMessage("WriteProcessMemory error", GetLastError());
return 0;
}
VirtualAllocEx — предоставляет физическую память в виртуальном адресном пространстве процесса, а WriteProcessMemory записывает наши данные в память процесса.
Теперь создадим поток в процессе, который воплотит наш коварный план в жизнь:
DWORD ThreadID;
HANDLE hThread = CreateRemoteThread(processHandel, NULL, 0, (LPTHREAD_START_ROUTINE)lpProc, lpParams, 0, &ThreadID);
if (hThread == NULL) {
sprintf_s(buffer, "Error creating thread");
addLogMessage(buffer, 1001);
}
Вот исходник для полной картинки, повторюсь, что я не тестил под Window 7, но уверен, что тоже должен работать. Правда интересно, как поведет себя их новый firewall, в Windows XP он не определил изменения памяти. Данному методу не страшны антивирусники, ее враг только firewall, так как они оповещают о попытках изменения памяти. Но как показывает практика, многие забивают на такие сообщения, если еще и имя приложению, которое инфицирует, дать нормальное, то даже продвинутые пользователи пропускают, если конечно firewall не стоит в паранойном режиме.