复习远程线程注入-CreateRemoteThread
大路货就不说了,做下总结:
1、权限。如果需要Inject一些系统关键进程,需要先提权。提权用到的函数:
OpenProcessToken
LookupPrivilegeValue
AdjustTokenPrivileges
能找到现成的可用代码,一搜一大把,我就不贴了
2、打开进程。
3、打开成功后,分配内存。因为要注入进程,而其只能访问自己进程的空间,但这时他并不知道要注入DLL的路径,所以需要把路径以这种方式写道对方进程里去。(得到目标进程中保存字符串的起始地址)
4、在对方地址包含要加载DLL的路径之后,从Kernel32中获取LoadLibrary的地址(这个地址在每个进程中都一样),调用CreateRemoteThread函数,把目标进程的字符串当作参数传给CreateRemoteThread。这样就Inject进去了。
Inject完了得释放,释放就是Inject过程的逆过程,加载DLL是LoadLibrary,释放是FreeLibrary:
1、先便利下目标进程已加载的所有模块,如果找到了我们刚刚注入的,则保存,跳出循环
2、得到FreeLibrary的地址,通过Kernel32模块。
3、调用CreateRemoteThread线程,将步骤1中得到的目标进程中我们注入的模块地址当参数传进去,然后就释放了。
晚上的时候阅读了下《WINDOWS核心编程》的源码,其中有这部分的代码,是99年编写的。拿VS2005转换并编译,注入功能依旧可用(我现在用的是WIN7)不禁让人唏嘘不已。。十年间多少人用这份代码学习WINDOWS编程,书上说的可维护、可移植的代码大概就是说的这种吧。。贴下主要部分:
代码
1 #ifdef UNICODE
2 #define InjectLib InjectLibW
3 #define EjectLib EjectLibW
4 #else
5 #define InjectLib InjectLibA
6 #define EjectLib EjectLibA
7 #endif // !UNICODE
8
9
10 ///////////////////////////////////////////////////////////////////////////////
11
12
13 const char * szDllPath = "D:\\source\\CreateRomoteThreadDemo\\dllsingle.dll";
14
15 BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {
16
17 BOOL fOk = FALSE; // Assume that the function fails
18 HANDLE hProcess = NULL, hThread = NULL;
19 PWSTR pszLibFileRemote = NULL;
20
21 __try {
22 // Get a handle for the target process.
23 hProcess = OpenProcess(
24 PROCESS_QUERY_INFORMATION | // Required by Alpha
25 PROCESS_CREATE_THREAD | // For CreateRemoteThread
26 PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx
27 PROCESS_VM_WRITE, // For WriteProcessMemory
28 FALSE, dwProcessId);
29 if (hProcess == NULL) __leave;
30
31 // Calculate the number of bytes needed for the DLL's pathname
32 int cch = 1 + lstrlenW(pszLibFile);
33 int cb = cch * sizeof(WCHAR);
34
35 // Allocate space in the remote process for the pathname
36 pszLibFileRemote = (PWSTR)
37 VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
38 if (pszLibFileRemote == NULL) __leave;
39
40 // Copy the DLL's pathname to the remote process's address space
41 if (!WriteProcessMemory(hProcess, pszLibFileRemote,
42 (PVOID) pszLibFile, cb, NULL)) __leave;
43
44 // Get the real address of LoadLibraryW in Kernel32.dll
45 PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
46 GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
47 if (pfnThreadRtn == NULL) __leave;
48
49 // Create a remote thread that calls LoadLibraryW(DLLPathname)
50 hThread = CreateRemoteThread(hProcess, NULL, 0,
51 pfnThreadRtn, pszLibFileRemote, 0, NULL);
52 if (hThread == NULL) __leave;
53
54 // Wait for the remote thread to terminate
55 WaitForSingleObject(hThread, INFINITE);
56
57 fOk = TRUE; // Everything executed successfully
58 }
59 __finally { // Now, we can clean everthing up
60
61 // Free the remote memory that contained the DLL's pathname
62 if (pszLibFileRemote != NULL)
63 VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
64
65 if (hThread != NULL)
66 CloseHandle(hThread);
67
68 if (hProcess != NULL)
69 CloseHandle(hProcess);
70 }
71
72 return(fOk);
73 }
74
75
76 ///////////////////////////////////////////////////////////////////////////////
77
78
79 BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {
80
81 // Allocate a (stack) buffer for the Unicode version of the pathname
82 PWSTR pszLibFileW = (PWSTR)
83 _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));
84
85 // Convert the ANSI pathname to its Unicode equivalent
86 wsprintfW(pszLibFileW, L"%S", pszLibFile);
87
88 // Call the Unicode version of the function to actually do the work.
89 return(InjectLibW(dwProcessId, pszLibFileW));
90 }
91
92
93 ///////////////////////////////////////////////////////////////////////////////
94
95
96 BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {
97
98 BOOL fOk = FALSE; // Assume that the function fails
99 HANDLE hthSnapshot = NULL;
100 HANDLE hProcess = NULL, hThread = NULL;
101
102 __try {
103 // Grab a new snapshot of the process
104 hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
105 if (hthSnapshot == NULL) __leave;
106
107 // Get the HMODULE of the desired library
108 MODULEENTRY32W me = { sizeof(me) };
109 BOOL fFound = FALSE;
110 BOOL fMoreMods = Module32FirstW(hthSnapshot, &me);
111 for (; fMoreMods; fMoreMods = Module32NextW(hthSnapshot, &me)) {
112 fFound = (lstrcmpiW(me.szModule, pszLibFile) == 0) ||
113 (lstrcmpiW(me.szExePath, pszLibFile) == 0);
114 if (fFound) break;
115 }
116 if (!fFound) __leave;
117
118 // Get a handle for the target process.
119 hProcess = OpenProcess(
120 PROCESS_QUERY_INFORMATION | // Required by Alpha
121 PROCESS_CREATE_THREAD |
122 PROCESS_VM_OPERATION, // For CreateRemoteThread
123 FALSE, dwProcessId);
124 if (hProcess == NULL) __leave;
125
126 // Get the real address of LoadLibraryW in Kernel32.dll
127 PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
128 GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
129 if (pfnThreadRtn == NULL) __leave;
130
131 // Create a remote thread that calls LoadLibraryW(DLLPathname)
132 hThread = CreateRemoteThread(hProcess, NULL, 0,
133 pfnThreadRtn, me.modBaseAddr, 0, NULL);
134 if (hThread == NULL) __leave;
135
136 // Wait for the remote thread to terminate
137 WaitForSingleObject(hThread, INFINITE);
138
139 fOk = TRUE; // Everything executed successfully
140 }
141 __finally { // Now we can clean everything up
142
143 if (hthSnapshot != NULL)
144 CloseHandle(hthSnapshot);
145
146 if (hThread != NULL)
147 CloseHandle(hThread);
148
149 if (hProcess != NULL)
150 CloseHandle(hProcess);
151 }
152
153 return(fOk);
154 }
155
156
157 ///////////////////////////////////////////////////////////////////////////////
158
159
160 BOOL WINAPI EjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {
161
162 // Allocate a (stack) buffer for the Unicode version of the pathname
163 PWSTR pszLibFileW = (PWSTR)
164 _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));
165
166 // Convert the ANSI pathname to its Unicode equivalent
167 wsprintfW(pszLibFileW, L"%S", pszLibFile);
168
169 // Call the Unicode version of the function to actually do the work.
170 return(EjectLibW(dwProcessId, pszLibFileW));
171 }
172
(支持ANSI和UNICODE两种版本的API)