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 CRemoteLoader::ProcessSections( PVOID BaseAddress, PVOID RemoteAddress, BOOL MapPEHeader ) { IMAGE_NT_HEADERS* ImageNtHeaders = ToNts( BaseAddress ); if( ImageNtHeaders == NULL ) return FALSE; // Write PE header if( MapPEHeader ) { if( WriteProcessMemory( GetProcess(), RemoteAddress, BaseAddress, ImageNtHeaders->OptionalHeader.SizeOfHeaders, NULL ) == FALSE ) { DebugShout( "[ProcessSections] Failed to map PE header!" ); } else { DebugShout( "[ProcessSections] Mapped PE Header successfully!" ); } } else { DebugShout( "[ProcessSections] PE Header mapping disabled, skipping." ); } // Write individual sections PIMAGE_SECTION_HEADER ImageSectionHeader = ( PIMAGE_SECTION_HEADER ) ( ( ( ULONG_PTR ) &ImageNtHeaders->OptionalHeader ) + ImageNtHeaders->FileHeader.SizeOfOptionalHeader ); for( DWORD i = 0; i < ImageNtHeaders->FileHeader.NumberOfSections; i++ ) { ULONG Protection = GetSectionProtection( ImageSectionHeader[ i ].Characteristics ); if( !_stricmp( ".reloc", ( CHAR* ) ImageSectionHeader[ i ].Name ) ) { DebugShout( "[ProcessSections] Skipping \".reloc\" section." ); continue; // NOPE } if( ProcessSection( ImageSectionHeader[ i ].Name, BaseAddress, RemoteAddress, ImageSectionHeader[ i ].PointerToRawData, ImageSectionHeader[ i ].VirtualAddress, ImageSectionHeader[ i ].SizeOfRawData, ImageSectionHeader[ i ].Misc.VirtualSize, Protection ) == FALSE ) { DebugShout( "[ProcessSections] Failed %s", ImageSectionHeader[ i ].Name ); } else { DebugShout( "[ProcessSections] Success %s", ImageSectionHeader[ i ].Name ); } } return TRUE; }