-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathinjector.c
325 lines (282 loc) · 10.4 KB
/
injector.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*************************************************************
* Registry Redirector
*
* (C)oded by [email protected], 2010
*
* This application redirects registry calls to Registry dump
* files, so that you can "shim" your application to a foreign
* registry.
*
* This may become handy if you want to check the registry
* of another machine with various checking tools that are
* designed for the checking of a live System.
* Note that the application must use the normal WIN32 API
* for registry Access. If the app is checking via Native API,
* this won't work.
*
* Be aware that reads AND WRITES are redirected, so only
* use this tool on copies of your original Registry files.
* It may be a good idea to use this tool in a PE environment.
*
*************************************************************
* Module: injector.c
* Descr.: Creates a remote thread in the target process that
* handles the redirection of the registry
* License: GPL 3
* Date : 12.02.2010
* Changelog:
*************************************************************/
// ------------------------- INCLUDES -------------------------
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "injector.h"
// ------------------------- DEFINES --------------------------
typedef FARPROC (WINAPI *RegOver)(HKEY, HKEY);
typedef FARPROC (WINAPI *RegCreate)(HKEY, LPCTSTR, DWORD, LPTSTR, DWORD,
REGSAM, LPSECURITY_ATTRIBUTES, PHKEY,
LPDWORD);
#define REG_CLASSES_SPECIAL_TAG 2
#define TagSpecialClassesHandle( Handle ) \
( *Handle = (( HKEY )((( ULONG_PTR )( *Handle )) | REG_CLASSES_SPECIAL_TAG )))
// ------------------------ VARIABLES -------------------------
static DWORD m_dwLastError = ERROR_SUCCESS;
static char m_szLastErr[256] = {0};
// ------------------------ PROTOTYPES ------------------------
static void Inj_Error (char *pszFormat, ...) ;
//-----------------------------------------------------------------
// Remote code
//-----------------------------------------------------------------
#pragma check_stack (off)
DWORD WINAPI ThreadProc (LPVOID lpParameter)
{
HKEY hKey = 0;
DWORD dwr=0, dwWait=INFINITE;
HYPINJECT* pp = (HYPINJECT*)lpParameter;
int i;
HKEY hkeyTab[sizeof(pp->aRedirKeys)/sizeof(pp->aRedirKeys[0])]={0};
// load advapi32.dll
HMODULE hadv = pp->fnLoad (pp->szADVAPI);
ProcGetProcAddress GetProc = (ProcGetProcAddress)(pp->fnGetProc);
RegOver RegOverride = (RegOver)GetProc(hadv,pp->szRegOverridePredefKey) ;
RegCreate RegCreateK = (RegCreate)GetProc(hadv, pp->szRegCreateKeyEx ) ;
// Create our substitute keys
for (i=0; i<sizeof(pp->aRedirKeys)/sizeof(pp->aRedirKeys[0]); i++)
{
if (pp->aRedirKeys[i].hKey)
{
if (RegCreateK (pp->aRedirKeys[i].hKey, pp->aRedirKeys[i].szPath, 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &hKey, &dwr) == ERROR_SUCCESS)
{
hkeyTab[i] = hKey;
// if (i == 0) TagSpecialClassesHandle(hKey);
RegOverride ((HKEY)(i | 0x80000000), hKey);
}
}
}
// Resume process
if (pp->hThread)
{
if (pp->fnResumeThread(pp->hThread) != 0xFFFFFFFF && pp->bWaitForMainThread)
// Some libs may f*ck up because of DLL_THREAD_ATTACH/DETACH calls issued during init
// So we may block until main thread terminates to not confuse these DLLs
if (pp->dwResetStartTimeout) dwWait = pp->dwResetStartTimeout;
if (pp->fnWaitForSingleObject (pp->hThread, dwWait) == WAIT_TIMEOUT)
{
// Re-override associations after a given time to be sure that
// it hasn't been reset by the app
for (i=0; i<sizeof(pp->aRedirKeys)/sizeof(pp->aRedirKeys[0]); i++)
{
if (hkeyTab[i]) RegOverride ((HKEY)(i | 0x80000000), hkeyTab[i]);
}
pp->fnWaitForSingleObject (pp->hThread, INFINITE);
}
}
return 0;
}
static void AfterThreadProc (void) { }
#pragma check_stack
//-----------------------------------------------------------------
// Public
//-----------------------------------------------------------------
/* Injector_Init
*
* Description: Sets up Injector structure with default values
* Parameters : pp - Structure to initialize
*/
void Injector_Init (HYPINJECT *pp)
{
HYPINJECT hypInject = {0};
HMODULE hk = GetModuleHandle ("kernel32.dll");
memset (pp, 0, sizeof(HYPINJECT));
pp->fnLoad = (ProcLoadLibrary)GetProcAddress (hk, "LoadLibraryA");
pp->fnGetProc = (ProcGetProcAddress)GetProcAddress (hk, "GetProcAddress");
pp->fnResumeThread = (ProcResumeThread)GetProcAddress (hk, "ResumeThread");
pp->fnWaitForSingleObject = (ProcWaitForSingleObject)GetProcAddress (hk, "WaitForSingleObject");
lstrcpy (pp->szADVAPI, "advapi32.dll");
lstrcpy (pp->szRegOverridePredefKey, "RegOverridePredefKey");
lstrcpy (pp->szRegCreateKeyEx, "RegCreateKeyExA");
pp->dwResetStartTimeout = 5000;
return;
}
//-----------------------------------------------------------------
/* Injector_GetLastError
*
* Description: Get last error that occured in this module
* Parameters : pdwLastErr - Optional pointer to a variable that receives error code
* Returns : Error message
*/
char *Injector_GetLastError(DWORD *pdwLastErr)
{
if (pdwLastErr) *pdwLastErr = m_dwLastError;
return m_szLastErr;
}
//-----------------------------------------------------------------
/* Injector_Override
*
* Description: Set base Keys you want to override
* Parameters : pp - Injector instance structure
* hKey - Root key which you want to override (HKLM/HKCU/HKCR,...)
* hRoot - Root Key of registry key where hKey will be redirected to
* pszSubKey - Subkey of hRoot where hKey will be redirected to
*/
void Injector_Override (HYPINJECT *pp, HKEY hKey, HKEY hRoot, char *pszSubKey)
{
REDIRINFO *pInfo;
pInfo = &pp->aRedirKeys[(DWORD)hKey^0x80000000];
pInfo->hKey = hRoot;
lstrcpyn (pInfo->szPath, pszSubKey, sizeof(pInfo->szPath));
}
//-----------------------------------------------------------------
/* Injector_OpenProcess
*
* Description : Inject into running process
* Parameters : pp - Injector instance structure
* PID - Process ID of target process
* Returns : TRUE on success, FALSE on failure
*/
BOOL Injector_OpenProcess (HYPINJECT *pp, DWORD PID)
{
BOOL bRet = FALSE;
HANDLE hProc = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE,
FALSE, PID);
if (!hProc)
{
Inj_Error ("OpenProcess for PID %d failed: ", PID);
return FALSE;
}
bRet = Injector_InjectFunc (pp, hProc);
CloseHandle (hProc);
return bRet;
}
//-----------------------------------------------------------------
/* Injector_CreateProcess
*
* Description : Start Application and inject into it
* Parameters : pp - Injector instance structure
* dwDelay - Delay to wait for after startup before injecting. Should be 0 normally.
* lpApplicationName - Path and filename of application to start
* lpCommandLine - Commandline args like with CreateProcess, can be NULL
* ppi - [OUT] PROCESS_INFORMATION from CreateProcess
* Returns : TRUE on success, FALSE on failure
*/
BOOL Injector_CreateProcess (HYPINJECT *pp, DWORD dwDelay, LPCTSTR lpApplicationName, LPTSTR lpCommandLine, PROCESS_INFORMATION *ppi)
{
BOOL bRet = FALSE;
STARTUPINFO sui={0};
if (!CreateProcess (lpApplicationName, lpCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL,
NULL, &sui,ppi))
{
Inj_Error ("CreateProcess for %s failed: ", lpApplicationName);
return FALSE;
}
if (dwDelay || !DuplicateHandle (GetCurrentProcess(), ppi->hThread, ppi->hProcess, &pp->hThread, PROCESS_ALL_ACCESS, FALSE, 0))
pp->hThread = NULL;
if (!pp->hThread)
{
ResumeThread (ppi->hThread);
WaitForInputIdle(ppi->hProcess, dwDelay);
SuspendThread (ppi->hThread);
}
else pp->bWaitForMainThread = TRUE;
bRet = Injector_InjectFunc (pp, ppi->hProcess);
if (!pp->hThread) ResumeThread (ppi->hThread);
return bRet;
}
//-----------------------------------------------------------------
/* Injector_InjectFunc
*
* Description : Inject our redirection code to the process
* Parameters : pp - Injector instance structure
* hProc - Handle to the process where wo should inject to
* Returns : TRUE on success, FALSE on failure
*/
BOOL Injector_InjectFunc(HYPINJECT *pp, HANDLE hProc)
{
PVOID pCode, pData;
HANDLE hThread;
DWORD cbCodeSize = (BYTE*)AfterThreadProc - (BYTE*)ThreadProc;
if (pCode = VirtualAllocEx (hProc,NULL,cbCodeSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE))
{
if (WriteProcessMemory(hProc,pCode,(LPVOID)(DWORD)&ThreadProc,cbCodeSize,NULL))
{
if (pData = VirtualAllocEx (hProc,NULL, sizeof (HYPINJECT), MEM_COMMIT, PAGE_EXECUTE_READWRITE))
{
if (WriteProcessMemory (hProc, pData, pp, sizeof (HYPINJECT), NULL))
{
if (hThread = CreateRemoteThread(hProc,NULL,0,(LPTHREAD_START_ROUTINE)pCode,pData,0,NULL))
{
if (!(pp->bWaitForMainThread && pp->hThread))
{
WaitForSingleObject (hThread, INFINITE);
CloseHandle(hThread);
}
return TRUE;
}
else
{
Inj_Error ("CreateRemoteThread failed: ");
}
}
else
{
Inj_Error ("Error writing Session data (%d bytes) to target process", sizeof (HYPINJECT));
}
VirtualFreeEx (hProc, pData, 0, MEM_RELEASE);
}
else
{
Inj_Error ("Error allocating Session data (%d bytes) in target process", sizeof (HYPINJECT));
}
}
else
{
Inj_Error ("Error writing Thread routine (%d bytes) to target process", cbCodeSize);
}
VirtualFreeEx (hProc, pCode, 0, MEM_RELEASE);
}
else
{
Inj_Error ("Error allocating memory for Thread routine (%d bytes) in target process", cbCodeSize);
}
return FALSE;
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Set last error message
static void Inj_Error (char *pszFormat, ...)
{
char *p;
va_list ap;
m_dwLastError = GetLastError();
va_start(ap, pszFormat);
_vsnprintf(m_szLastErr, sizeof(m_szLastErr), pszFormat, ap);
va_end(ap);
p = m_szLastErr + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_dwLastError,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), m_szLastErr, 0, NULL);
wsprintf (p, " (%08X)", m_dwLastError);
}