Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
bool Data00Loader::isSupported(const CodeSegment &code, const uint32 offset, const uint32 size) throw() {
	const byte *memory = _executable.getMemory();
	const uint32 memorySize = _executable.getMemorySize();

	// TODO: This detection heuristic is probably all wrong...

	// Chechk whether the segment is big enough
	if (memorySize < offset + 0x210)
		return false;

	// Check whether the offset into the jump table is 0
	if (READ_UINT16_BE(memory + offset + 0) != 0)
		return false;

	// Check whether just one function is exported
	if (READ_UINT16_BE(memory + offset + 2) != 1)
		return false;

	// Check whether a "CODE" tag is at 0xA
	if (READ_UINT32_BE(memory + offset + 0x0A) != 0x434F4445)
		return false;

	// Check whether a "DATA" tag is at 0x44
	if (READ_UINT32_BE(memory + offset + 0x44) != 0x44415441)
		return false;

	// Check whether we have an DATA00 resource
	_data00 = _resFork.getResource(0x44415441, 0x0000);
	if (_data00 == nullptr)
		return false;

	return true;
}
Ejemplo n.º 4
0
uint32 A5InitLoader::getRunLength(const uint8 *&src, uint32 &special) const throw() {
	assert(src != nullptr);

	uint32 rl = *src++;

	if (!(rl & 0x80)) {
		return rl;
	} else if (!(rl & 0x40)) {
		rl &= 0x3F;
		rl <<= 8;
		rl |= *src++;
		return rl;
	} else if (!(rl & 0x20)) {
		rl &= 0x1F;
		rl <<= 8;
		rl |= *src++;
		rl <<= 8;
		rl |= *src++;
		return rl;
	} else if (!(rl & 0x10)) {
		rl = READ_UINT32_BE(src);
		src += 4;
		return rl;
	} else {
		rl = getRunLength(src, special);
		special = getRunLength(src, special);
		return rl;
	}
}
Ejemplo n.º 5
0
void A5InitLoader::relocateWorld(const uint32 a5, uint8 *dst, const uint8 *src, std::ostream &out) const throw() {
	assert(dst != nullptr);
	assert(src != nullptr);

	uint32 dummy = 0;

	while (true) {
		uint32 loops = 1;
		uint32 offset = *src++;

		if (offset) {
			if (offset & 0x80) {
				offset &= 0x7F;
				offset <<= 8;
				offset |= *src++;
			}
		} else {
			offset = *src++;
			if (!offset)
				return;

			if (offset & 0x80) {
				offset <<= 8;
				offset |= *src++;
				offset <<= 8;
				offset |= *src++;
				offset <<= 8;
				offset |= *src++;
			} else {
				loops = getRunLength(src, dummy);
			}
		}

		offset += offset;

		do {
			dst += offset;
			out << boost::format("Relocation at 0x%1$08X\n") % (dst - _executable.getMemory());
			WRITE_UINT32_BE(dst, READ_UINT32_BE(dst) + a5);
		} while (--loops);
	}
}
Ejemplo n.º 6
0
uint8_t DBUtils::hgtxToDupID(const BinaryData& hgtx)
{
   return (READ_UINT32_BE(hgtx) & 0x7f);
}
void ZeroConfContainer::loadZeroConfMempool(
   function<bool(const BinaryData&)> filter,
   bool clearMempool)
{
   //run this in its own scope so the iter and tx are closed in order to open
   //RW tx afterwards
   {
      auto dbs = db_->getDbSelect(HISTORY);

      LMDBEnv::Transaction tx;
      db_->beginDBTransaction(&tx, dbs, LMDB::ReadOnly);
      LDBIter dbIter(db_->getIterator(dbs));

      if (!dbIter.seekToStartsWith(DB_PREFIX_ZCDATA))
      {
         enabled_ = true;
         return;
      }

      do
      {
         BinaryDataRef zcKey = dbIter.getKeyRef();

         if (zcKey.getSize() == 7)
         {
            //Tx, grab it from DB
            StoredTx zcStx;
            db_->getStoredZcTx(zcStx, zcKey);

            //add to newZCMap_
            Tx& zcTx = newZCMap_[zcKey.getSliceCopy(1, 6)];
            zcTx = Tx(zcStx.getSerializedTx());
            zcTx.setTxTime(zcStx.unixTime_);
         }
         else if (zcKey.getSize() == 9)
         {
            //TxOut, ignore it
            continue;
         }
         else
         {
            //shouldn't hit this
            LOGERR << "Unknown key found in ZC mempool";
            break;
         }
      } while (dbIter.advanceAndRead(DB_PREFIX_ZCDATA));
   }

   if (clearMempool == true)
   {
      vector<BinaryData> keysToWrite, keysToDelete;

      for (const auto& zcTx : newZCMap_)
         keysToDelete.push_back(zcTx.first);

      newZCMap_.clear();
      updateZCinDB(keysToWrite, keysToDelete);
   }
   else if (newZCMap_.size())
   {   

      //copy newZCmap_ to keep the pre parse ZC map
      auto oldZCMap = newZCMap_;

      //now parse the new ZC
      parseNewZC(filter);
      
      //set the zckey to the highest used index
      if (txMap_.size() > 0)
      {
         BinaryData topZcKey = txMap_.rbegin()->first;
         topId_.store(READ_UINT32_BE(topZcKey.getSliceCopy(2, 4)) +1);
      }

      //intersect oldZCMap and txMap_ to figure out the invalidated ZCs
      vector<BinaryData> keysToWrite, keysToDelete;

      for (const auto& zcTx : oldZCMap)
      {
         if (txMap_.find(zcTx.first) == txMap_.end())
            keysToDelete.push_back(zcTx.first);
      }

      //no need to run this in a side thread, this code only runs when we have 
      //full control over the main thread
      updateZCinDB(keysToWrite, keysToDelete);
   }

   enabled_ = true;
}
Ejemplo n.º 8
0
const byte *Data00Loader::uncompress(const uint32 offset, std::ostream &out) throw(std::exception) {
	byte * const memory = _executable.getMemory();
	Code0Segment &code0 = _executable.getCode0Segment();
	byte * const a5Base = memory + code0.getApplicationGlobalsSize();
	const byte *src = _data00->data + 4;

	// Whether data was written to the jump table
	bool dataWrittenToJumpTable = false;

	for (uint i = 0; i < 3; ++i) {
		// Read the offset
		const int32 offset = (int32)READ_UINT32_BE(src);
		src += 4;

		uint8 *dst = a5Base + offset;

		// Whether we uncompress data onto the uninitialized part of the jump table
		if (offset >= int32(code0.getApplicationParametersSize() + 8)) {
			out << "\tData write to jump table offset: " << offset << std::endl;
			dataWrittenToJumpTable = true;
		}

		while (true) {
			uint8 code = *src++;

			if (code & 0x80) {
				code &= 0x7F;
				code += 1;

				std::memcpy(dst, src, code);
				src += code;
				dst += code;
			} else if (code & 0x40) {
				code &= 0x3F;
				code += 1;

				std::memset(dst, 0, code);
				dst += code;
			} else if (code & 0x20) {
				code &= 0x1F;
				code += 2;

				const uint8 data = *src++;
				std::memset(dst, data, code);
				dst += code;
			} else if (code & 0x10) {
				code &= 0x0F;
				code += 1;

				std::memset(dst, 0xFF, code);
				dst += code;
			} else {
				if (code == 0) {
					break;
				} else if (code == 1) {
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0xFF;
					*dst++ = 0xFF;
					*dst++ = *src++;
					*dst++ = *src++;
				} else if (code == 2) {
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = 0xFF;
					*dst++ = *src++;
					*dst++ = *src++;
					*dst++ = *src++;
				} else if (code == 3) {
					*dst++ = 0xA9;
					*dst++ = 0xF0;
					*dst++ = 0x00;
					*dst++ = 0x00;
					*dst++ = *src++;
					*dst++ = *src++;
					*dst++ = 0x0;
					*dst++ = *src++;
				} else if (code == 4) {
					*dst++ = 0xA9;
					*dst++ = 0xF0;
					*dst++ = 0x00;
					*dst++ = *src++;
					*dst++ = *src++;
					*dst++ = *src++;
					*dst++ = 0x0;
					*dst++ = *src++;
				} else {
					throw std::runtime_error("DATA00 Loader: Invalid code " + boost::lexical_cast<std::string>(int(code)) + " encountered");
				}
			}
		}
	}
	
	// Check whether data was written to the jump table
	if (dataWrittenToJumpTable) {
		// Load the data from entry 1 to the last entry into our jump table structure
		for (uint i = 1, end = code0.getJumpTableEntryCount(); i < end; ++i)
			std::memcpy(code0.getJumpTableEntry(i).rawData, memory + code0.getJumpTableOffset() + i * 8, 8);

		code0.outputJumptable(out);
	}

	return src;
}