Advertisement
Guest User

Untitled

a guest
Apr 9th, 2016
2,575
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.12 KB | None | 0 0
  1. memlib.cpp
  2. [CODE]#define _CRT_SECURE_NO_WARNINGS
  3.  
  4. #include <windows.h>
  5. #include <winnt.h>
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <tchar.h>
  9. #include <iostream>
  10. #include <fstream>
  11.  
  12. #ifdef DEBUG_OUTPUT
  13. #include <stdio.h>
  14. #endif
  15.  
  16. #if _MSC_VER
  17. // Disable warning about data -> function pointer conversion
  18. #pragma warning(disable:4055)
  19. #endif
  20.  
  21. #define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
  22.  
  23. #include "MemLoadLibrary.h"
  24.  
  25. #define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
  26. #define ALIGN_DOWN(address, alignment) (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))
  27. #define ALIGN_VALUE_UP(value, alignment) (((value) + (alignment) - 1) & ~((alignment) - 1))
  28.  
  29. BOOL
  30. CWin32PE::CheckSize(size_t size, size_t expected) {
  31. if (size < expected) {
  32. SetLastError(ERROR_INVALID_DATA);
  33. return FALSE;
  34. }
  35.  
  36. return TRUE;
  37. }
  38.  
  39. BOOL CWin32PE::CopySections(const unsigned char *data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
  40. {
  41. int i, section_size;
  42. unsigned char *codeBase = module->codeBase;
  43. unsigned char *dest;
  44. PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
  45. for (i = 0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
  46. if (section->SizeOfRawData == 0) {
  47. // section doesn't contain data in the dll itself, but may define
  48. // uninitialized data
  49. section_size = old_headers->OptionalHeader.SectionAlignment;
  50. if (section_size > 0) {
  51. dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
  52. section_size,
  53. MEM_COMMIT,
  54. PAGE_READWRITE);
  55. if (dest == NULL) {
  56. return FALSE;
  57. }
  58.  
  59. // Always use position from file to support alignments smaller
  60. // than page size.
  61. dest = codeBase + section->VirtualAddress;
  62. section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
  63. memset(dest, 0, section_size);
  64. }
  65.  
  66. // section is empty
  67. continue;
  68. }
  69.  
  70. if (!CheckSize(size, section->PointerToRawData + section->SizeOfRawData)) {
  71. return FALSE;
  72. }
  73.  
  74. // commit memory block and copy data from dll
  75. dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
  76. section->SizeOfRawData,
  77. MEM_COMMIT,
  78. PAGE_READWRITE);
  79. if (dest == NULL) {
  80. return FALSE;
  81. }
  82.  
  83. // Always use position from file to support alignments smaller
  84. // than page size.
  85. dest = codeBase + section->VirtualAddress;
  86. memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
  87. section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
  88. }
  89.  
  90. return TRUE;
  91. }
  92.  
  93. // Protection flags for memory pages (Executable, Readable, Writeable)
  94. static int ProtectionFlags[2][2][2] = {
  95. {
  96. // not executable
  97. { PAGE_NOACCESS, PAGE_WRITECOPY },
  98. { PAGE_READONLY, PAGE_READWRITE },
  99. }, {
  100. // executable
  101. { PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY },
  102. { PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE },
  103. },
  104. };
  105.  
  106. DWORD
  107. CWin32PE::GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {
  108. DWORD size = section->SizeOfRawData;
  109. if (size == 0) {
  110. if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
  111. size = module->headers->OptionalHeader.SizeOfInitializedData;
  112. }
  113. else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
  114. size = module->headers->OptionalHeader.SizeOfUninitializedData;
  115. }
  116. }
  117. return size;
  118. }
  119.  
  120. BOOL
  121. CWin32PE::FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) {
  122. DWORD protect, oldProtect;
  123. BOOL executable;
  124. BOOL readable;
  125. BOOL writeable;
  126.  
  127. if (sectionData->size == 0) {
  128. return TRUE;
  129. }
  130.  
  131. if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
  132. // section is not needed any more and can safely be freed
  133. if (sectionData->address == sectionData->alignedAddress &&
  134. (sectionData->last ||
  135. module->headers->OptionalHeader.SectionAlignment == module->pageSize ||
  136. (sectionData->size % module->pageSize) == 0)
  137. ) {
  138. // Only allowed to decommit whole pages
  139. VirtualFree(sectionData->address, sectionData->size, MEM_DECOMMIT);
  140. }
  141. return TRUE;
  142. }
  143.  
  144. // determine protection flags based on characteristics
  145. executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
  146. readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0;
  147. writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0;
  148. protect = ProtectionFlags[executable][readable][writeable];
  149. if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
  150. protect |= PAGE_NOCACHE;
  151. }
  152.  
  153. // change memory access flags
  154. if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) {
  155. #ifdef DEBUG_OUTPUT
  156. OutputLastError("Error protecting memory page")
  157. #endif
  158. return FALSE;
  159. }
  160.  
  161. return TRUE;
  162. }
  163.  
  164. BOOL
  165. CWin32PE::FinalizeSections(PMEMORYMODULE module)
  166. {
  167. int i;
  168. PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
  169. #ifdef _WIN64
  170. uintptr_t imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);
  171. #else
  172. #define imageOffset 0
  173. #endif
  174. SECTIONFINALIZEDATA sectionData;
  175. sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
  176. sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize);
  177. sectionData.size = GetRealSectionSize(module, section);
  178. sectionData.characteristics = section->Characteristics;
  179. sectionData.last = FALSE;
  180. section++;
  181.  
  182. // loop through all sections and change access flags
  183. for (i = 1; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
  184. LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
  185. LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize);
  186. DWORD sectionSize = GetRealSectionSize(module, section);
  187. // Combine access flags of all sections that share a page
  188. // TODO(fancycode): We currently share flags of a trailing large section
  189. // with the page of a first small section. This should be optimized.
  190. if (sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address + sectionData.size >(uintptr_t) alignedAddress) {
  191. // Section shares page with previous
  192. if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) {
  193. sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE;
  194. }
  195. else {
  196. sectionData.characteristics |= section->Characteristics;
  197. }
  198. sectionData.size = (((uintptr_t)sectionAddress) + sectionSize) - (uintptr_t)sectionData.address;
  199. continue;
  200. }
  201.  
  202. if (!FinalizeSection(module, &sectionData)) {
  203. return FALSE;
  204. }
  205. sectionData.address = sectionAddress;
  206. sectionData.alignedAddress = alignedAddress;
  207. sectionData.size = sectionSize;
  208. sectionData.characteristics = section->Characteristics;
  209. }
  210. sectionData.last = TRUE;
  211. if (!FinalizeSection(module, &sectionData)) {
  212. return FALSE;
  213. }
  214. #ifndef _WIN64
  215. #undef imageOffset
  216. #endif
  217. return TRUE;
  218. }
  219.  
  220. BOOL
  221. CWin32PE::ExecuteTLS(PMEMORYMODULE module)
  222. {
  223. unsigned char *codeBase = module->codeBase;
  224. PIMAGE_TLS_DIRECTORY tls;
  225. PIMAGE_TLS_CALLBACK* callback;
  226.  
  227. PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS);
  228. if (directory->VirtualAddress == 0) {
  229. return TRUE;
  230. }
  231.  
  232. tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress);
  233. callback = (PIMAGE_TLS_CALLBACK *)tls->AddressOfCallBacks;
  234. if (callback) {
  235. while (*callback) {
  236. (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL);
  237. callback++;
  238. }
  239. }
  240. return TRUE;
  241. }
  242.  
  243. BOOL
  244. CWin32PE::PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta)
  245. {
  246. unsigned char *codeBase = module->codeBase;
  247. PIMAGE_BASE_RELOCATION relocation;
  248.  
  249. PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
  250. if (directory->Size == 0) {
  251. return (delta == 0);
  252. }
  253.  
  254. relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress);
  255. for (; relocation->VirtualAddress > 0;) {
  256. DWORD i;
  257. unsigned char *dest = codeBase + relocation->VirtualAddress;
  258. unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
  259. for (i = 0; i<((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) {
  260. DWORD *patchAddrHL;
  261. #ifdef _WIN64
  262. ULONGLONG *patchAddr64;
  263. #endif
  264. int type, offset;
  265.  
  266. // the upper 4 bits define the type of relocation
  267. type = *relInfo >> 12;
  268. // the lower 12 bits define the offset
  269. offset = *relInfo & 0xfff;
  270.  
  271. switch (type)
  272. {
  273. case IMAGE_REL_BASED_ABSOLUTE:
  274. // skip relocation
  275. break;
  276.  
  277. case IMAGE_REL_BASED_HIGHLOW:
  278. // change complete 32 bit address
  279. patchAddrHL = (DWORD *)(dest + offset);
  280. *patchAddrHL += (DWORD)delta;
  281. break;
  282.  
  283. #ifdef _WIN64
  284. case IMAGE_REL_BASED_DIR64:
  285. patchAddr64 = (ULONGLONG *)(dest + offset);
  286. *patchAddr64 += (ULONGLONG)delta;
  287. break;
  288. #endif
  289.  
  290. default:
  291. //printf("Unknown relocation: %d\n", type);
  292. break;
  293. }
  294. }
  295.  
  296. // advance to next relocation block
  297. relocation = (PIMAGE_BASE_RELOCATION)(((char *)relocation) + relocation->SizeOfBlock);
  298. }
  299. return TRUE;
  300. }
  301.  
  302. BOOL
  303. CWin32PE::BuildImportTable(PMEMORYMODULE module)
  304. {
  305. unsigned char *codeBase = module->codeBase;
  306. PIMAGE_IMPORT_DESCRIPTOR importDesc;
  307. BOOL result = TRUE;
  308.  
  309. PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
  310. if (directory->Size == 0) {
  311. return TRUE;
  312. }
  313.  
  314. importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress);
  315. for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++) {
  316. uintptr_t *thunkRef;
  317. FARPROC *funcRef;
  318. HCUSTOMMODULE *tmp;
  319. HCUSTOMMODULE handle = module->loadLibrary((LPCSTR)(codeBase + importDesc->Name), module->userdata);
  320. if (handle == NULL) {
  321. SetLastError(ERROR_MOD_NOT_FOUND);
  322. result = FALSE;
  323. break;
  324. }
  325.  
  326. tmp = (HCUSTOMMODULE *)realloc(module->modules, (module->numModules + 1)*(sizeof(HCUSTOMMODULE)));
  327. if (tmp == NULL) {
  328. module->freeLibrary(handle, module->userdata);
  329. SetLastError(ERROR_OUTOFMEMORY);
  330. result = FALSE;
  331. break;
  332. }
  333. module->modules = tmp;
  334.  
  335. module->modules[module->numModules++] = handle;
  336. if (importDesc->OriginalFirstThunk) {
  337. thunkRef = (uintptr_t *)(codeBase + importDesc->OriginalFirstThunk);
  338. funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk);
  339. }
  340. else {
  341. // no hint table
  342. thunkRef = (uintptr_t *)(codeBase + importDesc->FirstThunk);
  343. funcRef = (FARPROC *)(codeBase + importDesc->FirstThunk);
  344. }
  345. for (; *thunkRef; thunkRef++, funcRef++) {
  346. if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
  347. *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
  348. }
  349. else {
  350. PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef));
  351. *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
  352. }
  353. if (*funcRef == 0) {
  354. result = FALSE;
  355. break;
  356. }
  357. }
  358.  
  359. if (!result) {
  360. module->freeLibrary(handle, module->userdata);
  361. SetLastError(ERROR_PROC_NOT_FOUND);
  362. break;
  363. }
  364. }
  365.  
  366. return result;
  367. }
  368.  
  369.  
  370. HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void *userdata)
  371. {
  372. HMODULE result;
  373. UNREFERENCED_PARAMETER(userdata);
  374. result = LoadLibraryA(filename);
  375. if (result == NULL) {
  376. return NULL;
  377. }
  378.  
  379. return (HCUSTOMMODULE)result;
  380. }
  381.  
  382. FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, void *userdata)
  383. {
  384. UNREFERENCED_PARAMETER(userdata);
  385. return (FARPROC)GetProcAddress((HMODULE)module, name);
  386. }
  387.  
  388. void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void *userdata)
  389. {
  390. UNREFERENCED_PARAMETER(userdata);
  391. FreeLibrary((HMODULE)module);
  392. }
  393.  
  394.  
  395. HANDLE CLoad::MemLoadLibraryEx(const void *data, size_t size,
  396. MemLoadLibraryFn loadLibrary,
  397. MemGetProcAddressFn getProcAddress,
  398. MemFreeLibraryFn freeLibrary,
  399. void *userdata)
  400. {
  401. PMEMORYMODULE result = NULL;
  402. PIMAGE_DOS_HEADER dos_header;
  403. PIMAGE_NT_HEADERS old_header;
  404. unsigned char *code, *headers;
  405. ptrdiff_t locationDelta;
  406. SYSTEM_INFO sysInfo;
  407. PIMAGE_SECTION_HEADER section;
  408. DWORD i;
  409. size_t optionalSectionSize;
  410. size_t lastSectionEnd = 0;
  411. size_t alignedImageSize;
  412.  
  413. if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
  414. return NULL;
  415. }
  416. dos_header = (PIMAGE_DOS_HEADER)data;
  417. if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
  418. SetLastError(ERROR_BAD_EXE_FORMAT);
  419. return NULL;
  420. }
  421.  
  422. if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) {
  423. return NULL;
  424. }
  425. old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];
  426. if (old_header->Signature != IMAGE_NT_SIGNATURE) {
  427. SetLastError(ERROR_BAD_EXE_FORMAT);
  428. return NULL;
  429. }
  430.  
  431. #ifdef _WIN64
  432. if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
  433. #else
  434. if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
  435. #endif
  436. SetLastError(ERROR_BAD_EXE_FORMAT);
  437. return NULL;
  438. }
  439.  
  440. if (old_header->OptionalHeader.SectionAlignment & 1) {
  441. // Only support section alignments that are a multiple of 2
  442. SetLastError(ERROR_BAD_EXE_FORMAT);
  443. return NULL;
  444. }
  445.  
  446. section = IMAGE_FIRST_SECTION(old_header);
  447. optionalSectionSize = old_header->OptionalHeader.SectionAlignment;
  448. for (i = 0; i<old_header->FileHeader.NumberOfSections; i++, section++) {
  449. size_t endOfSection;
  450. if (section->SizeOfRawData == 0) {
  451. // Section without data in the DLL
  452. endOfSection = section->VirtualAddress + optionalSectionSize;
  453. }
  454. else {
  455. endOfSection = section->VirtualAddress + section->SizeOfRawData;
  456. }
  457.  
  458. if (endOfSection > lastSectionEnd) {
  459. lastSectionEnd = endOfSection;
  460. }
  461. }
  462.  
  463. GetNativeSystemInfo(&sysInfo);
  464. alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
  465. if (alignedImageSize != ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) {
  466. SetLastError(ERROR_BAD_EXE_FORMAT);
  467. return NULL;
  468. }
  469.  
  470. // reserve memory for image of library
  471. // XXX: is it correct to commit the complete memory region at once?
  472. // calling DllEntry raises an exception if we don't...
  473. code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
  474. alignedImageSize,
  475. MEM_RESERVE | MEM_COMMIT,
  476. PAGE_READWRITE);
  477.  
  478. if (code == NULL) {
  479. // try to allocate memory at arbitrary position
  480. code = (unsigned char *)VirtualAlloc(NULL,
  481. alignedImageSize,
  482. MEM_RESERVE | MEM_COMMIT,
  483. PAGE_READWRITE);
  484. if (code == NULL) {
  485. SetLastError(ERROR_OUTOFMEMORY);
  486. return NULL;
  487. }
  488. }
  489.  
  490. result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
  491. if (result == NULL) {
  492. VirtualFree(code, 0, MEM_RELEASE);
  493. SetLastError(ERROR_OUTOFMEMORY);
  494. return NULL;
  495. }
  496.  
  497. result->codeBase = code;
  498. result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;
  499. result->loadLibrary = loadLibrary;
  500. result->getProcAddress = getProcAddress;
  501. result->freeLibrary = freeLibrary;
  502. result->userdata = userdata;
  503. result->pageSize = sysInfo.dwPageSize;
  504.  
  505. if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
  506. goto error;
  507. }
  508.  
  509. // commit memory for headers
  510. headers = (unsigned char *)VirtualAlloc(code,
  511. old_header->OptionalHeader.SizeOfHeaders,
  512. MEM_COMMIT,
  513. PAGE_READWRITE);
  514.  
  515. // copy PE header to code
  516. memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders);
  517. result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];
  518.  
  519. // update position
  520. result->headers->OptionalHeader.ImageBase = (uintptr_t)code;
  521.  
  522. // copy sections from DLL file block to new memory location
  523. if (!CopySections((const unsigned char *)data, size, old_header, result)) {
  524. goto error;
  525. }
  526.  
  527. // adjust base address of imported data
  528. locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase);
  529. if (locationDelta != 0) {
  530. result->isRelocated = PerformBaseRelocation(result, locationDelta);
  531. }
  532. else {
  533. result->isRelocated = TRUE;
  534. }
  535.  
  536. // load required dlls and adjust function table of imports
  537. if (!BuildImportTable(result)) {
  538. goto error;
  539. }
  540.  
  541. // mark memory pages depending on section headers and release
  542. // sections that are marked as "discardable"
  543. if (!FinalizeSections(result)) {
  544. goto error;
  545. }
  546.  
  547. // TLS callbacks are executed BEFORE the main loading
  548. if (!ExecuteTLS(result)) {
  549. goto error;
  550. }
  551.  
  552. // get entry point of loaded library
  553. if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
  554. if (result->isDLL) {
  555. DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
  556. // notify library about attaching to process
  557. BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
  558. if (!successfull) {
  559. SetLastError(ERROR_DLL_INIT_FAILED);
  560. goto error;
  561. }
  562. result->initialized = TRUE;
  563. }
  564. else {
  565. result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
  566. }
  567. }
  568. else {
  569. result->exeEntry = NULL;
  570. }
  571.  
  572. return (HANDLE)result;
  573.  
  574. error:
  575. // cleanup
  576. FreeLibraryFromMemory(result);
  577. return NULL;
  578. }
  579.  
  580. HANDLE CLoad::LoadFromMemory(const void *data, size_t size)
  581. {
  582. return MemLoadLibraryEx(data, size, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL);
  583. }
  584.  
  585. FARPROC CLoad::GetProcAddressFromMemory(HANDLE module, LPCSTR name)
  586. {
  587. unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;
  588. DWORD idx = 0;
  589. PIMAGE_EXPORT_DIRECTORY exports;
  590. PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
  591. if (directory->Size == 0) {
  592. // no export table found
  593. SetLastError(ERROR_PROC_NOT_FOUND);
  594. return NULL;
  595. }
  596.  
  597. exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress);
  598. if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
  599. // DLL doesn't export anything
  600. SetLastError(ERROR_PROC_NOT_FOUND);
  601. return NULL;
  602. }
  603.  
  604. if (HIWORD(name) == 0) {
  605. // load function by ordinal value
  606. if (LOWORD(name) < exports->Base) {
  607. SetLastError(ERROR_PROC_NOT_FOUND);
  608. return NULL;
  609. }
  610.  
  611. idx = LOWORD(name) - exports->Base;
  612. }
  613. else {
  614. // search function name in list of exported names
  615. DWORD i;
  616. DWORD *nameRef = (DWORD *)(codeBase + exports->AddressOfNames);
  617. WORD *ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals);
  618. BOOL found = FALSE;
  619. for (i = 0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) {
  620. if (_stricmp(name, (const char *)(codeBase + (*nameRef))) == 0) {
  621. idx = *ordinal;
  622. found = TRUE;
  623. break;
  624. }
  625. }
  626.  
  627. if (!found) {
  628. // exported symbol not found
  629. SetLastError(ERROR_PROC_NOT_FOUND);
  630. return NULL;
  631. }
  632. }
  633.  
  634. if (idx > exports->NumberOfFunctions) {
  635. // name <-> ordinal number don't match
  636. SetLastError(ERROR_PROC_NOT_FOUND);
  637. return NULL;
  638. }
  639.  
  640. // AddressOfFunctions contains the RVAs to the "real" functions
  641. return (FARPROC)(LPVOID)(codeBase + (*(DWORD *)(codeBase + exports->AddressOfFunctions + (idx * 4))));
  642. }
  643.  
  644. void CLoad::FreeLibraryFromMemory(HANDLE mod)
  645. {
  646. PMEMORYMODULE module = (PMEMORYMODULE)mod;
  647.  
  648. if (module == NULL) {
  649. return;
  650. }
  651. if (module->initialized) {
  652. // notify library about detaching from process
  653. DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);
  654. (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
  655. }
  656.  
  657. if (module->modules != NULL) {
  658. // free previously opened libraries
  659. int i;
  660. for (i = 0; i<module->numModules; i++) {
  661. if (module->modules[i] != NULL) {
  662. module->freeLibrary(module->modules[i], module->userdata);
  663. }
  664. }
  665.  
  666. free(module->modules);
  667. }
  668.  
  669. if (module->codeBase != NULL) {
  670. // release memory of library
  671. VirtualFree(module->codeBase, 0, MEM_RELEASE);
  672. }
  673.  
  674. HeapFree(GetProcessHeap(), 0, module);
  675. }
  676.  
  677. int CLoad::CallEntryPointFromMemory(HANDLE mod)
  678. {
  679. PMEMORYMODULE module = (PMEMORYMODULE)mod;
  680.  
  681. if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) {
  682. return -1;
  683. }
  684.  
  685. return module->exeEntry();
  686. }
  687.  
  688. HANDLE CLoad::LoadFromFile(LPCSTR filename)
  689. {
  690. HANDLE Module;
  691. std::streampos size;
  692. char * memblock;
  693. std::fstream file(filename, std::ios::in | std::ios::binary | std::ios::ate);
  694. if (file.is_open())
  695. {
  696. size = file.tellg();
  697. memblock = new char[size];
  698. file.seekg(0, std::ios::beg);
  699. file.read(memblock, size);
  700. file.close();
  701. Module = LoadFromMemory(memblock, size);
  702. delete[] memblock;
  703. return Module;
  704. }
  705. else {
  706. return 0;
  707. }
  708. }
  709.  
  710. HANDLE CLoad::LoadFromResources(int IDD_RESOUCE)
  711. {
  712. HGLOBAL hResData;
  713. HRSRC hResInfo;
  714. void *pvRes;
  715. DWORD dwSize;
  716. void* lpMemory;
  717. HMODULE hModule = GetModuleHandle(NULL);
  718.  
  719. if (((hResInfo = FindResource(hModule, MAKEINTRESOURCE(IDD_RESOUCE), L"DLL")) != NULL) && ((hResData = LoadResource(hModule, hResInfo)) != NULL) && ((pvRes = LockResource(hResData)) != NULL))
  720. {
  721. dwSize = SizeofResource(hModule, hResInfo);
  722. lpMemory = (char*)malloc(dwSize);
  723. memset(lpMemory, 0, dwSize);
  724. memcpy(lpMemory, pvRes, dwSize);
  725. return lpMemory;
  726. }
  727. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement