CreateRemoteThread函数进程创建之后注入DLL

本文参考前辈的文章https://www.cnblogs.com/wf751620780/,对原理有了很大了解

首先CreateRemoteThread函数的原型如下,它很像CreateThread函数。不同的是,前者是远程创建线程,后者是在自己的进程下创建线程。我们用前者来注入DLL:

HANDLE WINAPI CreateRemoteThread(
  _In_  HANDLE                 hProcess,
  _In_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  _In_  SIZE_T                 dwStackSize,
  _In_  LPTHREAD_START_ROUTINE lpStartAddress,
  _In_  LPVOID                 lpParameter,
  _In_  DWORD                  dwCreationFlags,
  _Out_ LPDWORD                lpThreadId
);

两个函数的区别就是第一个句柄行参,hProcess表示创建的新线程属于哪一个进程。

注入的过程如下:

(1).用VirtualAllocEx函数在目标进程的地址空间中分配一块足够大的内存用于保存被注入的dll的路径。
(2).用WriteProcessMemory函数把本进程中保存dll路径的内存中的数据拷贝到第(1)步得到的目标进程的内存中。
(3).用GetProcAddress函数获得LoadLibraryW函数的起始地址。LoadLibraryW函数位于Kernel32.dll中。
(4).用CreateRemoteThread函数让目标进程执行LoadLibraryW来加载被注入的dll。函数结束将返回载入dll后的模块句柄。
(5).用VirtualFreeEx释放第(1)步开辟的内存。
在需要卸载dll时我们可以在上述第(5)步的基础上继续执行以下步骤:
(6).用GetProcAddress函数获得FreeLibrary函数的起始地址。FreeLibrary函数位于Kernel32.dll中。
(7).用CreateRemoteThread函数让目标进程执行FreeLibrary来卸载被注入的dll。(其参数是第(4)步返回的模块句柄)。
如果不在上述步骤基础上执行操作,卸载dll时你需要这么做:
(1).获得被注入的dll在目标进程的模块句柄。
(2).重复上述步骤的第(6)、(7)两步。

需要明确几点,首先用的调用dll函数是LoadLibraryW,因为不管是LoadLibrary还是LoadLibraryA,翻译到底层用的都是宽字符函数LoadLibraryW。第二使用GetProcAddress获得LoadLibraryW函数起始位置。

第三,DLL的绝对路径需要放在用WriteProcessMemory写到目标程序的内存空间下面,而分配这个内存空间使用的函数是VirtualAllocEx

这两个函数原型是:

LPVOID WINAPI VirtualAllocEx(
  _In_     HANDLE hProcess,
  _In_opt_ LPVOID lpAddress,
  _In_     SIZE_T dwSize,
  _In_     DWORD  flAllocationType,
  _In_     DWORD  flProtect
);

BOOL WINAPI WriteProcessMemory(
  _In_  HANDLE  hProcess,
  _In_  LPVOID  lpBaseAddress,
  _In_  LPCVOID lpBuffer,
  _In_  SIZE_T  nSize,
  _Out_ SIZE_T  *lpNumberOfBytesWritten
);

运行环境win10+vs2019。代码如下:

#include "windows.h"
#include "stdio.h"
#include "tlhelp32.h"
#include "io.h"
#include "tchar.h"

//判断某模块(dll)是否在相应的进程中
//dwPID         进程的PID
//szDllPath     查询的dll的完整路径
BOOL CheckDllInProcess(DWORD dwPID, LPCTSTR szDllPath)
{
    BOOL                    bMore = FALSE;
    HANDLE                  hSnapshot = INVALID_HANDLE_VALUE;
    MODULEENTRY32           me = { sizeof(me), };

    if (INVALID_HANDLE_VALUE ==
        (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)))//获得进程的快照
    {
        _tprintf(L"CheckDllInProcess() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n",
            dwPID, GetLastError());
        return FALSE;
    }
    bMore = Module32First(hSnapshot, &me);//遍历进程内得的所有模块
    for (; bMore; bMore = Module32Next(hSnapshot, &me))
    {
        if (!_tcsicmp(me.szModule, szDllPath) || !_tcsicmp(me.szExePath, szDllPath))//模块名或含路径的名相符
        {
            CloseHandle(hSnapshot);
            return TRUE;
        }
    }
    CloseHandle(hSnapshot);
    return FALSE;
}

//向指定的进程注入相应的模块
//dwPID         目标进程的PID
//szDllPath     被注入的dll的完整路径
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
    HANDLE                  hProcess = NULL;//保存目标进程的句柄
    LPVOID                  pRemoteBuf = NULL;//目标进程开辟的内存的起始地址
    DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);//开辟的内存的大小
    LPTHREAD_START_ROUTINE  pThreadProc = NULL;//loadLibreayW函数的起始地址
    HMODULE                 hMod = NULL;//kernel32.dll模块的句柄
    BOOL                    bRet = FALSE;
    if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))//打开目标进程,获得句柄
    {
        _tprintf(L"目标进程打开失败  OpenProcess(%d)!!! [%d]\n",
            dwPID, GetLastError());
        goto INJECTDLL_EXIT;
    }
    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,
        MEM_COMMIT, PAGE_READWRITE);//在目标进程空间开辟一块内存
    if (pRemoteBuf == NULL)
    {
        _tprintf(L"分配空间失败VirtualAllocEx() failed!!! [%d]\n",
            GetLastError());
        goto INJECTDLL_EXIT;
    }
    if (!WriteProcessMemory(hProcess, pRemoteBuf,
        (LPVOID)szDllPath, dwBufSize, NULL))//向开辟的内存复制dll的路径
    {
        _tprintf(L"向目标空间复制路径失败 WriteProcessMemory() failed!!! [%d]\n",
            GetLastError());
        goto INJECTDLL_EXIT;
    }
    hMod = GetModuleHandle(L"kernel32.dll");//获得本进程kernel32.dll的模块句柄
    if (hMod == NULL)
    {
        _tprintf(L"InjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n",
            GetLastError());
        goto INJECTDLL_EXIT;
    }
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");//获得LoadLibraryW函数的起始地址
    if (pThreadProc == NULL)
    {
        _tprintf(L"InjectDll() : GetProcAddress(\"LoadLibraryW\") failed!!! [%d]\n",
            GetLastError());
        goto INJECTDLL_EXIT;
    }
    if (!CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL))//执行远程线程
    {
        _tprintf(L"InjectDll() : MyCreateRemoteThread() failed!!!\n");
        goto INJECTDLL_EXIT;
    }
INJECTDLL_EXIT:
    bRet = CheckDllInProcess(dwPID, szDllPath);//确认结果
    if (pRemoteBuf) {
        MessageBox(NULL,L"注入成功",L"注入成功",NULL);
        VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
    }
    if (hProcess)
        CloseHandle(hProcess);
    return bRet;
}

//让指定的进程卸载相应的模块
//dwPID         目标进程的PID
//szDllPath     被注入的dll的完整路径,注意:路径不要用“/”来代替“\\”
BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
    BOOL                    bMore = FALSE, bFound = FALSE, bRet = FALSE;
    HANDLE                  hSnapshot = INVALID_HANDLE_VALUE;
    HANDLE                  hProcess = NULL;
    MODULEENTRY32           me = { sizeof(me), };
    LPTHREAD_START_ROUTINE  pThreadProc = NULL;
    HMODULE                 hMod = NULL;
    TCHAR                   szProcName[MAX_PATH] = { 0, };
    if (INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)))
    {
        _tprintf(L"EjectDll() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n",
            dwPID, GetLastError());
        goto EJECTDLL_EXIT;
    }
    bMore = Module32First(hSnapshot, &me);
    for (; bMore; bMore = Module32Next(hSnapshot, &me))//查找模块句柄
    {
        if (!_tcsicmp(me.szModule, szDllPath) ||
            !_tcsicmp(me.szExePath, szDllPath))
        {
            bFound = TRUE;
            break;
        }
    }
    if (!bFound)
    {
        _tprintf(L"EjectDll() : There is not %s module in process(%d) memory!!!\n",
            szDllPath, dwPID);
        goto EJECTDLL_EXIT;
    }
    if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
    {
        _tprintf(L"EjectDll() : OpenProcess(%d) failed!!! [%d]\n",
            dwPID, GetLastError());
        goto EJECTDLL_EXIT;
    }
    hMod = GetModuleHandle(L"kernel32.dll");
    if (hMod == NULL)
    {
        _tprintf(L"EjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n",
            GetLastError());
        goto EJECTDLL_EXIT;
    }
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "FreeLibrary");
    if (pThreadProc == NULL)
    {
        _tprintf(L"EjectDll() : GetProcAddress(\"FreeLibrary\") failed!!! [%d]\n",
            GetLastError());
        goto EJECTDLL_EXIT;
    }
    if (!CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL))
    {
        _tprintf(L"EjectDll() : MyCreateRemoteThread() failed!!!\n");
        goto EJECTDLL_EXIT;
    }
    bRet = TRUE;
EJECTDLL_EXIT:
    if (hProcess)
        CloseHandle(hProcess);
    if (hSnapshot != INVALID_HANDLE_VALUE)
        CloseHandle(hSnapshot);
    return bRet;
}

int main()
{
    InjectDll(19220, L"S:\\panny_dll.dll");
    EjectDll(19220, L"S:\\panny_dll.dll");
    return 0;
}

我们启动一个demo并获得它的pid:

然后获得我们需要注入的DLL的绝对路径,开始攻击:

用的查询注入是否成功的方法是用进程快照搜索进程空间是否有目标dll的方式,同反调试技术,运行就会弹出注入成功框:

同时Process Explore可以看到目标dll:

猜你喜欢

转载自www.cnblogs.com/jentleTao/p/12728142.html