bool A5InitLoader::isSupported(const CodeSegment &code, const uint32 offset, const uint32 size) throw() { // Check whether the name matches if (code.getName() != "%A5Init") return false; const byte *memory = _executable.getMemory(); const uint32 memorySize = _executable.getMemorySize(); // Check whether it only exports one function if (!code.is32BitSegment() && READ_UINT16_BE(memory + offset + 2) != 0x0001) return false; else if (READ_UINT32_BE(memory + offset + 8) != 0x00000001) return false; const uint32 internalOffset = (code.is32BitSegment() ? 46 : 10); const uint32 infoOffset = READ_UINT16_BE(memory + offset + internalOffset) + internalOffset; // Check whether the information area is still inside the memory dump if (offset + infoOffset + 16 >= memorySize) return false; const uint32 dataOffset = READ_UINT32_BE(memory + offset + infoOffset + 8); const uint32 relocationDataOffset = READ_UINT32_BE(memory + offset + infoOffset + 12); // Check whether the compressed data is still in the memory dump if (offset + dataOffset >= memorySize) return false; // Check whether the relocation data is still in the memory dump if (offset + relocationDataOffset >= memorySize) return false; // Looks like it is an %A5Init segment return true; }
void A5InitLoader::load(const CodeSegment &code, const uint32 offset, const uint32 size, std::ostream &out) throw(std::exception) { byte *memory = _executable.getMemory(); const uint32 internalOffset = (code.is32BitSegment() ? 46 : 10); const uint32 infoOffset = READ_UINT16_BE(memory + offset + internalOffset) + internalOffset; const uint32 dataSize = READ_UINT32_BE(memory + offset + infoOffset + 0); const uint16 needLoadBit = READ_UINT16_BE(memory + offset + infoOffset + 4); const uint32 dataOffset = READ_UINT32_BE(memory + offset + infoOffset + 8); const uint32 relocationDataOffset = READ_UINT32_BE(memory + offset + infoOffset + 12); // Output various information about the %A5Init segment out << "%A5Init info data:\n" "\tData size: " << dataSize << "\n" "\tNeed to load: " << needLoadBit << "\n" "\tData offset: " << dataOffset << "\n" "\tRelocation offset: " << relocationDataOffset << std::endl; // Check whether we actually have to do some work if (needLoadBit != 1) { out << "A5 data does not need any initialization" << std::endl; return; } const Code0Segment &code0 = _executable.getCode0Segment(); uint8 *dst = memory + code0.getApplicationGlobalsSize() - dataSize; // uncompress the world uncompressA5World(dst, memory + offset + infoOffset + dataOffset); // relocate the world relocateWorld(code0.getApplicationGlobalsSize(), dst, memory + offset + infoOffset + relocationDataOffset, out); // Mark segment as initialized WRITE_UINT16_BE(memory + offset + infoOffset + 4, 0); }