NKRecord::NKRecordPtr REGFHeader::getRootNKRecord() const { int32_t firstCellOffset = (int32_t)(getDWord(FIRST_KEY_OFFSET_OFFSET)); std::auto_ptr< HBIN > firstHBIN(getFirstHBIN()); if (firstHBIN.get() != NULL) { std::auto_ptr< Cell > cellPtr(firstHBIN->getCellAtOffset(firstCellOffset)); if (cellPtr.get() == NULL) { throw RegistryParseException("Failed to get first cell."); } return cellPtr->getNKRecord(); } else { throw RegistryParseException("Failed to get first HBIN."); } }
/** * Throws exception if position is too large. */ Buffer& Buffer::position(const uint32_t newPosition) { if (newPosition > _limit) { throw RegistryParseException("Buffer position greater than limit"); } _position = newPosition; return *this; }
Buffer& Buffer::limit(const uint32_t newLimit) { if (newLimit > _capacity) { throw RegistryParseException("Buffer limit greater than capacity"); } _limit = newLimit; return *this; }
ByteBuffer::ByteArray DBIndirectRecord::getData(uint32_t length) const { std::vector<uint8_t> data; uint32_t count = 0; while (length > 0) { uint32_t size = std::min(DB_DATA_SIZE, length); uint32_t offset = getDWord(OFFSET_LIST_OFFSET + (count * 4)); offset += REGFHeader::FIRST_HBIN_OFFSET; std::auto_ptr< Cell > c(new Cell(_buf, offset)); if (c.get() == NULL) { throw RegistryParseException("Failed to create Cell."); } std::vector<uint8_t> cellData = c->getData(); data.insert(data.end(), cellData.begin(), cellData.begin() + size); length -= size; count += 1; } return data; }
HBIN::HBINPtr REGFHeader::getFirstHBIN() const { if (getDWord(FIRST_HBIN_OFFSET) != 0x6E696268) { throw RegistryParseException("HBIN magic value not found."); } return new HBIN(this, _buf, getAbsoluteOffset(FIRST_HBIN_OFFSET)); }
REGFHeader::REGFHeader(RegistryByteBuffer& buf, const uint32_t offset) : BinaryBlock(buf, offset) { uint64_t magic = getDWord(offset); if (magic != 0x66676572) { throw RegistryParseException("REGF magic value not found"); } }
std::wstring VKRecord::getName() const { if (! hasName()) { return VKRecord::DEFAULT_VALUE_NAME; } uint32_t nameLength = getWord(NAME_LENGTH_OFFSET); if (nameLength > MAX_NAME_LENGTH) { throw RegistryParseException("Value name length exceeds maximum length."); } if (hasAsciiName()) { // TODO: This is a little hacky but it should work fine // for ASCII strings. std::vector<uint8_t> name = getData(NAME_OFFSET_OFFSET, nameLength); return std::wstring(name.begin(), name.end()); } return getUTF16String(NAME_OFFSET_OFFSET, nameLength); }
VKRecord::VKRecord(RegistryByteBuffer * buf, uint32_t offset) : Record(buf, offset) { if (!(getMagic() == MAGIC)) { throw RegistryParseException("VKRecord magic value not found."); } }
ValueData::ValueDataPtr VKRecord::getValue() const { uint32_t length = getRawDataLength(); uint32_t offset = getDataOffset(); if (length > LARGE_DATA_SIZE + DB_DATA_SIZE) { throw RegistryParseException("Value size too large."); } RegistryByteBuffer * data = NULL; switch (getValueType()) { case ValueData::VALTYPE_BIN: case ValueData::VALTYPE_NONE: case ValueData::VALTYPE_SZ: case ValueData::VALTYPE_EXPAND_SZ: case ValueData::VALTYPE_MULTI_SZ: case ValueData::VALTYPE_LINK: case ValueData::VALTYPE_RESOURCE_LIST: case ValueData::VALTYPE_FULL_RESOURCE_DESCRIPTOR: case ValueData::VALTYPE_RESOURCE_REQUIREMENTS_LIST: if (length >= LARGE_DATA_SIZE) { uint32_t bufSize = length - LARGE_DATA_SIZE; data = new RegistryByteBuffer(new ByteBuffer(getData(DATA_OFFSET_OFFSET, bufSize), bufSize)); } else if (DB_DATA_SIZE < length && length < LARGE_DATA_SIZE) { std::auto_ptr< Cell > c(new Cell(_buf, offset)); if (c.get() == NULL) { throw RegistryParseException("Failed to create Cell for Value data."); } try { std::auto_ptr< DBRecord > db(c->getDBRecord()); if (db.get() == NULL) { throw RegistryParseException("Failed to create Cell for DBRecord."); } data = new RegistryByteBuffer(new ByteBuffer(db->getData(length), length)); } catch (RegistryParseException& ) { data = new RegistryByteBuffer(new ByteBuffer(c->getData(), length)); } } else { std::auto_ptr< Cell > c(new Cell(_buf, offset)); if (c.get() == NULL) { throw RegistryParseException("Failed to create Cell for Value data."); } ByteBuffer * byteBuffer = new ByteBuffer(c->getData(), length); data = new RegistryByteBuffer(byteBuffer); } break; case ValueData::VALTYPE_DWORD: case ValueData::VALTYPE_BIG_ENDIAN: data = new RegistryByteBuffer(new ByteBuffer(getData(DATA_OFFSET_OFFSET, 0x4), 0x4)); break; case ValueData::VALTYPE_QWORD: { std::auto_ptr< Cell > c(new Cell(_buf, offset)); if (c.get() == NULL) { throw RegistryParseException("Failed to create Cell for Value data."); } ByteBuffer * byteBuffer = new ByteBuffer(c->getData(), length); data = new RegistryByteBuffer(byteBuffer); } break; default: // Unknown registry type. Create an empty buffer. data = new RegistryByteBuffer(new ByteBuffer(0)); } return new ValueData(data, getValueType()); }
std::wstring RegistryByteBuffer::getUTF16String(const uint32_t offset, const uint32_t length) const { if (length == 0) { return L""; } ByteBuffer::ByteArray &data = getData(offset, length); // If the size of the array is not a multiple of 2 it is // likely to not be UTF16 encoded. The most common case is that // the string is simply missing a terminating null so we add it. if (data.size() % 2 != 0) { data.push_back('\0'); } // Find UTF16 null terminator. uint32_t nullPos = 0; for (; nullPos < data.size(); nullPos += 2) { if (data[nullPos] == '\0' && data[nullPos+1] == '\0') { break; } } if (nullPos == 0) { return L""; } std::wstring result; try { result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[nullPos])); } catch (std::exception&) { throw RegistryParseException("Error: Failed to convert string"); } return result; }