Skip to content
Snippets Groups Projects
Commit eab82559 authored by esaunders's avatar esaunders
Browse files

Merge pull request #547 from sleuthkit/rejistry++

Added extra validation and handling of unknown registry types.
parents b820a5b2 2b0fbb30
Branches
Tags
No related merge requests found
...@@ -41,7 +41,9 @@ namespace Rejistry { ...@@ -41,7 +41,9 @@ namespace Rejistry {
} }
ByteBuffer::ByteBuffer(const ByteArray& buf, const uint32_t length) : Buffer(length) { ByteBuffer::ByteBuffer(const ByteArray& buf, const uint32_t length) : Buffer(length) {
initializeBuffer(&buf[0], length); if (buf.size() > 0) {
initializeBuffer(&buf[0], length);
}
} }
void ByteBuffer::initializeBuffer(const uint8_t * buf, const uint32_t length) { void ByteBuffer::initializeBuffer(const uint8_t * buf, const uint32_t length) {
...@@ -56,6 +58,11 @@ namespace Rejistry { ...@@ -56,6 +58,11 @@ namespace Rejistry {
} }
void ByteBuffer::get(ByteArray& dst, const uint32_t offset, const uint32_t length) { void ByteBuffer::get(ByteArray& dst, const uint32_t offset, const uint32_t length) {
if (length == 0) {
// No data requested.
return;
}
if (offset > dst.size()) { if (offset > dst.size()) {
throw RegistryParseException("Offset is greater than destination buffer size."); throw RegistryParseException("Offset is greater than destination buffer size.");
} }
...@@ -64,6 +71,14 @@ namespace Rejistry { ...@@ -64,6 +71,14 @@ namespace Rejistry {
throw RegistryParseException("Length is greater than available space in destination buffer."); throw RegistryParseException("Length is greater than available space in destination buffer.");
} }
if ((_position + offset) > _limit) {
throw RegistryParseException("Starting position is beyond end of buffer.");
}
if ((_position + offset + length) > _limit) {
throw RegistryParseException("Number of requested bytes exceeds buffer size.");
}
memcpy(&dst[0], &_buffer[_position + offset], length); memcpy(&dst[0], &_buffer[_position + offset], length);
_position += offset; _position += offset;
} }
......
...@@ -48,6 +48,7 @@ namespace Rejistry { ...@@ -48,6 +48,7 @@ namespace Rejistry {
ByteBuffer(const ByteArray& buf, const uint32_t length); ByteBuffer(const ByteArray& buf, const uint32_t length);
virtual ~ByteBuffer() { _buffer.clear(); } virtual ~ByteBuffer() { _buffer.clear(); }
/// Get one byte from the current position in the buffer.
uint8_t get(uint32_t offset) const; uint8_t get(uint32_t offset) const;
/** /**
...@@ -61,8 +62,12 @@ namespace Rejistry { ...@@ -61,8 +62,12 @@ namespace Rejistry {
* @throws RegistryParseException * @throws RegistryParseException
*/ */
void get(ByteArray& dst, const uint32_t offset, const uint32_t length); void get(ByteArray& dst, const uint32_t offset, const uint32_t length);
/// Get two bytes from the current position in the buffer.
uint16_t getShort(uint32_t offset) const; uint16_t getShort(uint32_t offset) const;
/// Get four bytes from the current position in the buffer.
uint32_t getInt(uint32_t offset) const; uint32_t getInt(uint32_t offset) const;
/// Get eight bytes from the current position in the buffer.
uint64_t getLong(uint32_t offset) const; uint64_t getLong(uint32_t offset) const;
private: private:
......
...@@ -57,6 +57,11 @@ namespace Rejistry { ...@@ -57,6 +57,11 @@ namespace Rejistry {
int32_t offset = (int32_t)getDWord(CLASSNAME_OFFSET_OFFSET); int32_t offset = (int32_t)getDWord(CLASSNAME_OFFSET_OFFSET);
uint16_t length = getWord(CLASSNAME_LENGTH_OFFSET); uint16_t length = getWord(CLASSNAME_LENGTH_OFFSET);
if (length > MAX_NAME_LENGTH) {
throw RegistryParseException("Class name exceeds maximum length.");
}
uint32_t classnameOffset = REGFHeader::FIRST_HBIN_OFFSET + offset; uint32_t classnameOffset = REGFHeader::FIRST_HBIN_OFFSET + offset;
std::auto_ptr< Cell > c(new Cell(_buf, classnameOffset)); std::auto_ptr< Cell > c(new Cell(_buf, classnameOffset));
if (c.get() == NULL) { if (c.get() == NULL) {
...@@ -84,6 +89,11 @@ namespace Rejistry { ...@@ -84,6 +89,11 @@ namespace Rejistry {
std::wstring NKRecord::getName() const { std::wstring NKRecord::getName() const {
uint32_t nameLength = getWord(NAME_LENGTH_OFFSET); uint32_t nameLength = getWord(NAME_LENGTH_OFFSET);
if (nameLength > MAX_NAME_LENGTH) {
throw RegistryParseException("Key name exceeds maximum length.");
}
if (hasAsciiName()) { if (hasAsciiName()) {
// TODO: This is a little hacky but it should work fine // TODO: This is a little hacky but it should work fine
// for ASCII strings. // for ASCII strings.
......
...@@ -163,6 +163,8 @@ namespace Rejistry { ...@@ -163,6 +163,8 @@ namespace Rejistry {
static const uint16_t CLASSNAME_LENGTH_OFFSET = 0x4A; static const uint16_t CLASSNAME_LENGTH_OFFSET = 0x4A;
static const uint16_t NAME_OFFSET = 0x4C; static const uint16_t NAME_OFFSET = 0x4C;
static const uint8_t MAX_NAME_LENGTH = 255;
NKRecord() {}; NKRecord() {};
NKRecord& operator=(const NKRecord &); NKRecord& operator=(const NKRecord &);
}; };
......
...@@ -66,6 +66,10 @@ namespace Rejistry { ...@@ -66,6 +66,10 @@ namespace Rejistry {
} }
std::string RegistryByteBuffer::getASCIIString(const uint32_t offset, const uint32_t length) const { std::string RegistryByteBuffer::getASCIIString(const uint32_t offset, const uint32_t length) const {
if (length == 0) {
return "";
}
ByteBuffer::ByteArray &data = getData(offset, length); ByteBuffer::ByteArray &data = getData(offset, length);
return std::string(data.begin(), data.end()); return std::string(data.begin(), data.end());
...@@ -76,6 +80,10 @@ namespace Rejistry { ...@@ -76,6 +80,10 @@ namespace Rejistry {
} }
std::wstring RegistryByteBuffer::getUTF16String(const uint32_t offset, const uint32_t length) const { std::wstring RegistryByteBuffer::getUTF16String(const uint32_t offset, const uint32_t length) const {
if (length == 0) {
return L"";
}
ByteBuffer::ByteArray &data = getData(offset, length); ByteBuffer::ByteArray &data = getData(offset, length);
std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>, wchar_t> conv; std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>, wchar_t> conv;
std::wstring result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[0] + length)); std::wstring result = conv.from_bytes(reinterpret_cast<const char*>(&data[0]), reinterpret_cast<const char*>(&data[0] + length));
......
...@@ -59,6 +59,11 @@ namespace Rejistry { ...@@ -59,6 +59,11 @@ namespace Rejistry {
} }
uint32_t nameLength = getWord(NAME_LENGTH_OFFSET); uint32_t nameLength = getWord(NAME_LENGTH_OFFSET);
if (nameLength > MAX_NAME_LENGTH) {
throw RegistryParseException("Value name length exceeds maximum length.");
}
if (hasAsciiName()) { if (hasAsciiName()) {
// TODO: This is a little hacky but it should work fine // TODO: This is a little hacky but it should work fine
// for ASCII strings. // for ASCII strings.
...@@ -75,7 +80,7 @@ namespace Rejistry { ...@@ -75,7 +80,7 @@ namespace Rejistry {
uint32_t VKRecord::getDataLength() const { uint32_t VKRecord::getDataLength() const {
uint32_t size = getDWord(DATA_LENGTH_OFFSET); uint32_t size = getDWord(DATA_LENGTH_OFFSET);
if (size > LARGE_DATA_SIZE){ if (size >= LARGE_DATA_SIZE){
size -= LARGE_DATA_SIZE; size -= LARGE_DATA_SIZE;
} }
return size; return size;
...@@ -140,7 +145,8 @@ namespace Rejistry { ...@@ -140,7 +145,8 @@ namespace Rejistry {
data = new RegistryByteBuffer(new ByteBuffer(getData(DATA_OFFSET_OFFSET, 0x8), 0x8)); data = new RegistryByteBuffer(new ByteBuffer(getData(DATA_OFFSET_OFFSET, 0x8), 0x8));
break; break;
default: default:
throw RegistryParseException("Unknown value type."); // Unknown registry type. Create an empty buffer.
data = new RegistryByteBuffer(new ByteBuffer(0));
} }
return new ValueData(data, getValueType()); return new ValueData(data, getValueType());
......
...@@ -149,6 +149,8 @@ namespace Rejistry { ...@@ -149,6 +149,8 @@ namespace Rejistry {
static const uint16_t DB_DATA_SIZE = 0x3FD8; static const uint16_t DB_DATA_SIZE = 0x3FD8;
static const uint32_t LARGE_DATA_SIZE = 0x80000000; static const uint32_t LARGE_DATA_SIZE = 0x80000000;
static const uint16_t MAX_NAME_LENGTH = 32767;
VKRecord(); VKRecord();
VKRecord& operator=(const VKRecord &); VKRecord& operator=(const VKRecord &);
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment