bool MapRemoteModule(unsigned long pId, const char *module) { IMAGE_DOS_HEADER *dosHd; IMAGE_NT_HEADERS *ntHd; IMAGE_NT_HEADERS64 *ntHd64 = NULL; HANDLE hFile = CreateFileA(module, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) return false; unsigned int fSize; if(GetFileAttributesA(module) & FILE_ATTRIBUTE_COMPRESSED) fSize = GetCompressedFileSizeA(module, NULL); else fSize = GetFileSize(hFile, NULL); unsigned char *dllBin = new unsigned char[fSize]; unsigned int nBytes; // copy into our dllBin buffer the entire DLL ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE); CloseHandle(hFile); // Every PE file contains a little DOS stub for backwards compatibility // its only real relevance is that it contains a pointer to the actual // PE header. dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0); // Make sure we got a valid DOS header if(dosHd->e_magic != IMAGE_DOS_SIGNATURE) { wxMessageBox( _("The DOS header was invalid"), _("Error: Invalid DOS header"), wxICON_ERROR ); delete [] dllBin; return false; } // Get the real PE header from the DOS stub header // This header contains pointers to the Optional Header and the // COFF File Header. ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew); // Verify that the PE header is PE00 if(ntHd->Signature != IMAGE_NT_SIGNATURE) { wxMessageBox( _("The PE Header was not found."), _("Error: PE Header not found"), wxICON_ERROR ); delete [] dllBin; return false; } // Verify that the image file is a DLL if( (ntHd->FileHeader.Characteristics & IMAGE_FILE_DLL) == false ) { wxMessageBox( _("You may only inject DLL image files."), _("Error: Injected image file was not a DLL"), wxICON_ERROR ); delete [] dllBin; return false; } // Open the target process HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId); // We failed to open the process, so return false if(!hProcess) { wxMessageBox( _("Failed to open target process."), _("Error: Failed to open process"), wxICON_ERROR ); delete [] dllBin; return false; } // Determine whether the image is a PE32 or PE32+ executable if( ntHd->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC ) { if( ntHd->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ) { ntHd64 = (IMAGE_NT_HEADERS64 *)ntHd; wxMessageBox( _("Image is a PE32+ executable.\nInjector Gadget doesn't support PE32+ executables yet."), _("Error: Image is not a PE32 executable"), wxICON_ERROR ); } else if( ntHd->OptionalHeader.Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC ) { wxMessageBox( _("Image is a ROM image.\nInjector Gadget doesn't support ROM images."), _("Error: Image is not a PE32 executable"), wxICON_ERROR ); } delete [] dllBin; return false; } // Allocate space for the module in the remote process void *imageBase = VirtualAllocEx(hProcess, NULL, ntHd->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!imageBase) { delete [] dllBin; return false; } // Allocate space for our stub void *stubBase = VirtualAllocEx(hProcess, NULL, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!stubBase) { delete [] dllBin; return false; } // We now need to fix up the tables. // The tables are as follows (in order): // Export Table, Import Table, Resource Table, Exception Table, // Certificate Table, Base Relocation Table, Debug, Architecture, // Global Ptr, TLS Table, Load Config Table, Bound Import, IAT, // Delay Import Descriptor, CLR Runtime Header, Reserved // First important section is the Export Table. We're going to skip this // since the whole point of cloaking a DLL is to hide its presence. // Second important section is the Import Table. We really need this. if( ntHd->OptionalHeader.NumberOfRvaAndSizes > 1 ) { IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) FixImports(pId, (unsigned char *)dllBin, ntHd, impDesc); else // size was 0 for the import directory entry { wxMessageBox( _("Size of import directory entry was 0"), _("Error: Import Directory size is 0"), wxICON_ERROR); delete [] dllBin; return false; } } else // IMAGE_DIRECTORY_ENTRY_IMPORT didn't exist in the data directories { wxMessageBox( _("The import table referenced an invalid index in the data directory."), _("Error: Import table could not be located"), wxICON_ERROR ); delete [] dllBin; return false; } // Fix "base relocations" of the new module. Base relocations are places // in the module that use absolute addresses to reference data. Since // the base address of the module can be different at different times, // the base relocation data is necessary to make the module loadable // at any address. IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) FixRelocs(dllBin, imageBase, ntHd, reloc, ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); // Write the PE header into the remote process's memory space WriteProcessMemory(hProcess, imageBase, dllBin, ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature), (SIZE_T *)&nBytes); // Map the sections into the remote process(they need to be aligned // along their virtual addresses) MapSections(hProcess, imageBase, dllBin, ntHd); // Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ // to PAGE_EXECUTE_READWRITE, so we can patch it. VirtualProtect((LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), PAGE_EXECUTE_READWRITE, (DWORD *)&nBytes); // Patch the stub so it calls the correct address *MakePtr(unsigned long *, DllCall_stub, 9) = MakePtr(unsigned long, imageBase, ntHd->OptionalHeader.AddressOfEntryPoint); // Write the stub into the remote process WriteProcessMemory(hProcess, stubBase, (LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), (SIZE_T *)&nBytes); #ifdef __USING_DEBUGGER wxMessageBox(_("Calling CreateRemoteThread")); wxMessageBox( _("hProcess: ") + wxString::Format("%08X",hProcess) ); wxMessageBox( _("stubBase: ") + wxString::Format("%08X",stubBase) ); wxMessageBox( _("moduleBas: ") + wxString::Format("%08X",imageBase) ); #endif // Execute our stub in the remote process CreateRemoteThread(hProcess, NULL, ntHd->OptionalHeader.SizeOfStackCommit, (LPTHREAD_START_ROUTINE)stubBase, imageBase, // Pass the base address of the module as the argument to the stub. // All a module handle is, is the base address of the module(except // in windows CE), so we're really passing a handle to the module // so that it can refer to itself, create dialogs, etc.. 0, NULL); delete dllBin; return true; }
bool MapRemoteModule(unsigned long pId, char *module) { IMAGE_DOS_HEADER *dosHd; IMAGE_NT_HEADERS *ntHd; HANDLE hFile = CreateFile(module, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) return false; unsigned int fSize; if(GetFileAttributes(module) & FILE_ATTRIBUTE_COMPRESSED) fSize = GetCompressedFileSize(module, NULL); else fSize = GetFileSize(hFile, NULL); unsigned char *dllBin = new unsigned char[fSize]; unsigned int nBytes; ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE); CloseHandle(hFile); // Every PE file contains a little DOS stub for backwards compatibility // it's only real relevance is that it contains a pointer to the actual // PE header. dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0); // Make sure we got a valid DOS header if(dosHd->e_magic != IMAGE_DOS_SIGNATURE) { delete dllBin; printf("invalid dos header\n"); return false; } // Get the real PE header from the DOS stub header ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew); // Verify the PE header if(ntHd->Signature != IMAGE_NT_SIGNATURE) { delete dllBin; printf("invalid nt header\n"); return false; } HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId); if(!hProcess) { printf("open process failed\n"); return false; } // Allocate space for the module in the remote process void *moduleBase = VirtualAllocEx(hProcess, NULL, ntHd->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!moduleBase) { printf("virtual alloc failed (moduleBase)\n"); return false; } // Allocate space for our stub void *stubBase = VirtualAllocEx(hProcess, NULL, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Make sure we got the memory space we wanted if(!stubBase) { printf("virtual alloc failed(stubBase)\n"); return false; } // Fix up the import table of the new module IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) FixImports(pId, (unsigned char *)dllBin, ntHd, impDesc); // Fix "base relocations" of the new module. Base relocations are places // in the module that use absolute addresses to reference data. Since // the base address of the module can be different at different times, // the base relocation data is necessary to make the module loadable // at any address. IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA( (DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), ntHd, (PBYTE)dllBin); if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) FixRelocs(dllBin, moduleBase, ntHd, reloc, ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); // Write the PE header into the remote process's memory space WriteProcessMemory(hProcess, moduleBase, dllBin, ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature), (SIZE_T *)&nBytes); // Map the sections into the remote process(they need to be aligned // along their virtual addresses) MapSections(hProcess, moduleBase, dllBin, ntHd); // Change the page protection on the DllCall_stub function from PAGE_EXECUTE_READ // to PAGE_EXECUTE_READWRITE, so we can patch it. VirtualProtect((LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), PAGE_EXECUTE_READWRITE, (DWORD *)&nBytes); // Patch the stub so it calls the correct address *MakePtr(unsigned long *, DllCall_stub, 9) = MakePtr(unsigned long, moduleBase, ntHd->OptionalHeader.AddressOfEntryPoint); // Write the stub into the remote process WriteProcessMemory(hProcess, stubBase, (LPVOID)DllCall_stub, MakeDelta(SIZE_T, DC_stubend, DllCall_stub), (SIZE_T *)&nBytes); // Execute our stub in the remote process CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)stubBase, moduleBase, // Pass the base address of the module as the argument to the stub. // All a module handle is, is the base address of the module(except // in windows CE), so we're really passing a handle to the module // so that it can refer to itself, create dialogs, etc.. 0, NULL); delete dllBin; return true; }
TInt E32ImageFile_ELF::Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, \ TBool aSymLkupEnabled) // // Translate a ELF format file to a E32Image file // { iSource = EElfFile; ELFFile elffile; if (!elffile.Init((const TText * const)aFileName)) return KErrGeneral; iFileName = strdup(aFileName); Adjust(ALIGN4(sizeof(E32ImageHeaderV))); // fixed for now because holes not supported SetDefaultHeader(); iHdr->iDllRefTableCount = elffile.NumberOfImportDlls(); iHdr->iExportDirCount = elffile.NumberOfExports(); iHdr->iCodeBase = elffile.iLinkedBase; if(aSymLkupEnabled) { if( !SetUpLookupTable(elffile) ) return KErrGeneral; } TInt size = ALIGN4(sizeof(E32ImageHeaderV)); // fixed for now because holes not supported iHdr->iCodeOffset = size; TInt pos = size; size+=DoCodeHeader(elffile); size += DoSymbolLookupHeader(elffile, size - pos); TInt nimports=elffile.NumberOfImports(); TInt importSectionSize; char *newImportSection=CreateImportSection(elffile, importSectionSize); TInt t=DoDataHeader(elffile, aDataBase); if (t>0) { iHdr->iDataOffset = size; size += t; } if (importSectionSize!=0) { iHdr->iImportOffset=size; size+=ALIGN4(importSectionSize); } char *newCodeRelocs=NULL; char *newDataRelocs=NULL; TInt codeRelocSize=0, dataRelocSize=0; TInt nCodeRelocs=elffile.NumberOfCodeRelocs(); TInt nDataRelocs=elffile.NumberOfDataRelocs(); if (nCodeRelocs + nDataRelocs) { Elf32_Rel **codeRelocs=new Elf32_Rel * [nCodeRelocs]; Elf32_Rel **dataRelocs=new Elf32_Rel * [nDataRelocs]; if (!elffile.GetRelocs(codeRelocs, dataRelocs)) return KErrGeneral; FixRelocs(elffile, codeRelocs, dataRelocs); if (elffile.iCodeSegmentHdr) newCodeRelocs=CreateRelocs(elffile, codeRelocs, nCodeRelocs, codeRelocSize, elffile.iCodeSegmentHdr->p_vaddr); if (elffile.iDataSegmentHdr) newDataRelocs=CreateRelocs(elffile, dataRelocs, nDataRelocs, dataRelocSize, elffile.iDataSegmentHdr->p_vaddr); if (codeRelocSize) { iHdr->iCodeRelocOffset = size; size += codeRelocSize; } if (dataRelocSize) { iHdr->iDataRelocOffset = size; size += dataRelocSize; } delete [] codeRelocs; delete [] dataRelocs; } Adjust(size); t=CopyCode(iData + pos, elffile); if (t<0) return KErrGeneral; pos += t; t = CopyExportSymInfo(iData+pos, elffile); if (t<0) return KErrGeneral; pos += t; pos += CopyData(iData + pos, elffile); if (nimports) { memcpy(iData + pos, newImportSection, importSectionSize); pos += ALIGN4(importSectionSize); } if (codeRelocSize) { memcpy(iData + pos, newCodeRelocs, codeRelocSize); pos += codeRelocSize; } if (dataRelocSize) { memcpy(iData + pos, newDataRelocs, dataRelocSize); pos += dataRelocSize; } // locate the entry point TUint entryPointOffset=elffile.GetEntryPointOffset(); // Arrange a header for this E32 Image iHdr->iCpuIdentifier = (TUint16)ECpuArmV4; // Import format is ELF-derived iHdr->iFlags |= KImageImpFmt_ELF; // ABI is ARM EABI iHdr->iFlags |= KImageABI_EABI; if (ImageIsDll(elffile)) { iHdr->iFlags |= KImageDll; if (iHdr->iDataSize && !aAllowDllData) return Print(EError, "Dll '%s' has initialised data.\n", iFileName); if (iHdr->iBssSize && !aAllowDllData) return Print(EError, "Dll '%s' has uninitialised data.\n", iFileName); } iHdr->iHeapSizeMin = elffile.iHeapCommittedSize; iHdr->iHeapSizeMax = elffile.iHeapReservedSize; iHdr->iStackSize = elffile.iStackCommittedSize; iHdr->iEntryPoint = entryPointOffset; TInt r = DetermineEntryPointType(); if (r == KErrCorrupt) return Print(EError, "File '%s': Bad Entry Point.\n", iFileName); else if (r == KErrNotSupported) return Print(EError, "File '%s': Bad Entry Point Type.\n", iFileName); SetUpExceptions(elffile); delete [] newImportSection; delete [] newCodeRelocs; delete [] newDataRelocs; return KErrNone; }