2022-02-20注入0
请注意,本文编写于 584 天前,最后修改于 506 天前,其中某些信息可能已经过时。

说起远程线程注入,首先要了解远程线程的一个概念,我们每一个进程中都有很多的线程,如果要在本进程内创建一个线程就可以使用CreateThread

c
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
  SIZE_T dwStackSize,                       // initial stack size
  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
  LPVOID lpParameter,                       // thread argument
  DWORD dwCreationFlags,                    // creation option
  LPDWORD lpThreadId                        // thread identifier
);

那么相对应的如果要在其他进程内部创建一个线程,Windows提供了CreateRemoteThread函数,这个函数除了hProcess之外,其他参数与CreateThread完全相同。

c
HANDLE CreateRemoteThread(
  HANDLE hProcess,                          // handle to process
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
  SIZE_T dwStackSize,                       // initial stack size
  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
  LPVOID lpParameter,                       // thread argument
  DWORD dwCreationFlags,                    // creation option
  LPDWORD lpThreadId                        // thread identifier
);

另外远程线程注入需要在目标进程中的一个线程调用LoadLibrary来载入我们想要的Dll。但由于我们不能轻易控制别人进程中的线程,所以这种方法要求我们在目标进程中创建一个线程,由于这个线程完全是由我们来创建的,所以我们就可以执行代码了。
hProcess用来表示新创建的线程归哪个进程所有。那线程创建完了,怎么样让这个线程去执行LoadLibrary呢?
CreateRemoteThread函数的lpStartAddress参数是线程回调函数的内存地址。

观察一下lpStartAddressLoadLibrary

lpStartAddress

c
DWORD WINAPI ThreadProc(
    LPVOID lpParameter   // thread data
);

LoadLibrary

c
    HMODULE LoadLibrary(LPCTSTR lpFileName   // file name of module
);

都是4个字节,很巧合,而这个巧合就可以让我们把CreateRemoteThread函数的lpStartAddress参数填成LoadLibrary,CreateRemoteThread函数的lpParameter参数填成我们的dll路径,那么线程一跑,LoadLibrary就被调用,我们的dll自然就加载进目标进程了。

但是我们还缺少LoadLibrary的参数怎么办,Windows为我们提供了VirtualAllocEx函数,他可以让一个进程在另一个进程中分配内存:

c
LPVOID VirtualAllocEx(
    HANDLE hProcess,          // process to allocate memory
    LPVOID lpAddress,         // desired starting address
    SIZE_T dwSize,            // size of region to allocate
    DWORD flAllocationType,   // type of allocation
    DWORD flProtect           // type of access protection
);

申请到空间后,我们就需要使用WriteProcessMemory把我们的dll路径写进目标进程中。

c
BOOL WriteProcessMemory(
  [in]  HANDLE  hProcess,
  [in]  LPVOID  lpBaseAddress,
  [in]  LPCVOID lpBuffer,
  [in]  SIZE_T  nSize,
  [out] SIZE_T  *lpNumberOfBytesWritten
);

接着我们调用CreateRemoteThread是将申请到的空间地址作为参数传进去就ok了

上面就是远程线程注入的基本知识点,接着上代码

c
# include <iostream>
# include <windows.h>
using namespace std;


int main()
{
    //获取进程句柄
    DWORD dwProcId = 0;
    HWND hWndCalc = ::FindWindow(NULL, "计算器");
    ::GetWindowThreadProcessId(hWndCalc, &dwProcId);
    HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcId);

    //在目标进程中申请一块内存,用来存储dll的路径
    char szDllPath[] = { "E:\\Na1r\\windows\\12\\Dll1\\Debug\\Dll1.dll" };
    LPVOID pBuff = VirtualAllocEx(
        hProc,
        NULL, //系统自动分配地址
        sizeof(szDllPath),
        MEM_COMMIT,
        PAGE_READWRITE
    );
    DWORD dwBytesWrited = 0;
    //写入dll路径
    BOOL bRet = WriteProcessMemory(
        hProc,
        pBuff,
        szDllPath,
        sizeof(szDllPath),
        &dwBytesWrited);


    auto pfnLoadLibrary = GetProcAddress(
        GetModuleHandle("Kernel32"),
        "LoadLibraryA");
    //创建远程线程
    HANDLE hThread = CreateRemoteThread(
        hProc,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)pfnLoadLibrary,
        pBuff,
        0,
        NULL);
    //退出
    WaitForSingleObject(hThread, INFINITE);

    HMODULE hModDll1 = NULL;
    GetExitCodeThread(hThread, (PDWORD)&hModDll1);

    auto pfnFreeLibrary = GetProcAddress(
        GetModuleHandle("Kernel32"),
        "FreeLibrary");
    HANDLE hThreadFree = CreateRemoteThread(
        hProc,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)pfnFreeLibrary,
        hModDll1,
        0,
        NULL);

    //释放句柄
	CloseHandle(hProc);
	CloseHandle(hThread);

    return 0;
}

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!