使用CreateRemoteThread注入DLL

DLL:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
    /* open file */
    FILE *file;
    fopen_s(&file, "D:\Case Folders\2019-11-27\CreateRemoteThread\temp.txt", "a+");

    switch (Reason) {
    case DLL_PROCESS_ATTACH:
        fprintf(file, "DLL attach function called.
");
        break;
    case DLL_PROCESS_DETACH:
        fprintf(file, "DLL detach function called.
");
        break;
    case DLL_THREAD_ATTACH:
        fprintf(file, "DLL thread attach function called.
");
        break;
    case DLL_THREAD_DETACH:
        fprintf(file, "DLL thread detach function called.
");
        break;
    }

    /* close file */
    fclose(file);

    return TRUE;
}

CreateRemoteThread program:

#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <TlHelp32.h>
#include <tchar.h>

bool Inject(DWORD pId, const char *dllName)
{
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pId);
    if (h)
    {
        LPVOID LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        LPVOID dereercomp = VirtualAllocEx(h, NULL, strlen(dllName), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        WriteProcessMemory(h, dereercomp, dllName, strlen(dllName), NULL);
        HANDLE asdc = CreateRemoteThread(h, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, dereercomp, 0, NULL);
        if (asdc == NULL) {
            printf("Error: the remote thread could not be created.
");
        }
        else {
            printf("Success: the remote thread was successfully created.
");
        }
        WaitForSingleObject(asdc, INFINITE);
        VirtualFreeEx(h, dereercomp, strlen(dllName), MEM_RELEASE);
        CloseHandle(asdc);
        CloseHandle(h);
        return true;
    }
    return false;
}
int _tmain(int argc, _TCHAR* argv[]) {
    const char* buffer = "D:\Case Folders\2019-11-27\CreateRemoteThread\inject\Debug\inject.dll";

    /*
    * Get process handle passing in the process ID.
    */
    int procID = 26824;
    Inject(26824, "D:\Case Folders\2019-11-27\CreateRemoteThread\inject\Debug\inject.dll");
    //HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
    //if (process == NULL) {
    //    printf("Error: the specified process couldn't be found.
");
    //}

    ///*
    //* Get address of the LoadLibrary function.
    //*/
    //LPVOID addr = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
    //if (addr == NULL) {
    //    printf("Error: the LoadLibraryA function was not found inside kernel32.dll library.
");
    //}

    ///*
    //* Allocate new memory region inside the process's address space.
    //*/
    //LPVOID arg = (LPVOID)VirtualAllocEx(process, NULL, strlen(buffer), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    //if (arg == NULL) {
    //    printf("Error: the memory could not be allocated inside the chosen process.
");
    //}

    ///*
    //* Write the argument to LoadLibraryA to the process's newly allocated memory region.
    //*/
    //int n = WriteProcessMemory(process, arg, buffer, strlen(buffer), NULL);
    //if (n == 0) {
    //    printf("Error: there was no bytes written to the process's address space.
");
    //}

    ///*
    //* Inject our DLL into the process's address space.
    //*/
    //HANDLE threadID = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)addr, arg, NULL, NULL);
    //int err = GetLastError();
    //if (threadID == NULL) {
    //    printf("Error: the remote thread could not be created.
");
    //}
    //else {
    //    printf("Success: the remote thread was successfully created.
");
    //}

    /*
    * Close the handle to the process, becuase we've already injected the DLL.
    */
    //CloseHandle(process);
    getchar();

    return 0;
}

检查被插入的进程是否包含inject.dll

#include <windows.h>
#include <Tlhelp32.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > tstring;


int ProcessModule(DWORD);
int CheckProcessModule(DWORD pid);
BOOL IsModuleValid(tstring szModuleName);
int dwCount = 0;
vector<tstring> patch;
vector<tstring> checkpatch;

int main(void)
{


    //进程创建完毕后的模块快照
    ProcessModule(26824);
    cout << "******************当前模块*****************" << endl;
    for (int i = 0; i < patch.size(); i++)
    {
        cout << patch[i].c_str() << endl;
    }
    cout << endl << endl;

    LoadLibrary(TEXT("user32.dll"));//加载user32.dll测试


    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);

    //检测是否存在不同的模块
//    CheckProcessModule(GetCurrentProcessId());
    cout << "******************检测模块*****************" << endl;
    for (int j = 0; j < checkpatch.size(); j++)
    {
        cout << checkpatch[j].c_str() << endl;;
    }
    cout << endl << endl;
    if (patch.size() == checkpatch.size())
    {
        cout << "没有检测到注入模块" << endl;
    }


    return 0;
}


//获取进程模块
int ProcessModule(DWORD pid)
{

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (hProcessSnap)
    {
        MODULEENTRY32 me32;
        me32.dwSize = sizeof(MODULEENTRY32);
        Module32First(hProcessSnap, &me32);//获取进程第一个模块信息
        do
        {
            patch.push_back(me32.szModule);
            //printf("模块路径:%s
",me32.szExePath);
            //printf("模块名:%s
",me32.szModule);
            //printf("模块基址:0x%08X
",(DWORD)me32.modBaseAddr);

        } while (Module32Next(hProcessSnap, &me32));
        CloseHandle(hProcessSnap);
        return 0;
    }
    else
    {
        cout << "获取进程快照失败" << endl;;
        return 0;
    }
    return 0;
}

int CheckProcessModule(DWORD pid)
{

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    if (hProcessSnap)
    {
        MODULEENTRY32 me32;
        me32.dwSize = sizeof(MODULEENTRY32);
        Module32First(hProcessSnap, &me32);//获取进程第一个模块信息
        do
        {
            checkpatch.push_back(me32.szModule);
            if (!IsModuleValid(me32.szModule))
            {
                cout << "[可疑模块]:" << me32.szExePath << endl;
                dwCount++;
            }

            //printf("模块路径:%s
",me32.szExePath);
            //printf("模块名:%s
",me32.szModule);
            //printf("模块基址:0x%08X
",(DWORD)me32.modBaseAddr);

        } while (Module32Next(hProcessSnap, &me32));
        CloseHandle(hProcessSnap);
        if (dwCount)
        {
            cout << "可疑模块数:" << dwCount << endl;
        }
        return 0;
    }
    else
    {
        cout << "获取进程快照失败" << endl;
        return 0;
    }
    return 0;
}


BOOL IsModuleValid(tstring szModuleName)
{
    // 遍历起始状态的模块列表
    for (int i = 0; i < patch.size(); i++)
    {
        if (patch[i] == szModuleName)
            return TRUE;
    }
    return FALSE;

}

 部分解释:

介绍将用于将DLL注入到进程的地址空间中的整个过程。为了清楚地表明我们将要执行的操作,请看下面的图片,在该图片中,我们将向其中注入DLL的过程标有紫色,并命名为受害者。但是,我们需要澄清另外两个难题。首先,我们需要确定如果要将DLL注入到某个进程中,则必须首先拥有要注入的DLL。DLL以绿色呈现,并具有名称inject.dll。但是我们还必须有一个程序,该程序会将DLL注入受害者的地址空间。该程序以蓝色显示,名称为program.exe。

为了能够将DLL注入受害者的地址空间,program.exe必须顺序调用提供的函数。首先,它必须调用OpenProcess来获取受害者进程的句柄。之后,它必须调用GetProcAddress函数来获取kernel32.dll库中LoadLibraryA函数的地址。在这里,我们可以运行任何我们喜欢的函数,但是它必须存在于DLL中,该DLL已经加载在进程的地址空间中。我们知道每个程序都使用kernel32.dll库,因此将DLL注入到进程的地址空间中的最佳方法是查找LoadLibraryA函数并调用它。为了加载DLL,我们必须将DLL路径传递给LoadLibraryA函数,但是该名称需要存储在进程地址空间内的某个位置。明显,DLL的路径已经不太可能出现在进程的地址空间中,这就是为什么我们需要接下来的两个函数:VirtualAllocEx和WriteProcessMemory。第一个函数在进程的地址空间内分配一个新的内存范围。该内存区域的大小仅需要大到适合其内部DLL的名称即可;通常将大小四舍五入以占据至少一页。WriteProcessMemory是实际上将DLL的路径写入受害者的地址空间的函数。最后,调用CreateRemoteThread,该调用在受害者的地址空间内调用LoadLibraryA函数以向其中注入DLL。

更多信息请参考:https://resources.infosecinstitute.com/using-createremotethread-for-dll-injection-on-windows/#gref

原文地址:https://www.cnblogs.com/strive-sun/p/11968782.html