diff --git a/libs/visor_dns/DnsResource.cpp b/libs/visor_dns/DnsResource.cpp index 97ad533c9..cd35ed230 100644 --- a/libs/visor_dns/DnsResource.cpp +++ b/libs/visor_dns/DnsResource.cpp @@ -58,11 +58,14 @@ size_t IDnsResource::decodeName(const char *encodedName, char *result, int itera resultPtr[0] = 0; size_t curOffsetInLayer = (uint8_t *)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) - return encodedNameLength; + if (curOffsetInLayer >= m_DnsLayer->m_DataLen) { + PCPP_LOG_ERROR(fmt::format("decodeName: curOffsetInLayer ({}) >= m_DnsLayer->m_DataLen ({})", curOffsetInLayer, m_DnsLayer->m_DataLen).c_str()); + return 0; + } if (iteration > 20) { - return encodedNameLength; + PCPP_LOG_ERROR(fmt::format("decodeName: recursion depth ({}) exceeded limit", iteration).c_str()); + return 0; } uint8_t wordLength = encodedName[0]; @@ -71,19 +74,26 @@ size_t IDnsResource::decodeName(const char *encodedName, char *result, int itera while (wordLength != 0) { // A pointer to another place in the packet if ((wordLength & 0xc0) == 0xc0) { - if (curOffsetInLayer + 2 > m_DnsLayer->m_DataLen || encodedNameLength > 255) - return encodedNameLength; + if (curOffsetInLayer + 2 > m_DnsLayer->m_DataLen || encodedNameLength >= 255) { + PCPP_LOG_ERROR(fmt::format("decodeName pointer case: out-of-bounds: curOffsetInLayer ({}) + 2 > m_DnsLayer->m_DataLen ({}) or encodedNameLength ({}) >= 255",curOffsetInLayer, m_DnsLayer->m_DataLen, encodedNameLength).c_str()); + return 0; + } uint16_t offsetInLayer = (wordLength & 0x3f) * 256 + (0xFF & encodedName[1]); if (offsetInLayer < sizeof(dnshdr) || offsetInLayer >= m_DnsLayer->m_DataLen) { - PCPP_LOG_ERROR("DNS parsing error: name pointer is illegal"); + PCPP_LOG_ERROR(fmt::format("DNS parsing error: name pointer is illegal, offsetInLayer = {}", offsetInLayer).c_str()); return 0; } char tempResult[256]; memset(tempResult, 0, 256); + size_t ret = decodeName((const char *)(m_DnsLayer->m_Data + offsetInLayer), tempResult, iteration + 1); + if (ret == 0) { + PCPP_LOG_ERROR(fmt::format("decodeName: recursive call failed at offset {}", offsetInLayer).c_str()); + return 0; + } + int i = 0; - decodeName((const char *)(m_DnsLayer->m_Data + offsetInLayer), tempResult, iteration + 1); while (tempResult[i] != 0 && decodedNameLength < 255) { resultPtr[0] = tempResult[i++]; resultPtr++; @@ -93,20 +103,13 @@ size_t IDnsResource::decodeName(const char *encodedName, char *result, int itera resultPtr[0] = 0; // in this case the length of the pointer is: 1 byte for 0xc0 + 1 byte for the offset itself - return encodedNameLength + sizeof(uint16_t); + return encodedNameLength + 2; } else { // return if next word would be outside of the DNS layer or overflow the buffer behind resultPtr - if (curOffsetInLayer + wordLength + 1 > m_DnsLayer->m_DataLen || encodedNameLength + wordLength > 255) { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) { - resultPtr--; - decodedNameLength--; - } else { - encodedNameLength++; - } - - resultPtr[0] = 0; - return encodedNameLength; + if (curOffsetInLayer + wordLength + 1 > m_DnsLayer->m_DataLen || encodedNameLength + wordLength >= 255) { + PCPP_LOG_ERROR(fmt::format("decodeName: label out-of-bounds: curOffsetInLayer ({}) + wordLength ({}) + 1 > m_DnsLayer->m_DataLen ({}) or encodedNameLength ({}) + wordLength ({}) >= 255", + curOffsetInLayer, wordLength, m_DnsLayer->m_DataLen, encodedNameLength, wordLength).c_str()); + return 0; } memcpy(resultPtr, encodedName + 1, wordLength); @@ -118,17 +121,10 @@ size_t IDnsResource::decodeName(const char *encodedName, char *result, int itera encodedNameLength += wordLength + 1; curOffsetInLayer = (uint8_t *)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) { - decodedNameLength--; - resultPtr--; - } else { - encodedNameLength++; - } - - resultPtr[0] = 0; - return encodedNameLength; + if (curOffsetInLayer >= m_DnsLayer->m_DataLen) { + PCPP_LOG_ERROR(fmt::format("decodeName: after label, curOffsetInLayer ({}) >= m_DnsLayer->m_DataLen ({})", + curOffsetInLayer, m_DnsLayer->m_DataLen).c_str()); + return 0; } wordLength = encodedName[0]; @@ -147,6 +143,7 @@ size_t IDnsResource::decodeName(const char *encodedName, char *result, int itera return encodedNameLength; } + void IDnsResource::encodeName(const std::string &decodedName, char *result, size_t &resultLen) { resultLen = 0;