dll远线程注入

原理

核心函数

CreateRemoteThread:让在其他进程中创建一个线程变成可能

核心思想

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
);
HMODULE
WINAPI
LoadLibraryW(
    _In_ LPCWSTR lpLibFileName
    );

CreateRemoteThread函数的第四个参数是线程函数,我们可以用LoadLibrary的函数地址作为线程函数地址。

CreateRemoteThread函数的第五个参数是线程函数参数。用要加载的dll路径作为线程函数的参数。

相当于用这个线程函数(LoadLibrary)把参数(dll路径)Load到“被注入的进程”里。

设计的巧合才出现了这一注入方式

代码实现

获取pid

OpenProcess这个函数有个参数是pid,获取pid的方式多种多样,我这里使用的是快照

 1 //根据进程名找对应的pid(快照方式)
 2  DWORD _getProcessHandle(LPCTSTR lpProcessName)
 3 {
 4     DWORD dwRet = 0;
 5     HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 6     if (hSnapShot == INVALID_HANDLE_VALUE)
 7     {
 8         printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
 9         return dwRet;
10     }
11 
12     PROCESSENTRY32 pe32;
13     pe32.dwSize = sizeof(PROCESSENTRY32);
14     ::Process32First(hSnapShot, &pe32);
15     do
16     {
17         if (!lstrcmp(pe32.szExeFile, lpProcessName))
18         {
19             dwRet = pe32.th32ProcessID;
20             break;
21         }
22     } while (::Process32Next(hSnapShot, &pe32));
23     ::CloseHandle(hSnapShot);
24     return dwRet;
25 }

打开进程

hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);

在注入进程里申请空间

pAlloc = ::VirtualAllocEx(hprocess,NULL, _SIZE, MEM_COMMIT,PAGE_READWRITE);

因为我们需要找到那个参数(dll路径),在我本来的进程中,dll路径存放的地方和注入进程中dll路径存放的地方不是同一个地方,我们需要跨进程将dll路径写在注入进程中,下面起线程的时候才能找到存放dll路径的字符串

在申请的空间中写入数据

::WriteProcessMemory(hprocess, pAlloc, psDllFillName, _SIZE, NULL);

获得LoadLibraryW的地址

pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");

由于Windows引入了基址随机化ASLR安全机制,所以导致每次开机启动时系统DLL加载基址都不一样,有些系统dll(kernel,ntdll)的加载地址,允许每次启动基址可以改变,但是启动之后必须固定,也就是说两个不同进程在相互的虚拟内存中,这样的系统dll地址总是一样的。

创建线程在注入进程中

hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc,0,NULL);

让这个线程loadlibrary

所有代码

 1 #include <iostream>
 2 #include <windows.h>
 3 #include <TlHelp32.h>
 4 #include "tchar.h"
 5 
 6 //根据进程名找对应的pid(快照方式)
 7  DWORD _getProcessHandle(LPCTSTR lpProcessName)
 8 {
 9     DWORD dwRet = 0;
10     HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
11     if (hSnapShot == INVALID_HANDLE_VALUE)
12     {
13         printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
14         return dwRet;
15     }
16 
17     PROCESSENTRY32 pe32;
18     pe32.dwSize = sizeof(PROCESSENTRY32);
19     ::Process32First(hSnapShot, &pe32);
20     do
21     {
22         if (!lstrcmp(pe32.szExeFile, lpProcessName))
23         {
24             dwRet = pe32.th32ProcessID;
25             break;
26         }
27     } while (::Process32Next(hSnapShot, &pe32));
28     ::CloseHandle(hSnapShot);
29     return dwRet;
30 }
31 
32 
33 //打开一个进程并为其创建一个线程
34 DWORD _InjectThread(DWORD _Pid, LPCWSTR psDllFillName)
35 {
36     //打开进程
37     HANDLE hprocess;
38     HANDLE hThread;
39     DWORD _SIZE = 0;
40     LPVOID pAlloc = NULL;
41     DWORD psDllAddr = 0;
42     FARPROC pThreadFunction;
43     hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);
44     //在注入进程中写入Loadlibrary名称
45     _SIZE = (_tcslen(psDllFillName) + 1)* sizeof(TCHAR);
46     pAlloc = ::VirtualAllocEx(hprocess,NULL, _SIZE, MEM_COMMIT,PAGE_READWRITE);
47     if (pAlloc == NULL)
48     {
49         printf("VirtualAllocExERROR");
50         return FALSE;
51     }
52     BOOL x = ::WriteProcessMemory(hprocess, pAlloc, psDllFillName, _SIZE, NULL);
53     if (FALSE == x)
54     {
55         printf("WriteProcessMemoryERROR");
56         return FALSE;
57     }
58     //获得Loadlibrary的地址
59     pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
60     //在另一个进程创建一个线程
61     hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc,0,NULL);
62     if (hThread == NULL)
63     {
64         printf("CreateRemoteThreadError");
65         return FALSE;
66     }
67     WaitForSingleObject(hThread,-1);
68     GetExitCodeThread(hThread, &psDllAddr); 
69     VirtualFreeEx(hprocess, pAlloc, _SIZE, MEM_DECOMMIT);
70     ::CloseHandle(hprocess);
71     return TRUE;
72 }
73 int main()
74 {
75     DWORD PID = _getProcessHandle(L"Test.exe");
76     _InjectThread(PID,L"MessageBox.dll");
77 }

实际上整个过程就是等效于在注入进程中自己LoadLibrary,只不过我们是在其他进程load这个dll

Dll文件

 1 #include "pch.h"
 2 
 3 BOOL APIENTRY DllMain( HMODULE hModule,
 4                        DWORD  ul_reason_for_call,
 5                        LPVOID lpReserved
 6                      )
 7 {
 8     switch (ul_reason_for_call)
 9     {
10     case DLL_PROCESS_ATTACH:
11         MessageBox(NULL, L"sucess!!!", L"注入", MB_OK);
12     case DLL_THREAD_ATTACH:
13         MessageBox(NULL, L"sucess!!!", L"注入", MB_OK);
14     case DLL_THREAD_DETACH:
15     case DLL_PROCESS_DETACH:
16         break;
17     }
18     return TRUE;
19 }

测试

一开始没有这个dll

 

 注入后

 

 

 

 说明注入成功

posted @ 2021-03-29 20:54  Punished  阅读(214)  评论(0编辑  收藏  举报