将DLL挂接到远程进程之中(远程注入)

本文详细介绍了一种远程DLL注入技术,即如何将自定义DLL挂载到远程进程,以实现在目标进程中执行特定代码的目的。文章提供了从创建DLL、获取目标进程ID到最终注入DLL的完整流程,并附带示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 将DLL挂接到远程进程之中(远程注入) 收藏

在上一篇文章《线程的远程注入》中介绍了如何让其他的进程中执行自己的代码的一种方法 
及自己定义一个线程,在线程体中编写执行代码,然后使用VirtualAllocEx函数为线程体以 
及线程中用到的字符常量和调用的MessageBox入口函数地址,在目标进程中开辟存储区,然 
后再通过WriteProcessMemory函数,将这些数据写入目标进程的地址空间中。最后通过 
CreateRemoteThread函数,让自己的线程运行在目标进程中。 

上面的方法需要为线程和常量在目标进程中开辟足够的存储空间,而且这个空间的大小很难 
确定,稍不注意就会发生访问违规的错误。 

下面我来介绍另外一种在其他进程中执行自己的代码的方法,让目标进程加载我们自己编写的 
DLL模块。 

首先我们来创建一个DLL模块(稍后我们将要把这个DLL加载到目标进程中,让目标进程来运行 
DLL中的代码)。 
我们创建的这个DLL模块非常简单,只是得到加载该DLL的进程的ID,然后通过MessageBox函数 
显示出来,当然也可以写一些复杂的代码。不过我们这里只是介绍一下方法,有个显示结果足 
以:)。下面就是DLL模块的代码: 

//Test.dll源代码 
// 
#include <windows.h> 

BOOL APIENTRY DllMain(HANDLE hMoudle, DWORD dwReason, LPVOID lpReserved) 

    char* pszProcessId = (char*)malloc(10*sizeof(char)); 

    switch(dwReason) { 
        case DLL_PROCESS_ATTACH: 
        _itoa(GetCurrentProcessId(), pszProcessId, 10); 
        MessageBox(NULL, pszProcessId, "Notice", MB_ICONINFORMATION | MB_OK); 
        case DLL_PROCESS_DETACH: 
        case DLL_THREAD_ATTACH: 
        case DLL_THREAD_DETACH: 
        break; 
    } 
    return TRUE; 


下一步我们就可以专注于如何把这个DLL挂接到目标进程中。 

首先我们通过OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId)来打开我们试图加载DLL的进程(注意
进程的打开权限一定要设置为PROCESS_ALL_ACCESS,因为我们要在目标进程中创建线程)。 

然后我们可以使用CreateRemoteThread来创建LoadLibraryA线程来启动我们的这个DLL。 
LoadLibraryA存在于系统的kernel32.dll中用来加载DLL模块,该函数只有一个参数就是DLL文件的名称(该 
名称包括路径)。由于加载DLL的操作是在其他进程中进行,所以我们必须把DLL的文件名称拷贝到目标进程 
的地址空间中。 

我们必须计算出该文件名所占的内存空间 

int nLength = (strlen(pszFileName)+1)*sizeof(char); 
接下来使用VirtualAllocEx函数为DLL文件名在目标进程中分配地址空间,在使用WriteProcessMemory将 
DLL的文件名拷贝到刚刚分配的地址中。 

下一步就是取得LoadLibraryA函数的入口地址 
PTHREAD_START_ROUTINE pfnLoadLibraryA = 
(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA"); 
因为kernel32.dll模块是系统的核心模块,所以该模块中的函数地址在所有进程中全都相同。 
我们在本进程中得到的LoadLibraryA函数的入口地址同样适用于其他进程。 

所有条件已经具备,最后我们使用CreateRemoteThread函数,将LoadLibraryA函数的入口地址以及DLL的文件 
名作为参数,即可让目标进程加载我们自己的DLL,至于你要让你的DLL中运行什么代码,就自己看着办吧! 

让远程进程挂接自己的DLL的思路就是这样,下面给出完整代码: 

#include <windows.h> 
#include <psapi.h> 
#include <string> 
#include <iostream> 

#pragma comment(lib, "Psapi.lib") 

//提升进程访问权限 
void enableDebugPriv() 

    HANDLE hToken; 
    LUID sedebugnameValue; 
    TOKEN_PRIVILEGES tkp; 

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
        return; 

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { 
        CloseHandle(hToken); 
        return; 
    } 

    tkp.PrivilegeCount = 1; 
    tkp.Privileges[0].Luid = sedebugnameValue; 
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) 
        CloseHandle(hToken); 
    } 

    //根据进程名称取得进程ID,如果有多个运行实例则返回第一个枚举出来的进程ID 
DWORD getSpecifiedProcessId(const char* pszProcessName) 

    DWORD processId[1024], cbNeeded, dwProcessesCount; 
    HANDLE hProcess; 
    HMODULE hMod; 

    char szProcessName[MAX_PATH] = "UnknownProcess"; 
    DWORD dwArrayInBytes = sizeof(processId)*sizeof(DWORD); 

    if (!EnumProcesses(processId, dwArrayInBytes, &cbNeeded)) 
        return 0; 
    //计算数组中的元素个数
    dwProcessesCount = cbNeeded / sizeof(DWORD); 
    enableDebugPriv(); 

    for (UINT i = 0; i < dwProcessesCount; i++) { 
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId[i]); 
        if (!hProcess) { 
            continue; 
        } else { 
            if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { 
                GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName)); 
                if (!_stricmp(szProcessName, pszProcessName)) { 
                    CloseHandle(hProcess); 
                    return processId[i]; 
                } 
            } 
        } 
    } 

    CloseHandle(hProcess); 
    return 0; 



int main(int argc, char* argv[]) 

    std::cout << "please input the name of target process !" << std::endl; 
    //等待输入进程名称 
    std::string strProcessName; 
    std::cin >> strProcessName; 

    //在这里为了简单起见,使用了绝对路径 
    char szDllPath[MAX_PATH] = "D://test.dll"; 
    char szFileName[MAX_PATH] = "D://test.dll"; 
    //提升进程访问权限 
    enableDebugPriv(); 

    if (strProcessName.empty()) { 
        MessageBox(NULL, "The target process name is invalid !", "Notice", MB_ICONSTOP); 
        return -1; 
    } 
    //根据进程名称得到进程ID 
    DWORD dwTargetProcessId = getSpecifiedProcessId(strProcessName.c_str()); 

    HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTargetProcessId); 

    if (!hTargetProcess) { 
        MessageBox(NULL, "Open target process failed !", "Notice", MB_ICONSTOP); 
        return -1; 
    } 
    //计算DLL文件名称所占的存储空间 
    int memorySize = (strlen(szDllPath) + 1) * sizeof(char); 
    //在目标进程中开辟存储空间,用来存放DLL的文件名称 
    char* pszFileNameRemote = (char*)VirtualAllocEx(hTargetProcess, 
        0, memorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 

    if (!pszFileNameRemote) { 
        MessageBox(NULL, "Alloc dll name string in target process failed !", "Notice", MB_ICONSTOP); 
        return -1; 
    } 
    //将DLL的文件名写入目标进程地址空间 
    if (!WriteProcessMemory(hTargetProcess, pszFileNameRemote, 
        (LPVOID)szFileName, memorySize, NULL)) { 
        MessageBox(NULL, "Write dll name string to target process failed !", 
            "Notice", MB_ICONSTOP); 
        return -1; 
    } 

    PTHREAD_START_ROUTINE pfnStartAddr = 
        (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); 

    HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess, 
        NULL, 0, pfnStartAddr, pszFileNameRemote, 0, NULL); 

    WaitForSingleObject(hRemoteThread, INFINITE); 
    VirtualFreeEx(hTargetProcess, 0, memorySize, NULL); 

    if (hRemoteThread) 
        CloseHandle(hTargetProcess); 

    return 0; 


本文参考了西祠高手shotgun的《揭开木马的神秘面纱》,代码为自己所写,放在这里供大家参考。 
大家可以参考上面的步骤自己实现一遍! 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值