Пример #1
0
 def foCreate(cSelf, oCrashInfo, oProcess, pAddress):
   asData = oCrashInfo._fasSendCommandAndReadData("dd /c0xA @@masm(poi(0x%X)) L0xA" % pAddress);
   # https://msdn.microsoft.com/en-us/library/windows/desktop/dn600343%28v=vs.85%29.aspx
   # https://msdn.microsoft.com/en-us/library/windows/desktop/dn600342%28v=vs.85%29.aspx
   #StowedExceptionInformation = {
   #  0000      DWORD           dsSize
   #  0004      char[4]         sSignature      // "SE01" or "SE02"
   #  0008      HRESULT         hResultCode      
   #  000C      :2 bits         ExceptionForm   // LSB, &3 1 => with exception address and call stack, 2 => with error text
   #            :30 bits        ThreadId        // MSB, &0xfffffffc
   #  {
   #    0010    VOID*           pExceptionAddress
   #    0014    DWORD           dwStackTraceWordSize (4)
   #    0018    DWORD           StackTraceWords
   #    001c    VOID*           pStackTrace
   #  } or {
   #    0010    WCHAR*          sErrorText
   #  }
   #  0020      ULONG           NestedExceptionType; // "SE02" only
   #  0024      VOID*           NestedException;     // "SE02" only
   #}
   adwData = [];
   for sLine in asData:
     asData = re.split(r"\s+", sLine);
     asData.pop(0); # first value is address, the rest is data
     adwData.extend([int(sData, 16) for sData in asData]);
   assert len(adwData) == 10, "Unexpected data size %d extracted from %s" % (len(adwData), repr(asLines));
   dwSignature = adwData[1];
   assert dwSignature in [0x53453031, 0x53453032], "Unexpected signature 0x%X" % dwSignature;
   uCode = adwData[2];
   uExceptionForm = adwData[3] & 3;
   assert uExceptionForm in [1, 2], "Unexpected exception form %d" % uExceptionForm;
   if uExceptionForm == 1:
     oSelf = cSelf(oProcess, uCode, uAddress = adwData[4], pStackTrace = adwData[7], uStackTraceSize = adwData[6]);
   else:
     oSelf = cSelf(oProcess, uCode, sErrorText = adwData[4]);
   uNestedExceptionType = adwData[8];
   assert dwSignature == 0x53453031 or uNestedExceptionType == 0, "Unexpected nested exception type 0x%X" % adwData[8];
   
   # Create an exception id that uniquely identifies the exception and a description of the exception.
   oSelf.sTypeId = "%s(Stowed)" + fsGetExceptionTypeId(oSelf.uCode);
   oSelf.sDescription = "Stowed exception code 0x%08X" % oSelf.uCode;
   
   # Get the stack
   oSelf.oStack = cStack.foCreateFromAddress(oCrashInfo, oProcess, oSelf.pStackTrace, oSelf.uStackTraceSize);
   if oSelf.oStack is None: return None;
   
   return oSelf;
Пример #2
0
 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;
Пример #3
0
    def foCreate(cSelf, oCrashInfo, oProcess, pAddress):
        asData = oCrashInfo._fasSendCommandAndReadData(
            "dd /c0xA @@masm(poi(0x%X)) L0xA" % pAddress)
        # https://msdn.microsoft.com/en-us/library/windows/desktop/dn600343%28v=vs.85%29.aspx
        # https://msdn.microsoft.com/en-us/library/windows/desktop/dn600342%28v=vs.85%29.aspx
        #StowedExceptionInformation = {
        #  0000      DWORD           dsSize
        #  0004      char[4]         sSignature      // "SE01" or "SE02"
        #  0008      HRESULT         hResultCode
        #  000C      :2 bits         ExceptionForm   // LSB, &3 1 => with exception address and call stack, 2 => with error text
        #            :30 bits        ThreadId        // MSB, &0xfffffffc
        #  {
        #    0010    VOID*           pExceptionAddress
        #    0014    DWORD           dwStackTraceWordSize (4)
        #    0018    DWORD           StackTraceWords
        #    001c    VOID*           pStackTrace
        #  } or {
        #    0010    WCHAR*          sErrorText
        #  }
        #  0020      ULONG           NestedExceptionType; // "SE02" only
        #  0024      VOID*           NestedException;     // "SE02" only
        #}
        adwData = []
        for sLine in asData:
            asData = re.split(r"\s+", sLine)
            asData.pop(0)
            # first value is address, the rest is data
            adwData.extend([int(sData, 16) for sData in asData])
        assert len(
            adwData) == 10, "Unexpected data size %d extracted from %s" % (
                len(adwData), repr(asLines))
        dwSignature = adwData[1]
        assert dwSignature in [0x53453031, 0x53453032
                               ], "Unexpected signature 0x%X" % dwSignature
        uCode = adwData[2]
        uExceptionForm = adwData[3] & 3
        assert uExceptionForm in [
            1, 2
        ], "Unexpected exception form %d" % uExceptionForm
        if uExceptionForm == 1:
            oSelf = cSelf(oProcess,
                          uCode,
                          uAddress=adwData[4],
                          pStackTrace=adwData[7],
                          uStackTraceSize=adwData[6])
        else:
            oSelf = cSelf(oProcess, uCode, sErrorText=adwData[4])
        uNestedExceptionType = adwData[8]
        assert dwSignature == 0x53453031 or uNestedExceptionType == 0, "Unexpected nested exception type 0x%X" % adwData[
            8]

        # Create an exception id that uniquely identifies the exception and a description of the exception.
        oSelf.sTypeId = "%s(Stowed)" + fsGetExceptionTypeId(oSelf.uCode)
        oSelf.sDescription = "Stowed exception code 0x%08X" % oSelf.uCode

        # Get the stack
        oSelf.oStack = cStack.foCreateFromAddress(oCrashInfo, oProcess,
                                                  oSelf.pStackTrace,
                                                  oSelf.uStackTraceSize)
        if oSelf.oStack is None: return None

        return oSelf
Пример #4
0
    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