diff options
Diffstat (limited to 'plugins/CryptoPP/dllloader.cpp')
-rw-r--r-- | plugins/CryptoPP/dllloader.cpp | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/plugins/CryptoPP/dllloader.cpp b/plugins/CryptoPP/dllloader.cpp new file mode 100644 index 0000000000..7dfea7ed0c --- /dev/null +++ b/plugins/CryptoPP/dllloader.cpp @@ -0,0 +1,280 @@ +/*
+* Loading dll from memory
+*
+* Written by Vitaliy Shitts (vit@shittz.ru)
+* Copyright (c) 2004 Vitaliy Shittz.
+*
+* THIS CODE IS PROVIDED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED
+* OR IMPLIED. YOU USE AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO LIABILITY
+* IF IT CAUSES ANY DAMAGE TO YOU OR YOUR COMPUTER WHATSOEVER.
+*
+* Beware of bugs.
+*/
+
+#include "commonheaders.h"
+
+#ifdef DLL_FROM_RESOURCE
+
+#ifndef MIN
+# define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+typedef BOOL (WINAPI *DLLMAIN)(HINSTANCE,DWORD,LPVOID);
+
+#pragma warning (push)
+#pragma warning (disable: 4311; disable: 4312; disable: 4018)
+
+DWORD GetSectionProtection(DWORD sc)
+{
+ DWORD dwResult=0;
+ if (sc & IMAGE_SCN_MEM_NOT_CACHED)
+ dwResult |= PAGE_NOCACHE;
+
+ if (sc & IMAGE_SCN_MEM_EXECUTE)
+ {
+ if (sc & IMAGE_SCN_MEM_READ)
+ {
+ if (sc & IMAGE_SCN_MEM_WRITE)
+ dwResult |= PAGE_EXECUTE_READWRITE;
+ else
+ dwResult |= PAGE_EXECUTE_READ;
+ }
+ else
+ {
+ if (sc & IMAGE_SCN_MEM_WRITE)
+ dwResult |= PAGE_EXECUTE_WRITECOPY;
+ else
+ dwResult |= PAGE_EXECUTE;
+ }
+ }
+ else
+ {
+ if (sc & IMAGE_SCN_MEM_READ)
+ {
+ if (sc & IMAGE_SCN_MEM_WRITE)
+ dwResult|=PAGE_READWRITE;
+ else
+ dwResult|=PAGE_READONLY;
+ }
+ else
+ {
+ if (sc & IMAGE_SCN_MEM_WRITE)
+ dwResult|=PAGE_WRITECOPY;
+ else
+ dwResult|=PAGE_NOACCESS;
+ }
+ }
+
+ return dwResult;
+}
+
+inline BOOL IsImportByOrdinal(DWORD ImportDescriptor)
+{
+ return (ImportDescriptor & IMAGE_ORDINAL_FLAG32)!=0;
+}
+
+
+HMODULE MemLoadLibrary(PBYTE data)
+{
+ IMAGE_FILE_HEADER *pFileHeader = NULL;
+ IMAGE_OPTIONAL_HEADER *pOptionalHeader = NULL;
+ IMAGE_SECTION_HEADER *pSectionHeader = NULL;
+ IMAGE_IMPORT_DESCRIPTOR *pImportDscrtr = NULL;
+ USHORT e_lfanew = *((USHORT*)(data+0x3c));
+ PCHAR ImageBase = NULL;
+ PCHAR SectionBase = NULL;
+
+ DWORD dwSize, dwOldProt, ImageBaseDelta;
+ int i;
+
+ pFileHeader = (IMAGE_FILE_HEADER *)(data+e_lfanew+4);
+ pOptionalHeader = (IMAGE_OPTIONAL_HEADER *)(data+e_lfanew+4+sizeof(IMAGE_FILE_HEADER));
+ if (pOptionalHeader->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ return NULL;
+
+ // Let's try to reserv memory
+ ImageBase = (PCHAR)VirtualAlloc(
+ (PVOID)pOptionalHeader->ImageBase,
+ pOptionalHeader->SizeOfImage,
+ MEM_RESERVE,PAGE_NOACCESS);
+
+ if(ImageBase==NULL)
+ {
+ ImageBase=(PCHAR)VirtualAlloc(NULL,
+ pOptionalHeader->SizeOfImage,
+ MEM_RESERVE,PAGE_NOACCESS);
+ if(ImageBase==NULL)
+ return NULL;
+ }
+
+ // copy the header
+ SectionBase=(PCHAR)VirtualAlloc(ImageBase,
+ pOptionalHeader->SizeOfHeaders,
+ MEM_COMMIT,PAGE_READWRITE);
+ memcpy(SectionBase,data,pOptionalHeader->SizeOfHeaders);
+ // Do headers read-only (to be on the safe side)
+ VirtualProtect(SectionBase,pOptionalHeader->SizeOfHeaders,PAGE_READONLY,&dwOldProt);
+
+ // find sections ...
+ pSectionHeader = (IMAGE_SECTION_HEADER *)(pOptionalHeader+1);
+ for (i=0; i<pFileHeader->NumberOfSections; i++)
+ {
+ SectionBase = (PCHAR)VirtualAlloc(
+ ImageBase+pSectionHeader[i].VirtualAddress,
+ pSectionHeader[i].Misc.VirtualSize,
+ MEM_COMMIT,PAGE_READWRITE);
+ if (SectionBase==NULL)
+ {
+ VirtualFree(ImageBase, 0, MEM_RELEASE);
+ return NULL;
+ }
+ // ... and copy initialization data
+ SectionBase = ImageBase+pSectionHeader[i].VirtualAddress;
+ dwSize = MIN(pSectionHeader[i].SizeOfRawData,pSectionHeader[i].Misc.VirtualSize);
+ memcpy(SectionBase, data+pSectionHeader[i].PointerToRawData,dwSize);
+ }
+
+ // check addersses
+ ImageBaseDelta = (DWORD)ImageBase-pOptionalHeader->ImageBase;
+ if (ImageBaseDelta!=0 &&
+ pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress!=0
+ )
+ {
+ IMAGE_BASE_RELOCATION *pBaseReloc = (IMAGE_BASE_RELOCATION *)(ImageBase+
+ pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
+ IMAGE_BASE_RELOCATION *pBaseReloc0 = pBaseReloc;
+ WORD *wPointer = NULL;
+ DWORD dwModCount;
+ int i;
+
+ while ((DWORD)pBaseReloc0-(DWORD)pBaseReloc < pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
+ {
+ dwModCount = (pBaseReloc0->SizeOfBlock-sizeof(pBaseReloc))/2;
+ wPointer = (WORD *)(pBaseReloc+1);
+ for (i=0; i<dwModCount; i++, wPointer++)
+ if ((*wPointer & 0xf000) !=0)
+ {
+ PDWORD pdw = (PDWORD)(ImageBase+pBaseReloc0->VirtualAddress+((*wPointer)&0xfff));
+ (*pdw)+=ImageBaseDelta;
+ }
+ pBaseReloc = (IMAGE_BASE_RELOCATION *)wPointer;
+ }
+ }
+ else if (ImageBaseDelta!=0)
+ {
+ VirtualFree(ImageBase, 0, MEM_RELEASE);
+ return NULL;
+ }
+
+ pImportDscrtr = (IMAGE_IMPORT_DESCRIPTOR *)(ImageBase+
+ pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+
+ for (;pImportDscrtr->Name!=0; pImportDscrtr++)
+ {
+ PCHAR pLibName = (PCHAR)(ImageBase+pImportDscrtr->Name);
+ PCHAR pImortName = NULL;
+ HMODULE hLibModule = LoadLibrary(pLibName);
+ DWORD *pImport = NULL,
+ *pAddress = NULL;
+ DWORD ProcAddress;
+
+ pAddress=(DWORD *)(ImageBase+pImportDscrtr->/*Original*/FirstThunk);
+ if (pImportDscrtr->TimeDateStamp==0)
+ pImport=(DWORD *)(ImageBase+pImportDscrtr->FirstThunk);
+ else
+ pImport=(DWORD *)(ImageBase+pImportDscrtr->OriginalFirstThunk);
+ for (i=0; pImport[i]!=0; i++)
+ {
+ if (IsImportByOrdinal(pImport[i]))
+ ProcAddress=(DWORD)GetProcAddress(hLibModule, (PCHAR)(pImport[i]&0xFFFF));
+ else // import by name
+ {
+ pImortName=(PCHAR)(ImageBase+(pImport[i])+2);
+ ProcAddress=(DWORD)GetProcAddress(hLibModule, pImortName);
+ }
+ pAddress[i]=ProcAddress;
+ }
+ }
+
+ // set section protection
+ for (i=0; i<pFileHeader->NumberOfSections; i++)
+ VirtualProtect((PVOID)(ImageBase+pSectionHeader[i].VirtualAddress),
+ pSectionHeader[i].Misc.VirtualSize,
+ GetSectionProtection(pSectionHeader[i].Characteristics),
+ &dwOldProt);
+
+ // call DLLMain
+ if (pOptionalHeader->AddressOfEntryPoint!=0)
+ {
+ DLLMAIN dllMain=(DLLMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
+ if (!dllMain((HMODULE)ImageBase, DLL_PROCESS_ATTACH, NULL))
+ {
+ VirtualFree(ImageBase, 0, MEM_RELEASE);
+ return NULL;
+ }
+ }
+
+ return (HMODULE)ImageBase;
+}
+
+
+BOOL MemFreeLibrary(HMODULE hDll)
+{
+ PIMAGE_DOS_HEADER pDosHeader = NULL;
+ PIMAGE_FILE_HEADER pFileHeader = NULL;
+ PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
+
+ pDosHeader=(PIMAGE_DOS_HEADER)hDll;
+ pFileHeader=(PIMAGE_FILE_HEADER)(((PBYTE)hDll)+pDosHeader->e_lfanew+4);
+ pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(pFileHeader+1);
+
+// Call to DllMain
+ if (pOptionalHeader->AddressOfEntryPoint!=0)
+ {
+ DLLMAIN dllMain=(DLLMAIN)((PBYTE)hDll+pOptionalHeader->AddressOfEntryPoint);
+ dllMain(hDll, DLL_PROCESS_DETACH, NULL);
+ }
+// free loaded librares
+ PIMAGE_IMPORT_DESCRIPTOR pImportDscrtr = (IMAGE_IMPORT_DESCRIPTOR *)((PBYTE)hDll+
+ pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ for (;pImportDscrtr->Name!=0; pImportDscrtr++)
+ {
+ PCHAR pLibName = (PCHAR)((PBYTE)hDll+pImportDscrtr->Name);
+ HMODULE hLib = GetModuleHandle(pLibName);
+ FreeLibrary(hLib);
+ }
+
+ return VirtualFree((PVOID)hDll, 0, MEM_RELEASE);
+}
+
+FARPROC MemGetProcAddress(HMODULE hDll, LPCTSTR fname)
+{
+ PIMAGE_DOS_HEADER pDosHeader = NULL;
+ PIMAGE_FILE_HEADER pFileHeader = NULL;
+ PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
+
+ pDosHeader=(PIMAGE_DOS_HEADER)hDll;
+ pFileHeader=(PIMAGE_FILE_HEADER)(((PBYTE)hDll)+pDosHeader->e_lfanew+4);
+ pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(pFileHeader+1);
+
+ DWORD dwExpRVA = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ PBYTE pb = (PBYTE)hDll;
+ PIMAGE_EXPORT_DIRECTORY pExportDir=(PIMAGE_EXPORT_DIRECTORY)(pb+dwExpRVA);
+ PDWORD pNamesRVA=(PDWORD)(pb+pExportDir->AddressOfNames);
+ PDWORD pFuncRVA=(PDWORD)(pb+pExportDir->AddressOfFunctions);
+ PWORD ord=(PWORD)(pb+pExportDir->AddressOfNameOrdinals);
+
+ DWORD dwFunc=pExportDir->NumberOfNames;
+ for (int i=0; i<dwFunc; i++)
+ {
+ PCHAR name =((PCHAR)(pb+pNamesRVA[i]));
+ if (0==strcmp(fname, name))
+ return (FARPROC)(pb+pFuncRVA[ord[i]]);
+ }
+
+ return NULL;
+}
+
+#pragma warning (pop)
+
+#endif
|