其他分享
首页 > 其他分享> > MemLoadLibraryCPP

MemLoadLibraryCPP

作者:互联网

  1 /*
  2  * Memory DLL loading code
  3  * Version 0.0.3
  4  *
  5  * Copyright (c) 2004-2013 by Joachim Bauch / mail@joachim-bauch.de
  6  * http://www.joachim-bauch.de
  7  *
  8  * The contents of this file are subject to the Mozilla Public License Version
  9  * 2.0 (the "License"); you may not use this file except in compliance with
 10  * the License. You may obtain a copy of the License at
 11  * http://www.mozilla.org/MPL/
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 15  * for the specific language governing rights and limitations under the
 16  * License.
 17  *
 18  * The Original Code is MemoryModule.c
 19  *
 20  * The Initial Developer of the Original Code is Joachim Bauch.
 21  *
 22  * Portions created by Joachim Bauch are Copyright (C) 2004-2013
 23  * Joachim Bauch. All Rights Reserved.
 24  *
 25  */
 26 
 27 #include "StdAfx.h"
 28 #ifndef __GNUC__
 29 // disable warnings about pointer <-> DWORD conversions
 30 #pragma warning( disable : 4311 4312 )
 31 #endif
 32 
 33 #ifdef _WIN64
 34 #define POINTER_TYPE ULONGLONG
 35 #else
 36 #define POINTER_TYPE DWORD
 37 #endif
 38 
 39 #include <windows.h>
 40 #include <winnt.h>
 41 #include <tchar.h>
 42 #ifdef DEBUG_OUTPUT
 43 #include <stdio.h>
 44 #endif
 45 
 46 #ifndef IMAGE_SIZEOF_BASE_RELOCATION
 47 // Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!?
 48 #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
 49 #endif
 50 
 51 #include "MemoryModule.h"
 52 
 53 typedef struct {
 54     PIMAGE_NT_HEADERS headers;
 55     unsigned char *codeBase;
 56     HCUSTOMMODULE *modules;
 57     int numModules;
 58     int initialized;
 59     CustomLoadLibraryFunc loadLibrary;
 60     CustomGetProcAddressFunc getProcAddress;
 61     CustomFreeLibraryFunc freeLibrary;
 62     void *userdata;
 63 } MEMORYMODULE, *PMEMORYMODULE;
 64 
 65 typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
 66 
 67 #define GET_HEADER_DICTIONARY(module, idx)    &(module)->headers->OptionalHeader.DataDirectory[idx]
 68 
 69 #ifdef DEBUG_OUTPUT
 70 static void
 71 OutputLastError(const char *msg)
 72 {
 73     LPVOID tmp;
 74     char *tmpmsg;
 75     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 76         NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL);
 77     tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);
 78     sprintf(tmpmsg, "%s: %s", msg, tmp);
 79     OutputDebugString(tmpmsg);
 80     LocalFree(tmpmsg);
 81     LocalFree(tmp);
 82 }
 83 #endif
 84 
 85 static void
 86 CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
 87 {
 88     int i, size;
 89     unsigned char *codeBase = module->codeBase;
 90     unsigned char *dest;
 91     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
 92     for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
 93         if (section->SizeOfRawData == 0) {
 94             // section doesn't contain data in the dll itself, but may define
 95             // uninitialized data
 96             size = old_headers->OptionalHeader.SectionAlignment;
 97             if (size > 0) {
 98                 dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
 99                     size,
100                     MEM_COMMIT,
101                     PAGE_READWRITE);
102 
103                 section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
104                 memset(dest, 0, size);
105             }
106 
107             // section is empty
108             continue;
109         }
110 
111         // commit memory block and copy data from dll
112         dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
113                             section->SizeOfRawData,
114                             MEM_COMMIT,
115                             PAGE_READWRITE);
116         memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
117         section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
118     }
119 }
120 
121 // Protection flags for memory pages (Executable, Readable, Writeable)
122 static int ProtectionFlags[2][2][2] = {
123     {
124         // not executable
125         {PAGE_NOACCESS, PAGE_WRITECOPY},
126         {PAGE_READONLY, PAGE_READWRITE},
127     }, {
128         // executable
129         {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
130         {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
131     },
132 };
133 
134 static void
135 FinalizeSections(PMEMORYMODULE module)
136 {
137     int i;
138     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
139 #ifdef _WIN64
140     POINTER_TYPE imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);
141 #else
142     #define imageOffset 0
143 #endif
144     
145     // loop through all sections and change access flags
146     for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
147         DWORD protect, oldProtect, size;
148         int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
149         int readable =   (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
150         int writeable =  (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
151 
152         if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
153             // section is not needed any more and can safely be freed
154             VirtualFree((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), section->SizeOfRawData, MEM_DECOMMIT);
155             continue;
156         }
157 
158         // determine protection flags based on characteristics
159         protect = ProtectionFlags[executable][readable][writeable];
160         if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
161             protect |= PAGE_NOCACHE;
162         }
163 
164         // determine size of region
165         size = section->SizeOfRawData;
166         if (size == 0) {
167             if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
168                 size = module->headers->OptionalHeader.SizeOfInitializedData;
169             } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
170                 size = module->headers->OptionalHeader.SizeOfUninitializedData;
171             }
172         }
173 
174         if (size > 0) 
175         {
176             // change memory access flags
177             if (VirtualProtect((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), size, protect, &oldProtect) == 0)
178             {
179 #ifdef DEBUG_OUTPUT
180                 OutputLastError("Error protecting memory page");
181 #endif 
182             }
183         }
184     }
185 #ifndef _WIN64
186 #undef imageOffset
187 #endif
188 }
189 
190 static void
191 PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
192 {
193     DWORD i;
194     unsigned char *codeBase = module->codeBase;
195 
196     PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
197     if (directory->Size > 0) {
198         PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress);
199         for (; relocation->VirtualAddress > 0; ) {
200             unsigned char *dest = codeBase + relocation->VirtualAddress;
201             unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
202             for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) {
203                 DWORD *patchAddrHL;
204 #ifdef _WIN64
205                 ULONGLONG *patchAddr64;
206 #endif
207                 int type, offset;
208 
209                 // the upper 4 bits define the type of relocation
210                 type = *relInfo >> 12;
211                 // the lower 12 bits define the offset
212                 offset = *relInfo & 0xfff;
213                 
214                 switch (type)
215                 {
216                 case IMAGE_REL_BASED_ABSOLUTE:
217                     // skip relocation
218                     break;
219 
220                 case IMAGE_REL_BASED_HIGHLOW:
221                     // change complete 32 bit address
222                     patchAddrHL = (DWORD *) (dest + offset);
223                     *patchAddrHL += (DWORD) delta;
224                     break;
225                 
226 #ifdef _WIN64
227                 case IMAGE_REL_BASED_DIR64:
228                     patchAddr64 = (ULONGLONG *) (dest + offset);
229                     *patchAddr64 += (ULONGLONG) delta;
230                     break;
231 #endif
232 
233                 default:
234                     //printf("Unknown relocation: %d\n", type);
235                     break;
236                 }
237             }
238 
239             // advance to next relocation block
240             relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);
241         }
242     }
243 }
244 
245 static int
246 BuildImportTable(PMEMORYMODULE module)
247 {
248     int result=1;
249     unsigned char *codeBase = module->codeBase;
250     HCUSTOMMODULE *tmp;
251 
252     PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
253     if (directory->Size > 0) {
254         PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);
255         for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) {
256             POINTER_TYPE *thunkRef;
257             FARPROC *funcRef;
258             HCUSTOMMODULE handle = module->loadLibrary((LPCSTR) (codeBase + importDesc->Name), module->userdata);
259             if (handle == NULL) {
260                 SetLastError(ERROR_MOD_NOT_FOUND);
261                 result = 0;
262                 break;
263             }
264 
265             tmp = (HCUSTOMMODULE *) realloc(module->modules, (module->numModules+1)*(sizeof(HCUSTOMMODULE)));
266             if (tmp == NULL) {
267                 module->freeLibrary(handle, module->userdata);
268                 SetLastError(ERROR_OUTOFMEMORY);
269                 result = 0;
270                 break;
271             }
272             module->modules = tmp;
273 
274             module->modules[module->numModules++] = handle;
275             if (importDesc->OriginalFirstThunk) {
276                 thunkRef = (POINTER_TYPE *) (codeBase + importDesc->OriginalFirstThunk);
277                 funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
278             } else {
279                 // no hint table
280                 thunkRef = (POINTER_TYPE *) (codeBase + importDesc->FirstThunk);
281                 funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
282             }
283             for (; *thunkRef; thunkRef++, funcRef++) {
284                 if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
285                     *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
286                 } else {
287                     PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef));
288                     *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
289                 }
290                 if (*funcRef == 0) {
291                     result = 0;
292                     break;
293                 }
294             }
295 
296             if (!result) {
297                 module->freeLibrary(handle, module->userdata);
298                 SetLastError(ERROR_PROC_NOT_FOUND);
299                 break;
300             }
301         }
302     }
303 
304     return result;
305 }
306 
307 static HCUSTOMMODULE _LoadLibrary(LPCSTR filename, void *userdata)
308 {
309     HMODULE result = LoadLibraryA(filename);
310     if (result == NULL) {
311         return NULL;
312     }
313     
314     return (HCUSTOMMODULE) result;
315 }
316 
317 static FARPROC _GetProcAddress(HCUSTOMMODULE module, LPCSTR name, void *userdata)
318 {
319     return (FARPROC) GetProcAddress((HMODULE) module, name);
320 }
321 
322 static void _FreeLibrary(HCUSTOMMODULE module, void *userdata)
323 {
324     FreeLibrary((HMODULE) module);
325 }
326 
327 HMEMORYMODULE MemoryLoadLibrary(const void *data)
328 {
329     return MemoryLoadLibraryEx(data, _LoadLibrary, _GetProcAddress, _FreeLibrary, NULL);
330 }
331 
332 HMEMORYMODULE MemoryLoadLibraryEx(const void *data,
333     CustomLoadLibraryFunc loadLibrary,
334     CustomGetProcAddressFunc getProcAddress,
335     CustomFreeLibraryFunc freeLibrary,
336     void *userdata)
337 {
338     PMEMORYMODULE result;
339     PIMAGE_DOS_HEADER dos_header;
340     PIMAGE_NT_HEADERS old_header;
341     unsigned char *code, *headers;
342     SIZE_T locationDelta;
343     DllEntryProc DllEntry;
344     BOOL successfull;
345 
346     dos_header = (PIMAGE_DOS_HEADER)data;
347     if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
348         SetLastError(ERROR_BAD_EXE_FORMAT);
349         return NULL;
350     }
351 
352     old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];
353     if (old_header->Signature != IMAGE_NT_SIGNATURE) {
354         SetLastError(ERROR_BAD_EXE_FORMAT);
355         return NULL;
356     }
357 
358     // reserve memory for image of library
359     // XXX: is it correct to commit the complete memory region at once?
360     //      calling DllEntry raises an exception if we don't...
361     code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
362         old_header->OptionalHeader.SizeOfImage,
363         MEM_RESERVE | MEM_COMMIT,
364         PAGE_READWRITE);
365 
366     if (code == NULL) {
367         // try to allocate memory at arbitrary position
368         code = (unsigned char *)VirtualAlloc(NULL,
369             old_header->OptionalHeader.SizeOfImage,
370             MEM_RESERVE | MEM_COMMIT,
371             PAGE_READWRITE);
372         if (code == NULL) {
373             SetLastError(ERROR_OUTOFMEMORY);
374             return NULL;
375         }
376     }
377     
378     result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE));
379     if (result == NULL) {
380         SetLastError(ERROR_OUTOFMEMORY);
381         VirtualFree(code, 0, MEM_RELEASE);
382         return NULL;
383     }
384 
385     result->codeBase = code;
386     result->numModules = 0;
387     result->modules = NULL;
388     result->initialized = 0;
389     result->loadLibrary = loadLibrary;
390     result->getProcAddress = getProcAddress;
391     result->freeLibrary = freeLibrary;
392     result->userdata = userdata;
393 
394     // commit memory for headers
395     headers = (unsigned char *)VirtualAlloc(code,
396         old_header->OptionalHeader.SizeOfHeaders,
397         MEM_COMMIT,
398         PAGE_READWRITE);
399     
400     // copy PE header to code
401     memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
402     result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];
403 
404     // update position
405     result->headers->OptionalHeader.ImageBase = (POINTER_TYPE)code;
406 
407     // copy sections from DLL file block to new memory location
408     CopySections((UCHAR *)data, old_header, result);
409 
410     // adjust base address of imported data
411     locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase);
412     if (locationDelta != 0) {
413         PerformBaseRelocation(result, locationDelta);
414     }
415 
416     // load required dlls and adjust function table of imports
417     if (!BuildImportTable(result)) {
418         goto error;
419     }
420 
421     // mark memory pages depending on section headers and release
422     // sections that are marked as "discardable"
423     FinalizeSections(result);
424 
425     // get entry point of loaded library
426     if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
427         DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);
428         // notify library about attaching to process
429         successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
430         if (!successfull) {
431             SetLastError(ERROR_DLL_INIT_FAILED);
432             goto error;
433         }
434         result->initialized = 1;
435     }
436 
437     return (HMEMORYMODULE)result;
438 
439 error:
440     // cleanup
441     MemoryFreeLibrary(result);
442     return NULL;
443 }
444 
445 FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name)
446 {
447     unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;
448     int idx=-1;
449     DWORD i, *nameRef;
450     WORD *ordinal;
451     PIMAGE_EXPORT_DIRECTORY exports;
452     PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
453     if (directory->Size == 0) {
454         // no export table found
455         SetLastError(ERROR_PROC_NOT_FOUND);
456         return NULL;
457     }
458 
459     exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress);
460     if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
461         // DLL doesn't export anything
462         SetLastError(ERROR_PROC_NOT_FOUND);
463         return NULL;
464     }
465 
466     // search function name in list of exported names
467     nameRef = (DWORD *) (codeBase + exports->AddressOfNames);
468     ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals);
469     for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) {
470         if (_stricmp(name, (const char *) (codeBase + (*nameRef))) == 0) {
471             idx = *ordinal;
472             break;
473         }
474     }
475 
476     if (idx == -1) {
477         // exported symbol not found
478         SetLastError(ERROR_PROC_NOT_FOUND);
479         return NULL;
480     }
481 
482     if ((DWORD)idx > exports->NumberOfFunctions) {
483         // name <-> ordinal number don't match
484         SetLastError(ERROR_PROC_NOT_FOUND);
485         return NULL;
486     }
487 
488     // AddressOfFunctions contains the RVAs to the "real" functions
489     return (FARPROC) (codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4))));
490 }
491 
492 void MemoryFreeLibrary(HMEMORYMODULE mod)
493 {
494     int i;
495     PMEMORYMODULE module = (PMEMORYMODULE)mod;
496 
497     if (module != NULL) {
498         if (module->initialized != 0) {
499             // notify library about detaching from process
500             DllEntryProc DllEntry = (DllEntryProc) (module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);
501             (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
502             module->initialized = 0;
503         }
504 
505         if (module->modules != NULL) {
506             // free previously opened libraries
507             for (i=0; i<module->numModules; i++) {
508                 if (module->modules[i] != NULL) {
509                     module->freeLibrary(module->modules[i], module->userdata);
510                 }
511             }
512 
513             free(module->modules);
514         }
515 
516         if (module->codeBase != NULL) {
517             // release memory of library
518             VirtualFree(module->codeBase, 0, MEM_RELEASE);
519         }
520 
521         HeapFree(GetProcessHeap(), 0, module);
522     }
523 }
524 
525 #define DEFAULT_LANGUAGE        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
526 
527 HMEMORYRSRC MemoryFindResource(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type)
528 {
529     return MemoryFindResourceEx(module, name, type, DEFAULT_LANGUAGE);
530 }
531 
532 static PIMAGE_RESOURCE_DIRECTORY_ENTRY _MemorySearchResourceEntry(
533     void *root,
534     PIMAGE_RESOURCE_DIRECTORY resources,
535     LPCTSTR key)
536 {
537     PIMAGE_RESOURCE_DIRECTORY_ENTRY entries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resources + 1);
538     PIMAGE_RESOURCE_DIRECTORY_ENTRY result = NULL;
539     DWORD start;
540     DWORD end;
541     DWORD middle;
542     
543     if (!IS_INTRESOURCE(key) && key[0] == TEXT('#')) {
544         // special case: resource id given as string
545         TCHAR *endpos = NULL;
546 #if defined(UNICODE)
547         long int tmpkey = (WORD) wcstol((TCHAR *) &key[1], &endpos, 10);
548 #else
549         long int tmpkey = (WORD) strtol((TCHAR *) &key[1], &endpos, 10);
550 #endif
551         if (tmpkey <= 0xffff && lstrlen(endpos) == 0) {
552             key = MAKEINTRESOURCE(tmpkey);
553         }
554     }
555     
556     // entries are stored as ordered list of named entries,
557     // followed by an ordered list of id entries - we can do
558     // a binary search to find faster...
559     if (IS_INTRESOURCE(key)) {
560         WORD check = (WORD) (POINTER_TYPE) key;
561         start = resources->NumberOfNamedEntries;
562         end = start + resources->NumberOfIdEntries;
563         
564         while (end > start) {
565             WORD entryName;
566             middle = (start + end) >> 1;
567             entryName = (WORD) entries[middle].Name;
568             if (check < entryName) {
569                 end = (end != middle ? middle : middle-1);
570             } else if (check > entryName) {
571                 start = (start != middle ? middle : middle+1);
572             } else {
573                 result = &entries[middle];
574                 break;
575             }
576         }
577     } else {
578 #if !defined(UNICODE)
579         char *searchKey = NULL;
580         int searchKeyLength = 0;
581 #endif
582         start = 0;
583         end = resources->NumberOfIdEntries;
584         while (end > start) {
585             // resource names are always stored using 16bit characters
586             int cmp;
587             PIMAGE_RESOURCE_DIR_STRING_U resourceString;
588             middle = (start + end) >> 1;
589             resourceString = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) root) + (entries[middle].Name & 0x7FFFFFFF));
590 #if !defined(UNICODE)
591             if (searchKey == NULL || searchKeyLength < resourceString->Length) {
592                 void *tmp = realloc(searchKey, resourceString->Length);
593                 if (tmp == NULL) {
594                     break;
595                 }
596                 
597                 searchKey = (char *) tmp;
598             }
599             wcstombs(searchKey, resourceString->NameString, resourceString->Length);
600             cmp = strncmp(key, searchKey, resourceString->Length);
601 #else
602             cmp = wcsncmp(key, resourceString->NameString, resourceString->Length);
603 #endif
604             if (cmp < 0) {
605                 end = (middle != end ? middle : middle-1);
606             } else if (cmp > 0) {
607                 start = (middle != start ? middle : middle+1);
608             } else {
609                 result = &entries[middle];
610                 break;
611             }
612         }
613 #if !defined(UNICODE)
614         free(searchKey);
615 #endif
616     }
617     
618     
619     return result;
620 }
621 
622 HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE module, LPCTSTR name, LPCTSTR type, WORD language)
623 {
624     unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;
625     PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE) module, IMAGE_DIRECTORY_ENTRY_RESOURCE);
626     PIMAGE_RESOURCE_DIRECTORY rootResources;
627     PIMAGE_RESOURCE_DIRECTORY nameResources;
628     PIMAGE_RESOURCE_DIRECTORY typeResources;
629     PIMAGE_RESOURCE_DIRECTORY_ENTRY foundType;
630     PIMAGE_RESOURCE_DIRECTORY_ENTRY foundName;
631     PIMAGE_RESOURCE_DIRECTORY_ENTRY foundLanguage;
632     if (directory->Size == 0) {
633         // no resource table found
634         SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
635         return NULL;
636     }
637     
638     if (language == DEFAULT_LANGUAGE) {
639         // use language from current thread
640         language = LANGIDFROMLCID(GetThreadLocale());
641     }
642 
643     // resources are stored as three-level tree
644     // - first node is the type
645     // - second node is the name
646     // - third node is the language
647     rootResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress);
648     foundType = _MemorySearchResourceEntry(rootResources, rootResources, type);
649     if (foundType == NULL) {
650         SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
651         return NULL;
652     }
653     
654     typeResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff));
655     foundName = _MemorySearchResourceEntry(rootResources, typeResources, name);
656     if (foundName == NULL) {
657         SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
658         return NULL;
659     }
660     
661     nameResources = (PIMAGE_RESOURCE_DIRECTORY) (codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff));
662     foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (LPCTSTR) (POINTER_TYPE) language);
663     if (foundLanguage == NULL) {
664         // requested language not found, use first available
665         if (nameResources->NumberOfIdEntries == 0) {
666             SetLastError(ERROR_RESOURCE_LANG_NOT_FOUND);
667             return NULL;
668         }
669         
670         foundLanguage = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (nameResources + 1);
671     }
672     
673     return (codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff));
674 }
675 
676 DWORD MemorySizeofResource(HMEMORYMODULE module, HMEMORYRSRC resource)
677 {
678     PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;
679     
680     return entry->Size;
681 }
682 
683 LPVOID MemoryLoadResource(HMEMORYMODULE module, HMEMORYRSRC resource)
684 {
685     unsigned char *codeBase = ((PMEMORYMODULE) module)->codeBase;
686     PIMAGE_RESOURCE_DATA_ENTRY entry = (PIMAGE_RESOURCE_DATA_ENTRY) resource;
687     
688     return codeBase + entry->OffsetToData;
689 }
690 
691 int
692 MemoryLoadString(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize)
693 {
694     return MemoryLoadStringEx(module, id, buffer, maxsize, DEFAULT_LANGUAGE);
695 }
696 
697 int
698 MemoryLoadStringEx(HMEMORYMODULE module, UINT id, LPTSTR buffer, int maxsize, WORD language)
699 {
700     HMEMORYRSRC resource;
701     PIMAGE_RESOURCE_DIR_STRING_U data;
702     DWORD size;
703     if (maxsize == 0) {
704         return 0;
705     }
706     
707     resource = MemoryFindResourceEx(module, MAKEINTRESOURCE((id >> 4) + 1), RT_STRING, language);
708     if (resource == NULL) {
709         buffer[0] = 0;
710         return 0;
711     }
712     
713     data = (PIMAGE_RESOURCE_DIR_STRING_U)MemoryLoadResource(module, resource);
714     id = id & 0x0f;
715     while (id--) {
716         data = (PIMAGE_RESOURCE_DIR_STRING_U) (((char *) data) + (data->Length + 1) * sizeof(WCHAR));
717     }
718     if (data->Length == 0) {
719         SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
720         buffer[0] = 0;
721         return 0;
722     }
723     
724     size = data->Length;
725     if (size >= (DWORD) maxsize) {
726         size = maxsize;
727     } else {
728         buffer[size] = 0;
729     }
730 #if defined(UNICODE)
731     wcsncpy(buffer, data->NameString, size);
732 #else
733     wcstombs(buffer, data->NameString, size);
734 #endif
735     return size;
736 }

 

标签:RESOURCE,module,codeBase,MemLoadLibraryCPP,result,PIMAGE,NULL
来源: https://www.cnblogs.com/admrty/p/15270936.html