/*++ Copyright (C) 1997-2001 Microsoft Corporation Module Name: BMOFCHCK.CPP Abstract: Has test to determine if a binary mof is valid. Note that the file has not been tested and is not currently a part of mofcomp. This exists as a backup in case the current fixes are not bullet proof. History: davj 27-Nov-00 Created. --*/ #include "precomp.h" #include #include #include "trace.h" #include "bmof.h" BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj); DWORD CheckString(BYTE * pStr,BYTE * pToFar); void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar); enum EFailureType { UNALIGNED_PTR = 0, BAD_OBJECT, BAD_SIZE, BAD_STRING, BAD_ARRAY_DATA, BAD_SCALAR_DATA, BAD_FLAVOR_TABLE }; class CGenException { private: EFailureType m_eType; public: CGenException( EFailureType eType ){ m_eType =eType ;} EFailureType GetErrorCode() { return m_eType; } }; #ifdef _WIN64 #define RETURN_IF_UNALIGN64() return FALSE; #else #define RETURN_IF_UNALIGN64() #endif void CheckAlignment(DWORD dwToCheck) { if(dwToCheck & 3) { ERRORTRACE((LOG_MOFCOMP,"CheckAlignment\n")); #ifdef _WIN64 throw CGenException( UNALIGNED_PTR ); #endif } } DWORD CheckSimpleValue(BYTE *pData, BYTE *pToFar, DWORD dwType, BOOL bQualifier) { DWORD dwTypeSize = iTypeSize(dwType); if(dwTypeSize == 0) throw CGenException( BAD_SCALAR_DATA ); if(dwType == VT_DISPATCH) { WBEM_Object * pObject; pObject = (WBEM_Object *)pData; CheckClassOrInst(pObject, pToFar); return pObject->dwLength; } else if(dwType == VT_BSTR) { DWORD dwNumChar = CheckString(pData ,pToFar); return (dwNumChar+1) * sizeof(WCHAR); } if(pData + dwTypeSize >= pToFar) throw CGenException( BAD_SCALAR_DATA ); return dwTypeSize; } void CheckValue(BYTE * pData, BYTE * pToFar, DWORD dwType, BOOL bQualifier) { DWORD * pArrayInfo, dwNumObj, dwCnt; if(pData >= pToFar) throw CGenException( BAD_OBJECT ); CheckAlignment((DWORD)pData); if(dwType & VT_ARRAY) { CheckObject(pData, pToFar, 4*sizeof(DWORD)); DWORD dwSimpleType = dwType & ~VT_ARRAY & ~VT_BYREF; pArrayInfo = (DWORD *)pData; // check the number of rows. Currently only 1 is supported pArrayInfo++; if(*pArrayInfo != 1) { throw CGenException( BAD_ARRAY_DATA ); } // Get the number of objects pArrayInfo++; dwNumObj = *pArrayInfo; // Start into the row. It starts off with the total size pArrayInfo++; CheckAlignment(*pArrayInfo); // Test each object pArrayInfo++; // now points to first object BYTE * pSingleData = (BYTE *)pArrayInfo; for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++) { DWORD dwSize = CheckSimpleValue(pSingleData, pToFar, dwSimpleType, bQualifier); pSingleData += dwSize; } } else CheckSimpleValue(pData, pToFar, dwType, bQualifier); } BYTE * CheckObject(BYTE * pObj, BYTE * pToFar, DWORD dwSizeOfObj) { if(pObj + dwSizeOfObj >= pToFar) throw CGenException( BAD_OBJECT ); CheckAlignment((DWORD)pObj); // these always start off with the size, make sure that is OK DWORD * pdw = (DWORD *)pObj; if(*pdw + pObj >= pToFar) throw CGenException( BAD_SIZE ); return *pdw + pObj + 1; } DWORD CheckString(BYTE * pStr,BYTE * pToFar) { DWORD dwNumChar = 0; if(pStr >= pToFar) throw CGenException( BAD_STRING ); CheckAlignment((DWORD)pStr); WCHAR * pwc; for(pwc = (WCHAR *)pStr; *pwc && pwc < (WCHAR*)pToFar; pwc++, dwNumChar++); // intentional semi if(pwc >= (WCHAR *)pToFar) throw CGenException( BAD_STRING ); return dwNumChar; } void CheckQualifier(WBEM_Qualifier *pQual, BYTE * pToFar) { BYTE * pByteInfo = (BYTE *)pQual; pByteInfo += sizeof(WBEM_Qualifier); pToFar = CheckObject((BYTE *)pQual, pToFar, sizeof(WBEM_Qualifier)); CheckString(pByteInfo + pQual->dwOffsetName, pToFar); CheckValue(pByteInfo + pQual->dwOffsetValue, pToFar, pQual->dwType, TRUE); return; } void CheckQualList(WBEM_QualifierList *pQualList, BYTE * pToFar) { DWORD dwNumQual, dwCnt; WBEM_Qualifier *pQual; pToFar = CheckObject((BYTE *)pQualList, pToFar, sizeof(WBEM_QualifierList)); dwNumQual = pQualList->dwNumQualifiers; if(dwNumQual == 0) return; pQual = (WBEM_Qualifier *)((PBYTE)pQualList + sizeof(WBEM_QualifierList)); for(dwCnt = 0; dwCnt < dwNumQual; dwCnt++) { CheckQualifier(pQual, pToFar); pQual = (WBEM_Qualifier *)((BYTE *)pQual + pQual->dwLength); } return; } void CheckProperty(WBEM_Property *pProperty, BOOL bProperty, BYTE * pToFar) { WBEM_QualifierList *pQualList; BYTE * pValue; pToFar = CheckObject((BYTE *)pProperty, pToFar, sizeof(WBEM_Property)); if(pProperty->dwOffsetName != 0xffffffff) { BYTE * pStr = ((BYTE *)pProperty + sizeof(WBEM_Property) + pProperty->dwOffsetName); CheckString(pStr, pToFar); } if(pProperty->dwOffsetQualifierSet != 0xffffffff) { pQualList = (WBEM_QualifierList *)((BYTE *)pProperty + sizeof(WBEM_Property) + pProperty->dwOffsetQualifierSet); CheckQualList(pQualList, pToFar); } if(pProperty->dwOffsetValue != 0xffffffff) { CheckAlignment(pProperty->dwOffsetValue & 3); pValue = ((BYTE *)pProperty + sizeof(WBEM_Property) + pProperty->dwOffsetValue); CheckValue(pValue, pToFar, pProperty->dwType, FALSE); } return; } void CheckPropList(WBEM_PropertyList *pPropList, BOOL bProperty, BYTE * pToFar) { DWORD dwNumProp, dwCnt; WBEM_Property *pProperty; pToFar = CheckObject((BYTE *)pPropList, pToFar, sizeof(WBEM_PropertyList)); dwNumProp = pPropList->dwNumberOfProperties; if(dwNumProp == 0) return; pProperty = (WBEM_Property *)((PBYTE)pPropList + sizeof(WBEM_PropertyList)); for(dwCnt = 0; dwCnt < dwNumProp; dwCnt++) { CheckProperty(pProperty, bProperty, pToFar); pProperty = (WBEM_Property *)((BYTE *)pProperty + pProperty->dwLength); } return; } void CheckClassOrInst(WBEM_Object * pObject, BYTE * pToFar) { WBEM_QualifierList *pQualList; WBEM_PropertyList * pPropList; WBEM_PropertyList * pMethodList; pToFar = CheckObject((BYTE *)pObject, pToFar, sizeof(WBEM_Object)); if(pObject->dwType != 0 && pObject->dwType != 1) throw CGenException( BAD_OBJECT ); // Check the qualifier list if(pObject->dwOffsetQualifierList != 0xffffffff) { pQualList = (WBEM_QualifierList *)((BYTE *)pObject + sizeof(WBEM_Object) + pObject->dwOffsetQualifierList); CheckQualList(pQualList, pToFar); } // check the property list if(pObject->dwOffsetPropertyList != 0xffffffff) { pPropList = (WBEM_PropertyList *)((BYTE *)pObject + sizeof(WBEM_Object) + pObject->dwOffsetPropertyList); CheckPropList(pPropList, TRUE, pToFar); } // check the method list if(pObject->dwOffsetMethodList != 0xffffffff) { pMethodList = (WBEM_PropertyList *)((BYTE *)pObject + sizeof(WBEM_Object) + pObject->dwOffsetMethodList); CheckPropList(pMethodList, FALSE, pToFar); } return; } void CheckBMOFQualFlavor(BYTE * pBinaryMof, BYTE * pToFar) { UNALIGNED DWORD * pdwTemp; BYTE * pFlavorBlob; DWORD dwNumPairs; UNALIGNED DWORD * pOffset; DWORD dwMyOffset; DWORD dwCnt; DWORD dwOrigBlobSize = 0; // Calculate the pointer of the start of the flavor data pdwTemp = (DWORD * )pBinaryMof; pdwTemp++; // point to the original blob size dwOrigBlobSize = *pdwTemp; pFlavorBlob = pBinaryMof + dwOrigBlobSize; // Dont even try past the end of memory if(pFlavorBlob + 20 >= pToFar) return; // Check if the flavor blob is valid, it should start off with the // characters "BMOFQUALFLAVOR11" if(memcmp(pFlavorBlob, "BMOFQUALFLAVOR11", 16)) return; // Not really a problem since it may be old file // The flavor part of the file has the format // DWORD dwNumPair, followed by pairs of dwords; // offset, flavor // Determine the number of pairs pFlavorBlob+= 16; // skip past signature pdwTemp = (DWORD *)pFlavorBlob; dwNumPairs = *pdwTemp; // Number of offset/value pairs if(dwNumPairs < 1) return; // Given the number of pairs, make sure there is enough memory if((pFlavorBlob + sizeof(DWORD) + (dwNumPairs * 2 * sizeof(DWORD)))>= pToFar) throw CGenException( BAD_FLAVOR_TABLE ); // point to the first offset/flavor pair pOffset = pdwTemp+1; // go through the offset/flavor list. Ignore the flavors, but make sure the // offsets are valid for(dwCnt = 0; dwCnt < dwNumPairs; dwCnt++) { if(*pOffset >= dwOrigBlobSize) throw CGenException( BAD_FLAVOR_TABLE ); pOffset += 2; } } //*************************************************************************** // // IsValidBMOF. // // DESCRIPTION: // // Checks to make sure that a binary mof is properly aligned on // 4 byte boundaries. Note that this is not really necessary for // 32 bit windows. // // PARAMETERS: // // pBuffer Pointer to uncompressed binary mof data. // // RETURN: // // TRUE if all is well. // //*************************************************************************** BOOL IsValidBMOF(BYTE * pData, BYTE * pToFar) { WBEM_Binary_MOF * pBinaryMof; DWORD dwNumObj, dwCnt; WBEM_Object * pObject; if(pData == NULL || pToFar == NULL || pData >= pToFar) return FALSE; try { pBinaryMof = (WBEM_Binary_MOF *)pData; CheckObject(pData, pToFar, sizeof(WBEM_Binary_MOF)); if(pBinaryMof->dwSignature != BMOF_SIG) return FALSE; dwNumObj = pBinaryMof->dwNumberOfObjects; if(dwNumObj == 0) return TRUE; pObject = (WBEM_Object *)(pData + sizeof(WBEM_Binary_MOF)); for(dwCnt = 0; dwCnt < dwNumObj; dwCnt++) { CheckClassOrInst(pObject, pToFar); pObject = (WBEM_Object *)((PBYTE *)pObject + pObject->dwLength); } CheckBMOFQualFlavor(pData, pToFar); } catch(CGenException) { ERRORTRACE((LOG_MOFCOMP,"BINARY MOF had exception\n")); return FALSE; } return TRUE; }