每日总结-第三十八天-代码注入

2020-05-20  本文已影响0人  SamiraG

代码注入是一种向目标进程插入独立运行代码并使之运行的技术,一般调用CreateRemoteThread()API以远程线程形式运行插入的代码,所以也被称为线程注入。
首先向目标进程插入代码和数据,在此过程中,代码以线程过程形式插入,而代码中使用的数据则以线程参数的形式传入,也就是说代码与数据是分别注入的。

// CodeInjection.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "windows.h"
#include "stdio.h"
#include "windef.h"
typedef struct _THREAD_PARAM
{
    //FARPROC是一个(int FAR WINAPI*)()类型的指针
    FARPROC pFunc[2];  // LoadLibraryA(), GetProcAddress()
    char szBuf[4][128];  // "user32.dll", "MessageBoxA",
                         // "www.reversecore.com", "ReverseCore"
} THREAD_PARAM, *PTHREAF_PARAM;

// LoadLibraryA() 函数指针PFLOADLIBRARYA
typedef HMODULE (WINAPI *PFLOADLIBRARYA)(LPCSTR lpLibFileName);

// GetProcAddress()
typedef FARPROC (WINAPI *PFGETPROCADDRESS)
(
    HMODULE hModule,
    LPCSTR lpProcName
);

// MessageBoxA()
typedef int (WINAPI *PFMESSAGEBOXA)
(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType
);

// Thread Procedure
DWORD WINAPI ThreadProc(LPVOID lParam)
{
    PTHREAF_PARAM pParam = (PTHREAF_PARAM)lParam;
    HMODULE hMod = NULL;
    FARPROC pFunc = NULL;

    // LoadLibraryA("user32.dll")
    // pParam->pFunc[0] -> kernel32!LoadLibraryA()
    // pParam->szBuf[0] -> "user32.dll"
    hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);

    // GetProcAddress("MessageBoxA")
    // pParam->pFunc[1] -> kernel32!GetProcAddress()
    // pParam->szBuf[1] -> "MessageBoxA"
    pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, 
        pParam->szBuf[1]);

    // MessageBoxA(NULL, "www...", "ReverseCore", MB_OK)
    // pParam->szBuf[2] = "www..."
    // pParam->szBuf[3] = "ReverseCore"
    ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);

    return 0;
}

BOOL InjectCode(DWORD dwPID)
{
    HMODULE hMod = NULL;
    THREAD_PARAM param = { 0, };
    HANDLE hProcess = NULL;
    HANDLE hThread = NULL;
    LPVOID pRemoteBuf[2] = { 0, };
    DWORD dwSize = 0;

    hMod = GetModuleHandleA("kernel32.dll");

    param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
    param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
    strcpy_s(param.szBuf[0], "user32.dll");
    strcpy_s(param.szBuf[1], "MessageBoxA");
    strcpy_s(param.szBuf[2], "www.reversecore.com");
    strcpy_s(param.szBuf[3], "ReverseCore");

    // OpenProcess
    hProcess = OpenProcess(PROCESS_ALL_ACCESS,
        FALSE,
        dwPID);

    // Allocation for THREAD_PRARM
    dwSize = sizeof(THREAD_PARAM);
    pRemoteBuf[0] = VirtualAllocEx(hProcess, 
        NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
    if (pRemoteBuf[0] == NULL)
    {
        printf("VirtualAllocEx failed\n");
        return FALSE;
    }
    if (!WriteProcessMemory(hProcess,
        pRemoteBuf[0], (LPVOID)&param, dwSize, NULL))
    {
        printf("WriteProcessMemory failed\n");
        return FALSE;
    }

    // Allocation for ThreadProc
    dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
    printf("dwSize: %d\n", dwSize);
    pRemoteBuf[1] = VirtualAllocEx(hProcess, NULL, dwSize,
        MEM_COMMIT, PAGE_EXECUTE_READWRITE);  // 这里注意要有可执行权限
    if (pRemoteBuf[1] == NULL)
    {
        printf("VirtualAllocEx failed\n");
        return FALSE;
    }
    if (!WriteProcessMemory(hProcess, pRemoteBuf[1],
        (LPVOID)ThreadProc, dwSize, NULL))
    {
        printf("WriteProcessMemory failed\n");
        return FALSE;
    }

    hThread = CreateRemoteThread(hProcess,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)pRemoteBuf[1],
        pRemoteBuf[0],
        0,
        NULL);
    if (hThread == NULL)
    {
        printf("CreateRemoteThread failed\n");
        return FALSE;
    }

    WaitForSingleObject(hThread, INFINITE);

    CloseHandle(hThread);
    CloseHandle(hProcess);

    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD dwPID = 0;

    if (argc != 2)
    {
        printf("\n usage: %s PID\n", argv[0]);
        return 1;
    }

    dwPID = (DWORD)atol(argv[1]);
    InjectCode(dwPID);

    return 0;
}

执行的时候注意要生成release版本,因为MS Virual C++中使用Release模式编译程序代码后,源代码中函数顺序与二进制代码中的顺序是一致的,所以代码中的InjectCode-ThreadProc才可以表示ThreadProc函数的大小。
将PID设置成notepad.exe的PID时,结果如下:

上一篇下一篇

猜你喜欢

热点阅读