线程的远程注入

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/vcforever/archive/2005/03/15/320144.aspx

 

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

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

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

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

[cpp]  view plain copy
  1. //Test.dll源代码  
  2. //  
  3. #include <windows.h>  
  4. BOOL APIENTRY DllMain(HANDLE hMoudle, DWORD dwReason, LPVOID lpReserved)  
  5. {  
  6.     char* pszProcessId = (char*)malloc(10*sizeof(char));  
  7.     switch(dwReason) {  
  8.         case DLL_PROCESS_ATTACH:  
  9.         _itoa(GetCurrentProcessId(), pszProcessId, 10);  
  10.         MessageBox(NULL, pszProcessId, "Notice", MB_ICONINFORMATION | MB_OK);  
  11.         case DLL_PROCESS_DETACH:  
  12.         case DLL_THREAD_ATTACH:  
  13.         case DLL_THREAD_DETACH:  
  14.         break;  
  15.     }  
  16.     return TRUE;  
  17. }  
 

下一步我们就可以专注于如何把这个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的思路就是这样,下面给出完整代码:

[cpp]  view plain copy
  1. #include <windows.h>  
  2. #include <psapi.h>  
  3. #include <string>  
  4. #include <iostream>  
  5. #pragma comment(lib, "Psapi.lib")  
  6. //提升进程访问权限  
  7. void enableDebugPriv()  
  8. {  
  9.     HANDLE hToken;  
  10.     LUID sedebugnamue;  
  11.     TOKEN_PRIVILEGES tkp;  
  12.     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))  
  13.         return;  
  14.     if (!LookupPrivilegue(NULL, SE_DEBUG_NAME, &sedebugnamue)) {  
  15.         CloseHandle(hToken);  
  16.         return;  
  17.     }  
  18.     tkp.PrivilegeCount = 1;  
  19.     tkp.Privileges[0].Luid = sedebugnamue;  
  20.     tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
  21.     if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))  
  22.         CloseHandle(hToken);  
  23.     }  
  24.     //根据进程名称取得进程ID,如果有多个运行实例则返回第一个枚举出来的进程ID  
  25. DWORD getSpecifiedProcessId(const char* pszProcessName)  
  26. {  
  27.     DWORD processId[1024], cbNeeded, dwProcessesCount;  
  28.     HANDLE hProcess;  
  29.     HMODULE hMod;  
  30.     char szProcessName[MAX_PATH] = "UnknownProcess";  
  31.     DWORD dwArrayInBytes = sizeof(processId)*sizeof(DWORD);  
  32.     if (!EnumProcesses(processId, dwArrayInBytes, &cbNeeded))  
  33.         return 0;  
  34.     //计算数组中的元素个数  
  35.     dwProcessesCount = cbNeeded / sizeof(DWORD);  
  36.     enableDebugPriv();  
  37.     for (UINT i = 0; i < dwProcessesCount; i++) {  
  38.         hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId[i]);  
  39.         if (!hProcess) {  
  40.             continue;  
  41.         } else {  
  42.             if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {  
  43.                 GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName));  
  44.                 if (!_stricmp(szProcessName, pszProcessName)) {  
  45.                     CloseHandle(hProcess);  
  46.                     return processId[i];  
  47.                 }  
  48.             }  
  49.         }  
  50.     }  
  51.     CloseHandle(hProcess);  
  52.     return 0;  
  53. }  
  54. int main(int argc, char* argv[])  
  55. {  
  56.     std::cout << "please input the name of target process !" << std::endl;  
  57.     //等待输入进程名称  
  58.     std::string strProcessName;  
  59.     std::cin >> strProcessName;  
  60.     //在这里为了简单起见,使用了绝对路径  
  61.     char szDllPath[MAX_PATH] = "D://test.dll";  
  62.     char szFileName[MAX_PATH] = "D://test.dll";  
  63.     //提升进程访问权限  
  64.     enableDebugPriv();  
  65.     if (strProcessName.empty()) {  
  66.         MessageBox(NULL, "The target process name is invalid !""Notice", MB_ICONSTOP);  
  67.         return -1;  
  68.     }  
  69.     //根据进程名称得到进程ID  
  70.     DWORD dwTargetProcessId = getSpecifiedProcessId(strProcessName.c_str());  
  71.     HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTargetProcessId);  
  72.     if (!hTargetProcess) {  
  73.         MessageBox(NULL, "Open target process failed !""Notice", MB_ICONSTOP);  
  74.         return -1;  
  75.     }  
  76.     //计算DLL文件名称所占的存储空间  
  77.     int memorySize = (strlen(szDllPath) + 1) * sizeof(char);  
  78.     //在目标进程中开辟存储空间,用来存放DLL的文件名称  
  79.     char* pszFileNameRemote = (char*)VirtualAllocEx(hTargetProcess,  
  80.         0, memorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);  
  81.     if (!pszFileNameRemote) {  
  82.         MessageBox(NULL, "Alloc dll name string in target process failed !""Notice", MB_ICONSTOP);  
  83.         return -1;  
  84.     }  
  85.     //将DLL的文件名写入目标进程地址空间  
  86.     if (!WriteProcessMemory(hTargetProcess, pszFileNameRemote,  
  87.         (LPVOID)szFileName, memorySize, NULL)) {  
  88.         MessageBox(NULL, "Write dll name string to target process failed !",  
  89.             "Notice", MB_ICONSTOP);  
  90.         return -1;  
  91.     }  
  92.     PTHREAD_START_ROUTINE pfnStartAddr =  
  93.         (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");  
  94.     HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess,  
  95.         NULL, 0, pfnStartAddr, pszFileNameRemote, 0, NULL);  
  96.     WaitForSingleObject(hRemoteThread, INFINITE);  
  97.     VirtualFreeEx(hTargetProcess, 0, memorySize, NULL);  
  98.     if (hRemoteThread)  
  99.         CloseHandle(hTargetProcess);  
  100.     return 0;  
  101. }  
 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值