def cBugReport_foAnalyzeException_STATUS_STOWED_EXCEPTION(oBugReport, oCdbWrapper): oException = oBugReport.oException; # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oException.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oException.auParameters); pStowedExceptionsAddresses = oException.auParameters[0]; uStowedExceptionsCount = oException.auParameters[1]; assert uStowedExceptionsCount <= 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount; # The stowed exception replaces this exception: oBugReport.oException = cStowedException.foCreate(oCdbWrapper, oException.oProcess, pStowedExceptionsAddresses); return oBugReport;
def cErrorReport_foSpecialErrorReport_STATUS_STOWED_EXCEPTION(oErrorReport, oCrashInfo): oException = oErrorReport.oException; # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oException.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oException.auParameters); pStowedExceptionsAddress = oException.auParameters[0]; uStowedExceptionsCount = oException.auParameters[1]; assert uStowedExceptionsCount == 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount; # The stowed exception replaces this exception: oErrorReport.oException = cStowedException.foCreate(oCrashInfo, oException.oProcess, pStowedExceptionsAddress); return oErrorReport;
def cErrorReport_foSpecialErrorReport_STATUS_STOWED_EXCEPTION( oErrorReport, oCdbWrapper): oException = oErrorReport.oException # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oException.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oException.auParameters) pStowedExceptionsAddresses = oException.auParameters[0] uStowedExceptionsCount = oException.auParameters[1] assert uStowedExceptionsCount < 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount # The stowed exception replaces this exception: oErrorReport.oException = cStowedException.foCreate( oCdbWrapper, oException.oProcess, pStowedExceptionsAddresses) return oErrorReport
def cBugReport_foAnalyzeException_STATUS_STOWED_EXCEPTION(oBugReport, oCdbWrapper, oException): # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oException.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oException.auParameters); pStowedExceptionsAddresses = oException.auParameters[0]; uStowedExceptionsCount = oException.auParameters[1]; assert uStowedExceptionsCount <= 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount; # Get the stowed exception and replace information in the bug report: oStowedException = cStowedException.foCreate(oCdbWrapper, pStowedExceptionsAddresses); oBugReport.sBugTypeId = oStowedException.sTypeId; oBugReport.sBugDescription = oStowedException.sDescription; oBugReport.sSecurityImpact = oStowedException.sSecurityImpact; oBugReport.oProcess = cProcess.foCreate(oCdbWrapper); oBugReport.oStack = cStack.foCreateFromAddress(oCdbWrapper, oStowedException.pStackTrace, oStowedException.uStackTraceSize); return oBugReport;
def cBugReport_foAnalyzeException_STATUS_STOWED_EXCEPTION( oBugReport, oCdbWrapper, oException): # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oException.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oException.auParameters) pStowedExceptionsAddresses = oException.auParameters[0] uStowedExceptionsCount = oException.auParameters[1] assert uStowedExceptionsCount <= 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount # Get the stowed exception and replace information in the bug report: oStowedException = cStowedException.foCreate(oCdbWrapper, pStowedExceptionsAddresses) oBugReport.sBugTypeId = oStowedException.sTypeId oBugReport.sBugDescription = oStowedException.sDescription oBugReport.sSecurityImpact = oStowedException.sSecurityImpact oBugReport.oProcess = cProcess.foCreate(oCdbWrapper) oBugReport.oStack = cStack.foCreateFromAddress( oCdbWrapper, oStowedException.pStackTrace, oStowedException.uStackTraceSize) return oBugReport
def foCreate(cSelf, oCrashInfo, uCode, sCodeDescription): oProcess = cProcess.foCreate(oCrashInfo); oSelf = cSelf(oProcess, uCode, sCodeDescription); # We do this twice to make sure symbols are loaded the first time, which may create additional symbal warnings and # errors that makes the output harder to parse. The second time, there will be no such output, so we can parse it # a lot easier. asExceptionRecord = oCrashInfo._fasSendCommandAndReadOutput(".exr -1"); if asExceptionRecord is None: return None; asExceptionRecord = oCrashInfo._fasSendCommandAndReadOutput(".exr -1"); if asExceptionRecord is None: return None; uParameterCount = None; uParameterIndex = None; for sLine in asExceptionRecord: oNameValueMatch = re.match(r"^\s*%s\s*$" % ( r"(\w+)(?:\[(\d+)\])?\:\s+" # (name) optional{ "[" (index) "]" } ":" whitespace r"([0-9A-F`]+)" # (value) r"(?:\s+\((.*)\))?" # optional{ whitespace "(" (symbol || description) ")" } ), sLine, re.I); if oNameValueMatch: sName, sIndex, sValue, sDetails = oNameValueMatch.groups(); uValue = int(sValue.replace("`", ""), 16); if sName == "ExceptionAddress": oSelf.uAddress = uValue; oSelf.sAddressSymbol = sDetails; elif sName == "ExceptionCode": assert uValue == uCode, \ "Exception record has an unexpected ExceptionCode value (0x%08X vs 0x%08X)" % (uValue, uCode); assert sDetails is None or sDetails == sCodeDescription, \ "Exception record has an unexpected ExceptionCode description (%s vs %s)" % \ (repr(sDetails), repr(sCodeDescription)); elif sName == "ExceptionFlags": oSelf.uFlags = uValue; elif sName == "NumberParameters": uParameterCount = uValue; uParameterIndex = 0; oSelf.auParameters = []; elif sName == "Parameter": assert int(sIndex, 16) == uParameterIndex, \ "Unexpected parameter #0x%s vs 0x%X" % (sIndex, uParameterIndex); oSelf.auParameters.append(uValue); uParameterIndex += 1; else: raise AssertionError("Unknown exception record value %s" % sLine); elif oSelf.sDetails is None: oSelf.sDetails = sLine; else: raise AssertionError("Superfluous exception record line %s" % sLine); assert oSelf.uAddress is not None, \ "Exception record is missing an ExceptionAddress value"; assert oSelf.uFlags is not None, \ "Exception record is missing an ExceptionFlags value"; assert uParameterCount is not None, \ "Exception record is missing an NumberParameters value"; assert uParameterCount == len(oSelf.auParameters), \ "Unexpected number of parameters (%d vs %d)" % (len(oSelf.auParameters), uParameterCount); # Now handle the information in the exception record and perform additional tasks as needed. Create an exception # id that uniquely identifies the exception and a description of the exception. if uCode == 0xC000027B: # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oSelf.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oSelf.auParameters); pStowedExceptionsAddress = oSelf.auParameters[0]; uStowedExceptionsCount = oSelf.auParameters[1]; assert uStowedExceptionsCount == 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount; # The stowed exception replaces this exception: return cStowedException.foCreate(oCrashInfo, oProcess, pStowedExceptionsAddress); elif uCode == STATUS_ACCESS_VIOLATION: # Parameter[0] = access type (0 = read, 1 = write, 8 = execute) # Parameter[1] = address assert len(oSelf.auParameters) == 2, \ "Unexpected number of access violation exception parameters (%d vs 2)" % len(oSelf.auParameters); # Access violation: add the type of operation and the location to the exception id. sViolationTypeId = "AV" + {0:"R", 1:"W", 8:"E"}.get(oSelf.auParameters[0], "?"); sViolationTypeDescription = {0:"reading", 1:"writing", 8:"executing"}.get(oSelf.auParameters[0], "0x%X-ing" % oSelf.auParameters[0]); uAddress = oSelf.auParameters[1]; sAddressId, sAddressDescription = ftsGetAddressIdAndDescription(uAddress); if sAddressId != "NULL": asPageHeapInformation = oCrashInfo._fasSendCommandAndReadOutput("!heap -p -a 0x%X" % uAddress); asPageHeapInformation = oCrashInfo._fasSendCommandAndReadOutput("!heap -p -a 0x%X" % uAddress); asPageHeapInformation = oCrashInfo._fasSendCommandAndReadOutput("!heap -p -a 0x%X" % (uAddress - 0x4)); if asPageHeapInformation is None: return None; #if uAddress & 0xFFF < 0x8: # # Assuming page heap is This may be a buffer overrun oSelf.sTypeId = "%s@%s" % (sViolationTypeId, sAddressId); oSelf.sDescription = "%s while %s memory at 0x%X (%s)" % \ (sCodeDescription, sViolationTypeDescription, uAddress, sAddressDescription); uNULLMinusOffsetMinAddress = {"x64": 0xFFFFFFFFFFFF0000, "x86": 0xFFFF0000}[oProcess.sISA]; oSelf.sSecurityImpact = ((uAddress > uNULLMinusOffsetMinAddress or uAddress < 0x10000) and "Not a security issue" or "Probably a security issue" ); elif uCode == STATUS_STACK_BUFFER_OVERRUN: # Parameter[0] = fail fast code assert len(oSelf.auParameters) == 1, \ "Unexpected number of fail fast exception parameters (%d vs 1)" % len(oSelf.auParameters); sCodeId, sCodeDescription, sSecurityImpact = \ ftsGetFailFastErrorCodeIdDescriptionAndSecurityImpact(oSelf.auParameters[0]); oSelf.sTypeId = "FF@%s" % sCodeId; oSelf.sDescription = "A critical issue was detected (code %d: %s)" % (oSelf.auParameters[0], sCodeDescription); oSelf.sSecurityImpact = sSecurityImpact; else: oSelf.sTypeId = fsGetExceptionTypeId(uCode); oSelf.sDescription = "%s (code 0x%08X)" % (sCodeDescription, uCode); oSelf.sSecurityImpact = fsGetSecurityImpact(uCode); # Get the stack oSelf.oStack = cStack.foCreate(oCrashInfo, oSelf.oProcess); if oSelf.oStack is None: return None; return oSelf;
def foCreate(cSelf, oCrashInfo, uCode, sCodeDescription): oProcess = cProcess.foCreate(oCrashInfo) oSelf = cSelf(oProcess, uCode, sCodeDescription) # We do this twice to make sure symbols are loaded the first time, which may create additional symbal warnings and # errors that makes the output harder to parse. The second time, there will be no such output, so we can parse it # a lot easier. asExceptionRecord = oCrashInfo._fasSendCommandAndReadOutput(".exr -1") if asExceptionRecord is None: return None asExceptionRecord = oCrashInfo._fasSendCommandAndReadOutput(".exr -1") if asExceptionRecord is None: return None uParameterCount = None uParameterIndex = None for sLine in asExceptionRecord: oNameValueMatch = re.match( r"^\s*%s\s*$" % ( r"(\w+)(?:\[(\d+)\])?\:\s+" # (name) optional{ "[" (index) "]" } ":" whitespace r"([0-9A-F`]+)" # (value) r"(?:\s+\((.*)\))?" # optional{ whitespace "(" (symbol || description) ")" } ), sLine, re.I) if oNameValueMatch: sName, sIndex, sValue, sDetails = oNameValueMatch.groups() uValue = int(sValue.replace("`", ""), 16) if sName == "ExceptionAddress": oSelf.uAddress = uValue oSelf.sAddressSymbol = sDetails elif sName == "ExceptionCode": assert uValue == uCode, \ "Exception record has an unexpected ExceptionCode value (0x%08X vs 0x%08X)" % (uValue, uCode) assert sDetails is None or sDetails == sCodeDescription, \ "Exception record has an unexpected ExceptionCode description (%s vs %s)" % \ (repr(sDetails), repr(sCodeDescription)) elif sName == "ExceptionFlags": oSelf.uFlags = uValue elif sName == "NumberParameters": uParameterCount = uValue uParameterIndex = 0 oSelf.auParameters = [] elif sName == "Parameter": assert int(sIndex, 16) == uParameterIndex, \ "Unexpected parameter #0x%s vs 0x%X" % (sIndex, uParameterIndex) oSelf.auParameters.append(uValue) uParameterIndex += 1 else: raise AssertionError("Unknown exception record value %s" % sLine) elif oSelf.sDetails is None: oSelf.sDetails = sLine else: raise AssertionError("Superfluous exception record line %s" % sLine) assert oSelf.uAddress is not None, \ "Exception record is missing an ExceptionAddress value" assert oSelf.uFlags is not None, \ "Exception record is missing an ExceptionFlags value" assert uParameterCount is not None, \ "Exception record is missing an NumberParameters value" assert uParameterCount == len(oSelf.auParameters), \ "Unexpected number of parameters (%d vs %d)" % (len(oSelf.auParameters), uParameterCount) # Now handle the information in the exception record and perform additional tasks as needed. Create an exception # id that uniquely identifies the exception and a description of the exception. if uCode == 0xC000027B: # Parameter[0] = paStowedExceptionInformationArray; # Parameter[1] = uStowedExceptionInformationArrayLength; assert len(oSelf.auParameters) == 2, \ "Unexpected number of WinRT language exception parameters (%d vs 2)" % len(oSelf.auParameters) pStowedExceptionsAddress = oSelf.auParameters[0] uStowedExceptionsCount = oSelf.auParameters[1] assert uStowedExceptionsCount == 1, \ "Unexpected number of WinRT language exception stowed exceptions (%d vs 1)" % uStowedExceptionsCount # The stowed exception replaces this exception: return cStowedException.foCreate(oCrashInfo, oProcess, pStowedExceptionsAddress) elif uCode == STATUS_ACCESS_VIOLATION: # Access violation: add the type of operation and the location to the exception id. sViolationTypeId = "AV" + { 0: "R", 1: "W", 8: "E" }.get(oSelf.auParameters[0], "?") sViolationTypeDescription = { 0: "reading", 1: "writing", 8: "executing" }.get(oSelf.auParameters[0], "?") uAddress = oSelf.auParameters[1] sAddressId = fsGetAddressId(uAddress) oSelf.sTypeId = "%s@%s" % (sViolationTypeId, sAddressId) oSelf.sDescription = "%s while %s memory at 0x%08X (%s)" % ( sCodeDescription, sViolationTypeDescription, uAddress, sAddressId) oSelf.sSecurityImpact = ( (uAddress > 0xFFFF0000 or uAddress < 0x10000) and "Not a security issue" or "Probably a security issue") else: oSelf.sTypeId = fsGetExceptionTypeId(uCode) oSelf.sDescription = "%s (code 0x%08X)" % (sCodeDescription, uCode) oSelf.sSecurityImpact = fsGetSecurityImpact(uCode) # Get the stack oSelf.oStack = cStack.foCreate(oCrashInfo, oSelf.oProcess) if oSelf.oStack is None: return None return oSelf