From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- cryptopp/dllloader.cpp | 280 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 cryptopp/dllloader.cpp (limited to 'cryptopp/dllloader.cpp') diff --git a/cryptopp/dllloader.cpp b/cryptopp/dllloader.cpp new file mode 100644 index 0000000..7dfea7e --- /dev/null +++ b/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; iNumberOfSections; 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; iVirtualAddress+((*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; iNumberOfSections; 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