3 |
4 |
5 | %(sContent)s
6 |
7 |
⇓ click on the title of a section to open or close it.
8 |
9 | """.lstrip("\r\n");
10 |
11 |
--------------------------------------------------------------------------------
/mBugTranslations/ASan.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | def fDisableDetectionOfAccessViolations(oCdbWrapper, oBugReport):
4 | oCdbWrapper.fbFireCallbacks("ASan detected");
5 | oCdbWrapper.fasbExecuteCdbCommand(
6 | sbCommand = b"sxd av",
7 | sb0Comment = b"Disable handling of exceptions because ASan throws too many",
8 | );
9 |
10 | aoBugTranslations = [
11 | # AVs during initialization --> expected, not a bug.
12 | cBugTranslation(
13 | srzOriginalBugTypeId = r"AVW:Reserved\[(0x)?[\dA-F]+n?\]@\d+",
14 | azs0rbAppliesOnlyToTopStackFrame = [
15 | rb".*!__asan::FastPoisonShadow",
16 | ],
17 | s0zTranslatedBugTypeId = None,
18 | f0Callback = fDisableDetectionOfAccessViolations
19 | ),
20 | # IllegalInstruction --> ASan
21 | cBugTranslation(
22 | srzOriginalBugTypeId = r"IllegalInstruction",
23 | azs0rbAppliesOnlyToTopStackFrame = [
24 | rb".*!__sanitizer::Trap",
25 | ],
26 | s0zTranslatedBugTypeId = "ASan",
27 | # This is a backup in case cAsanErrorDetector does not detect and handle the ASan debug output we normally expect.
28 | s0zTranslatedBugDescription = "ASan triggered an illegal instruction to indicate it detected an issue which cBugId does not recognize.",
29 | s0zTranslatedSecurityImpact = "The security implications of this issue are unknown",
30 | ),
31 | # ASan --> (hide irrelevant frames only)
32 | cBugTranslation(
33 | srzOriginalBugTypeId = "ASan",
34 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
35 | rb".*!agent::asan::\w+.*",
36 | rb".*!_*asan_\w+.*",
37 | rb".*!__asan::\w+.*",
38 | rb".*!__sanitizer::\w+.*",
39 | rb".*!uprv_realloc_60",
40 | ],
41 | ),
42 | ];
--------------------------------------------------------------------------------
/mBugTranslations/Cpp.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb".*!_?CxxThrowException",
8 | rb".*!abort",
9 | ],
10 | ),
11 | # Breakpoint -> OOM
12 | cBugTranslation(
13 | srzOriginalBugTypeId = r"Breakpoint",
14 | azs0rbAppliesOnlyToTopStackFrame = [
15 | rb".*!malloc",
16 | ],
17 | s0zTranslatedBugTypeId = "OOM",
18 | s0zTranslatedBugDescription = "The application triggered a breakpoint exception to indicate it was unable to allocate enough memory.",
19 | s0zTranslatedSecurityImpact = None,
20 | ),
21 | # C++:std::bad_alloc -> OOM
22 | cBugTranslation(
23 | srzOriginalBugTypeId = r"C\+\+:std::bad_alloc",
24 | s0zTranslatedBugTypeId = "OOM",
25 | s0zTranslatedBugDescription = "The application triggered a C++ std::bad_alloc exception to indicate it was unable to allocate enough memory.",
26 | s0zTranslatedSecurityImpact = None,
27 | ),
28 | # AppExit -> PureCall
29 | cBugTranslation(
30 | srzOriginalBugTypeId = r"AppExit",
31 | azs0rbAppliesOnlyToTopStackFrame = [
32 | rb".*!_?purecall",
33 | ],
34 | s0zTranslatedBugTypeId = "PureCall",
35 | s0zTranslatedBugDescription = "Pure virtual function call (R6025).",
36 | s0zTranslatedSecurityImpact = "This is a potentially exploitable security issue",
37 | ),
38 | # PureCall -> hide irrelevant frames
39 | cBugTranslation(
40 | srzOriginalBugTypeId = r"PureCall",
41 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
42 | rb".*!_?purecall",
43 | ],
44 | ),
45 | # StackExhaustion (hide irrelevant frames)
46 | cBugTranslation(
47 | srzOriginalBugTypeId = r"StackExhaustion",
48 | azs0rbAppliesOnlyToTopStackFrame = [
49 | rb".*!__?chkstk",
50 | ],
51 | ),
52 | # hide irrelevant heap management frames
53 | cBugTranslation(
54 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
55 | rb".*!(m|re)alloc",
56 | rb".*!mem(chr|cmp|cpy|move|set)",
57 | rb".*!(.+::)?operator (delete|new(\[\])?)",
58 | rb".*!__scrt_throw_std_bad_alloc",
59 | rb".*!str(n?cat|r?chr|n?cmp|n?cpy|len|str)",
60 | rb".*!std::_.*",
61 | rb".*!std::allocator<.+>::.*",
62 | rb".*!std::basic_string<.+>::.*",
63 | rb".*!std::vector<.+>::.*",
64 | ],
65 | ),
66 | ];
67 |
--------------------------------------------------------------------------------
/mBugTranslations/Firefox.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Breakpoint -> hide irrelevant stack frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"(mozglue|xul)\.dll!Abort",
8 | rb"(mozglue|xul)\.dll!arena_\w+",
9 | rb"(mozglue|xul)\.dll!(.*::)?\w+alloc(<.+>|::.*)?",
10 | rb"(mozglue|xul)\.dll!collections::vec::Vec<.+>::reserve<.+>",
11 | rb"(mozglue|xul)\.dll!moz_abort",
12 | rb"(mozglue|xul)\.dll!mozalloc_abort",
13 | ],
14 | ),
15 | # Breakpoint -> OOM
16 | cBugTranslation(
17 | srzOriginalBugTypeId = r"Breakpoint",
18 | azs0rbAppliesOnlyToTopStackFrame = [
19 | rb"mozglue\.dll!arena_run_split",
20 | rb"mozglue\.dll!mozalloc_handle_oom",
21 | rb"mozglue\.dll!pages_commit",
22 | rb"xul\.dll!js::CrashAtUnhandlableOOM",
23 | rb"xul\.dll!js::AutoEnterOOMUnsafeRegion::crash",
24 | rb"xul\.dll!NS_ABORT_OOM",
25 | ],
26 | s0zTranslatedBugTypeId = "OOM",
27 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
28 | s0zTranslatedSecurityImpact = None,
29 | ),
30 | # IllegalInstruction -> OOM
31 | cBugTranslation(
32 | srzOriginalBugTypeId = r"IllegalInstruction",
33 | azs0rbAppliesOnlyToTopStackFrame = [
34 | rb"xul\.dll!alloc::oom::default_oom_handler",
35 | rb"xul\.dll!alloc::heap::\{\{impl\}\}::oom",
36 | ],
37 | s0zTranslatedBugTypeId = "OOM",
38 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
39 | s0zTranslatedSecurityImpact = None,
40 | ),
41 | # IllegalInstruction without symbol -> ignore
42 | # JIT compiled JavaScript uses it to signal stuff, e.g. MacroAssembler::wasmTrapInstruction.
43 | # JIT compiled Javascript is generated assembly, hence there is no symbol.
44 | cBugTranslation(
45 | srzOriginalBugTypeId = r"IllegalInstruction",
46 | azs0rbAppliesOnlyToTopStackFrame = [
47 | None,
48 | ],
49 | s0zTranslatedBugTypeId = None,
50 | bDebug = True,
51 | ),
52 | # Breakpoint -> Assert
53 | cBugTranslation(
54 | srzOriginalBugTypeId = r"Breakpoint",
55 | azs0rbAppliesOnlyToTopStackFrame = [
56 | rb"xul\.dll!NS_DebugBreak",
57 | ],
58 | s0zTranslatedBugTypeId = "Assert",
59 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate an assertion failed.",
60 | s0zTranslatedSecurityImpact = "Unlikely to be exploitable, unless you can find a way to avoid this breakpoint.",
61 | ),
62 | ];
63 |
--------------------------------------------------------------------------------
/mBugTranslations/RTC.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [];
4 | aoBugTranslations.append(cBugTranslation(
5 | srzOriginalBugTypeId = r"Breakpoint",
6 | azs0rbAppliesOnlyToTopStackFrame = [
7 | rb".*!failwithmessage",
8 | rb".*!_RTC_StackFailure",
9 | ],
10 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
11 | rb".*!_RTC_CheckStackVars\d*",
12 | ],
13 | s0zTranslatedBugTypeId = "OOBW:Stack",
14 | s0zTranslatedBugDescription = "The Windows Run-Time detected that a stack variable was modified, which suggests an out-of-bounds write on the stack.",
15 | s0zTranslatedSecurityImpact = "Potentially exploitable security issue",
16 | ));
17 |
--------------------------------------------------------------------------------
/mBugTranslations/SafeInt.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # IntegerOverflow -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb".*!SafeIntExceptionHandler<.+>::SafeIntOnOverflow",
8 | rb".*!msl::utilities::SafeIntErrorPolicy_SafeIntException::SafeIntOnOverflow",
9 | ],
10 | ),
11 | cBugTranslation(
12 | srzOriginalBugTypeId = r"C\+\+:msl::utilities::SafeIntException",
13 | s0zTranslatedBugTypeId = "SafeInt",
14 | s0zTranslatedBugDescription = "The application attempted to store an integer value in an integer type that cannot contain this value.",
15 | s0zTranslatedSecurityImpact = None,
16 | ),
17 | cBugTranslation(
18 | srzOriginalBugTypeId = r"SafeInt",
19 | azs0rbAppliesOnlyToTopStackFrame = [
20 | rb".*!msl::utilities::SafeInt<.+>::operator\+\+",
21 | ],
22 | s0zTranslatedBugTypeId = "IntegerOverflow",
23 | s0zTranslatedBugDescription = "The application attempted to increase an integer above its maxium value.",
24 | s0zTranslatedSecurityImpact = None,
25 | ),
26 | cBugTranslation(
27 | srzOriginalBugTypeId = r"SafeInt",
28 | azs0rbAppliesOnlyToTopStackFrame = [
29 | rb".*!msl::utilities::SafeInt<.+>::operator\-\-",
30 | ],
31 | s0zTranslatedBugTypeId = "IntegerUnderflow",
32 | s0zTranslatedBugDescription = "The application attempted to decrease an integer below its minimum value.",
33 | s0zTranslatedSecurityImpact = None,
34 | ),
35 | cBugTranslation(
36 | srzOriginalBugTypeId = r"SafeInt",
37 | azs0rbAppliesOnlyToTopStackFrame = [
38 | rb".*!msl::utilities::details::MultiplicationHelper<.+>::Multiply",
39 | ],
40 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
41 | rb".*!msl::utilities::SafeInt<...>::operator\*=<.+>",
42 | ],
43 | s0zTranslatedBugTypeId = "IntegerTruncation",
44 | s0zTranslatedBugDescription = "The application attempted to store the result of a multiplication in an integer that cannot contain this value.",
45 | s0zTranslatedSecurityImpact = None,
46 | ),
47 | cBugTranslation(
48 | srzOriginalBugTypeId = r"SafeInt",
49 | azs0rbAppliesOnlyToTopStackFrame = [
50 | rb".*!msl::utilities::details::LargeIntRegMultiply<.+>::RegMultiply",
51 | ],
52 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
53 | rb".*!msl::utilities::details::LargeIntRegMultiply<.*>::.*",
54 | rb".*!msl::utilities::details::MultiplicationHelper<.*>::.*",
55 | rb".*!msl::utilities::SafeInt<...>::operator\*=<.+>",
56 | ],
57 | s0zTranslatedBugTypeId = "IntegerTruncation",
58 | s0zTranslatedBugDescription = "The application attempted to store the result of a multiplication in an integer that cannot contain this value.",
59 | s0zTranslatedSecurityImpact = None,
60 | ),
61 | cBugTranslation(
62 | srzOriginalBugTypeId = r"SafeInt",
63 | azs0rbAppliesOnlyToTopStackFrame = [
64 | rb".*!msl::utilities::details::SafeCastHelper<.+>::Cast",
65 | ],
66 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
67 | rb".*!msl::utilities::SafeInt<.+>::SafeInt<.+><.+>",
68 | rb".*!msl::utilities::SafeInt<.+>::operator=<.+>",
69 | ],
70 | s0zTranslatedBugTypeId = "IntegerTruncation",
71 | s0zTranslatedBugDescription = "The application attempted to store a value in an integer that cannot contain this value.",
72 | s0zTranslatedSecurityImpact = None,
73 | ),
74 | ];
75 |
--------------------------------------------------------------------------------
/mBugTranslations/SlashGS.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [];
4 | # OOBW@Stack (hide irrelevant frames only)
5 | aoBugTranslations.append(cBugTranslation(
6 | srzOriginalBugTypeId = r"OOBW:Stack",
7 | azs0rbAppliesOnlyToTopStackFrame = [
8 | rb".*!__security_check_cookie",
9 | ],
10 | ));
11 |
--------------------------------------------------------------------------------
/mBugTranslations/V8.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # AVE@NULL -> Assert
5 | cBugTranslation(
6 | srzOriginalBugTypeId = r"AVE@NULL",
7 | azs0rbAppliesOnlyToTopStackFrame = [
8 | rb".*!v8::base::OS::Abort",
9 | ],
10 | s0zTranslatedBugTypeId = "Assert",
11 | s0zTranslatedBugDescription = "The application caused an access violation by calling NULL to indicate an assertion failed.",
12 | s0zTranslatedSecurityImpact = None,
13 | ),
14 | # AVE@NULL -> Assert
15 | cBugTranslation(
16 | srzOriginalBugTypeId = r"AVE@NULL",
17 | azs0rbAppliesOnlyToTopStackFrame = [
18 | rb".*!V8_Fatal",
19 | ],
20 | s0zTranslatedBugTypeId = "Assert",
21 | s0zTranslatedBugDescription = "The application caused an access violation by calling NULL to indicate an assertion failed.",
22 | s0zTranslatedSecurityImpact = None,
23 | ),
24 | # Assert -> ignore functions
25 | cBugTranslation(
26 | srzOriginalBugTypeId = r"Assert",
27 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
28 | rb".*!V8_Fatal",
29 | rb".*!v8::base::OS::Abort",
30 | rb".*!v8::MaybeLocal<.+>::ToLocalChecked",
31 | rb".*!v8::Utils::ReportApiFailure",
32 | rb".*!v8::Utils::ApiCheck",
33 | rb".*!v8::V8::ToLocalEmpty",
34 | rb".*!v8::MaybeLocal",
35 | ],
36 | ),
37 | # Assert -> OOM
38 | cBugTranslation(
39 | srzOriginalBugTypeId = r"Assert",
40 | azs0rbAppliesOnlyToTopStackFrame = [
41 | rb".*!v8::internal::V8::FatalProcessOutOfMemory",
42 | ],
43 | s0zTranslatedBugTypeId = "OOM",
44 | s0zTranslatedBugDescription = "The application caused a fatal exception to indicate it was unable to allocate enough memory.",
45 | s0zTranslatedSecurityImpact = None,
46 | ),
47 | # Assert -> OOM
48 | cBugTranslation(
49 | srzOriginalBugTypeId = r"Assert",
50 | azs0rbAppliesOnlyToTopStackFrame = [
51 | rb".*!v8::Utils::ReportOOMFailure",
52 | ],
53 | s0zTranslatedBugTypeId = "OOM",
54 | s0zTranslatedBugDescription = "The application caused a fatal exception to indicate it was unable to allocate enough memory.",
55 | s0zTranslatedSecurityImpact = None,
56 | ),
57 | ];
58 |
--------------------------------------------------------------------------------
/mBugTranslations/__init__.py:
--------------------------------------------------------------------------------
1 | from .mBugTranslations import *;
2 |
--------------------------------------------------------------------------------
/mBugTranslations/chakra_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Breakpoint -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"chakra\.dll!ReportFatalException",
8 | rb"chakra\.dll!Js::Exception::RaiseIfScriptActive",
9 | rb"chakra\.dll!Js::JavascriptError::ThrowOutOfMemoryError",
10 | rb"chakra\.dll!Js::Throw::OutOfMemory",
11 | rb"chakra\.dll!Memory::HeapAllocator::Alloc",
12 | ],
13 | ),
14 | cBugTranslation(
15 | srzOriginalBugTypeId = r"Breakpoint",
16 | azs0rbAppliesOnlyToTopStackFrame = [
17 | rb"chakra\.dll!Js::Throw::FatalInternalError",
18 | ],
19 | s0zTranslatedBugTypeId = "Assert",
20 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate a fatal error was detected.",
21 | s0zTranslatedSecurityImpact = None,
22 | ),
23 | # Breakpoint -> OOM
24 | cBugTranslation(
25 | srzOriginalBugTypeId = r"Breakpoint",
26 | azs0rbAppliesOnlyToTopStackFrame = [
27 | rb"chakra\.dll!MarkStack_OOM_fatal_error",
28 | rb"chakra\.dll!JavascriptDispatch_OOM_fatal_error",
29 | rb"chakra\.dll!OutOfMemory_fatal_error",
30 | rb"chakra\.dll!Js::JavascriptError::ThrowOutOfMemoryError",
31 | rb"chakra\.dll!Js::JavascriptExceptionOperators::ThrowOutOfMemory",
32 | ],
33 | s0zTranslatedBugTypeId = "OOM",
34 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
35 | s0zTranslatedSecurityImpact = None,
36 | ),
37 | ];
38 |
--------------------------------------------------------------------------------
/mBugTranslations/clr_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"clr\.dll!RaiseTheExceptionInternalOnly",
8 | rb"clr\.dll!IL_Throw",
9 | ],
10 | ),
11 | ];
--------------------------------------------------------------------------------
/mBugTranslations/combase_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"combase\.dll!SendReport",
8 | rb"combase\.dll!RoOriginateError",
9 | rb"combase\.dll!RoFailFastWithErrorContextInternal2",
10 | rb".*!RoFailFastWithErrorContext", # This function is actually in the binary that contains the code that triggered it.
11 | ],
12 | ),
13 | ];
14 |
--------------------------------------------------------------------------------
/mBugTranslations/conhost_exe.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"conhost\.exe!o_terminate",
8 | rb"conhost\.exe!_scrt_unhandled_exception_filter",
9 | ],
10 | ),
11 | ];
12 |
--------------------------------------------------------------------------------
/mBugTranslations/corpol_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [];
4 | # AVE@Arbitrary -> Ignored
5 | aoBugTranslations.append(cBugTranslation(
6 | # corpol.dll can test if DEP is enabled by storing a RET instruction in RW memory and calling it. This causes an
7 | # access violation if DEP is enabled, which is caught and handled. Therefore this exception should be ignored:
8 | srzOriginalBugTypeId = r"AVE@Arbitrary",
9 | azs0rbAppliesOnlyToTopStackFrame = [
10 | rb"\(unknown\)", # The location where the RET instruction is stored is not inside a module and has no symbol.
11 | rb"corpol\.dll!IsNxON",
12 | ],
13 | s0zTranslatedBugTypeId = None, # This is not a bug; allow the application to continue running.
14 | s0zTranslatedBugDescription = None,
15 | s0zTranslatedSecurityImpact = None,
16 | ));
17 |
--------------------------------------------------------------------------------
/mBugTranslations/edgecontent_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Assert -> OOM
5 | cBugTranslation(
6 | srzOriginalBugTypeId = r"Assert",
7 | azs0rbAppliesOnlyToTopStackFrame = [
8 | rb"edgecontent\.dll!`anonymous namespace'::MemoryLimitWatchdogThreadProc",
9 | ],
10 | s0zTranslatedBugTypeId = "OOM",
11 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
12 | s0zTranslatedSecurityImpact = None,
13 | ),
14 | ];
15 |
--------------------------------------------------------------------------------
/mBugTranslations/edgehtml_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # OOM -> hide irrelevant frames
5 | cBugTranslation(
6 | srzOriginalBugTypeId = r"OOM",
7 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
8 | rb"edgehtml\.dll!Streams::Chunk<.+>::InternalAlloc",
9 | ],
10 | ),
11 | ];
12 |
--------------------------------------------------------------------------------
/mBugTranslations/iso.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Assert -> OOM
5 | cBugTranslation(
6 | srzOriginalBugTypeId = r"Assert(:HRESULT)?",
7 | azs0rbAppliesOnlyToTopStackFrame = [
8 | rb".*!CIsoMalloc::_InitializeEntry",
9 | ],
10 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
11 | rb".*!CIsoScope::_?Alloc\w+",
12 | rb".*!IsoAllocMessageBuffer",
13 | ],
14 | s0zTranslatedBugTypeId = "OOM",
15 | s0zTranslatedBugDescription = "The application triggered a fail fast application exit to indicate it was unable to allocate enough memory.",
16 | s0zTranslatedSecurityImpact = "Unlikely to be exploitable, unless you can find a way to avoid this breakpoint.",
17 | ),
18 | ];
19 |
--------------------------------------------------------------------------------
/mBugTranslations/jscript9_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Breakpoint -> ignore stack
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"jscript9\.dll!ReportFatalException",
8 | ],
9 | ),
10 | cBugTranslation(
11 | srzOriginalBugTypeId = r"Breakpoint",
12 | azs0rbAppliesOnlyToTopStackFrame = [
13 | rb"jscript9\.dll!JavascriptDispatch_OOM_fatal_error",
14 | ],
15 | s0zTranslatedBugTypeId = "OOM",
16 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
17 | s0zTranslatedSecurityImpact = None,
18 | ),
19 | ];
20 |
--------------------------------------------------------------------------------
/mBugTranslations/kernel32_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"kernel32\.dll!RaiseExceptionStub",
8 | rb"kernel32\.dll!HeapFreeStub",
9 | ],
10 | ),
11 | ];
12 |
--------------------------------------------------------------------------------
/mBugTranslations/kernelbase_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | cBugTranslation(
5 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
6 | # There are a lot of helper functions that clutter the stack without
7 | # providing insight into the issue. These are all hidden by BugId:
8 | rb"kernelbase\.dll!DebugBreak",
9 | rb"kernelbase\.dll!FindClose",
10 | rb"kernelbase\.dll!LocalFree",
11 | rb"kernelbase\.dll!Raise.*Exception",
12 | rb"kernelbase\.dll!UnhandledExceptionFilter",
13 | rb"kernelbase\.dll!TerminateProcessOnMemoryExhaustion",
14 | ],
15 | ),
16 | ];
17 |
--------------------------------------------------------------------------------
/mBugTranslations/mBugTranslations.py:
--------------------------------------------------------------------------------
1 | from .fApplyBugTranslationsToBugReport import fApplyBugTranslationsToBugReport;
2 | __all__ = [
3 | "fApplyBugTranslationsToBugReport",
4 | ];
5 |
--------------------------------------------------------------------------------
/mBugTranslations/mshtml_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Breakpoint -> OOM
5 | cBugTranslation(
6 | srzOriginalBugTypeId = r"Breakpoint",
7 | azs0rbAppliesOnlyToTopStackFrame = [
8 | rb"mshtml\.dll!ReportFatalException",
9 | rb"mshtml\.dll!MarkStack_OOM_fatal_error",
10 | ],
11 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
12 | rb"mshtml\.dll!Memory::.*",
13 | rb"mshtml\.dll!MemoryProtection::.*",
14 | ],
15 | s0zTranslatedBugTypeId = "OOM",
16 | s0zTranslatedBugDescription = "The application triggered a breakpoint to indicate it was unable to allocate enough memory.",
17 | s0zTranslatedSecurityImpact = None,
18 | ),
19 | ];
--------------------------------------------------------------------------------
/mBugTranslations/ntdll_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | cBugTranslation(
5 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
6 | # There are a lot of helper functions that clutter the stack without
7 | # providing insight into the issue. These are all hidden by BugId:
8 | rb"ntdll\.dll!_C_specific_handler",
9 | rb"ntdll\.dll!DbgBreakPoint",
10 | rb"ntdll\.dll!DbgUiRemoteBreakin",
11 | rb"ntdll\.dll!FindNodeOrParent",
12 | rb"ntdll\.dll!Ki.*UserExceptionDispatcher",
13 | rb"ntdll\.dll!.*HandleInvalidUserCallTarget",
14 | rb"ntdll\.dll!RtlDispatchException",
15 | rb"ntdll\.dll!Rtl.*CriticalSection",
16 | rb"ntdll\.dll!RtlFailFast\d*",
17 | rb"ntdll\.dll!RtlInsertElementGenericTableAvl",
18 | rb"ntdll\.dll!Rtl.*(Allocate|Free).*Heap.*\w*",
19 | rb"ntdll\.dll!RtlpExecuteHandlerForException",
20 | rb"ntdll\.dll!RtlpFreeDebugInfo",
21 | rb"ntdll\.dll!RtlRaiseException",
22 | rb"ntdll\.dll!RtlReportCriticalFailure",
23 | rb"ntdll\.dll!RtlUserThreadStart\$filt\$0",
24 | rb"ntdll\.dll!v?DbgPrint.*",
25 | ],
26 | ),
27 | cBugTranslation(
28 | # Breakpoint when intializing process -> ignore.
29 | srzOriginalBugTypeId = r"Breakpoint",
30 | azs0rbAppliesOnlyToTopStackFrame = [
31 | rb"ntdll\.dll!LdrpDoDebuggerBreak",
32 | rb"ntdll\.dll!LdrpInitializeProcess",
33 | ],
34 | s0zTranslatedBugTypeId = None,
35 | ),
36 | # Breakpoint -> HeapCorrupt
37 | cBugTranslation(
38 | srzOriginalBugTypeId = r"Breakpoint",
39 | azs0rbAppliesOnlyToTopStackFrame = [
40 | rb"ntdll\.dll!RtlpHeapHandleError",
41 | rb"ntdll\.dll!RtlpBreakPointHeap",
42 | ],
43 | s0zTranslatedBugTypeId = "HeapCorrupt",
44 | s0zTranslatedBugDescription = "A breakpoint was triggered to indicate heap corruption was detected",
45 | s0zTranslatedSecurityImpact = "This is probably an exploitable security issue",
46 | ),
47 | # AVR@Reserved -> AVR@CFG
48 | cBugTranslation(
49 | srzOriginalBugTypeId = r"AVR@(?:Reserved|Invalid)",
50 | azs0rbAppliesOnlyToTopStackFrame = [
51 | rb"ntdll\.dll!LdrpDispatchUserCallTarget",
52 | rb"ntdll\.dll!LdrpValidateUserCallTarget(?:BitMapCheck|ES)?",
53 | ],
54 | s0zTranslatedBugTypeId = "AVR@CFG",
55 | s0zTranslatedBugDescription = "The process attempted to call a function using an invalid function pointer, " \
56 | "which caused an access violation exception in Control Flow Guard. This is often caused by a NULL pointer.",
57 | s0zTranslatedSecurityImpact = "Unlikely to be an exploitable security issue, unless you can control the invalid function pointer",
58 | ),
59 | # AVE:NULL @ ntdll.dll!NtWow64IsProcessorFeaturePresent -> ignore
60 | cBugTranslation(
61 | srzOriginalBugTypeId = r"AVE:NULL",
62 | azs0rbAppliesOnlyToTopStackFrame = [
63 | rb"ntdll\.dll!NtWow64IsProcessorFeaturePresent",
64 | ],
65 | s0zTranslatedBugTypeId = None,
66 | ),
67 | # AVW:NULL @ ntdll.dll!RtlpWaitOnCriticalSection -> ignore
68 | cBugTranslation(
69 | srzOriginalBugTypeId = r"AVW:NULL(\+.*)?",
70 | azs0rbAppliesOnlyToTopStackFrame = [
71 | rb"ntdll\.dll!RtlpWaitOnCriticalSection",
72 | ],
73 | s0zTranslatedBugTypeId = None,
74 | ),
75 | ];
--------------------------------------------------------------------------------
/mBugTranslations/oledb32_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Apparently this code will try to see if a string is NULL terminated by
5 | # scanning memory until it sees a NULL, regardless of the size of the buffer
6 | # This code is wrapped in an exception handler to detect when it is reading
7 | # memory out of bounds. This is of course a very bad idea, but it is how
8 | # things work in MS Office... sigh.
9 | cBugTranslation(
10 | srzOriginalBugTypeId = r"OOBR\[.*\].*",
11 | azs0rbAppliesOnlyToTopStackFrame = [
12 | rb"oledb32\.dll!SafeCheckWCharNullTermination",
13 | ],
14 | s0zTranslatedBugTypeId = None,
15 | ),
16 | ];
--------------------------------------------------------------------------------
/mBugTranslations/ucrtbase_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb"ucrtbase\.dll!abort",
8 | rb"ucrtbase\.dll!terminate",
9 | rb"ucrtbase\.dll!__crt_state_management::wrapped_invoke<.+>",
10 | ],
11 | ),
12 | ];
13 |
--------------------------------------------------------------------------------
/mBugTranslations/verifier_dll.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # Everything reported through a verifier stop should get the verifier calls removed, as these are not relevant to
5 | # the bug; they are only the messenger.
6 | cBugTranslation(
7 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
8 | rb"verifier\.dll!.*",
9 | ],
10 | ),
11 | ];
12 |
--------------------------------------------------------------------------------
/mBugTranslations/wil.py:
--------------------------------------------------------------------------------
1 | from .cBugTranslation import cBugTranslation;
2 |
3 | aoBugTranslations = [
4 | # * -> hide irrelevant frames
5 | cBugTranslation(
6 | azs0rbAdditionalIrrelevantStackFrameSymbols = [
7 | rb".*!wil::details::DebugBreak",
8 | rb".*!wil::details::in1diag3::Throw_.+",
9 | rb".*!wil::details::ReportFailure_.+",
10 | rb".*!wil::details::ThrowResultExceptionInternal",
11 | rb".*!wil::details::WilDynamicLoadRaiseFailFastException",
12 | rb".*!wil::details::WilFailFast",
13 | rb".*!wil::details::WilRaiseFailFastException",
14 | ],
15 | ),
16 | # AppExit -> Assert
17 | cBugTranslation(
18 | azs0rbAppliesOnlyToTopStackFrame = [
19 | rb".*!wil::details::ReportFailure",
20 | ],
21 | s0zTranslatedBugTypeId = "Assert",
22 | s0zTranslatedBugDescription = "The application triggered a fail fast application exit to indicate an assertion failed.",
23 | s0zTranslatedSecurityImpact = "Unlikely to be exploitable.",
24 | ),
25 | # Assert -> Assert:Win32
26 | cBugTranslation(
27 | azs0rbAppliesOnlyToTopStackFrame = [
28 | rb".*!wil::details::(?:ReportFailure|in1diag3::_?FailFast)_Win32",
29 | ],
30 | s0zTranslatedBugTypeId = "Assert:Win32",
31 | ),
32 | # Assert -> Assert:HRESULT
33 | cBugTranslation(
34 | azs0rbAppliesOnlyToTopStackFrame = [
35 | rb".*!wil::details::(?:ReportFailure|in1diag3::_?FailFast)_Hr",
36 | ],
37 | s0zTranslatedBugTypeId = "Assert:HRESULT",
38 | ),
39 | # Assert -> Assert:Unexpected
40 | cBugTranslation(
41 | azs0rbAppliesOnlyToTopStackFrame = [
42 | rb".*!wil::details::(?:ReportFailure|in1diag3::_?FailFast)_Unexpected",
43 | ],
44 | s0zTranslatedBugTypeId = "Assert:Unexpected",
45 | ),
46 | # Assert -> OOM
47 | cBugTranslation(
48 | azs0rbAppliesOnlyToTopStackFrame = [
49 | rb".*!wil::details::(?:ReportFailure|in1diag3::_?FailFast)_NullAlloc",
50 | ],
51 | s0zTranslatedBugTypeId = "OOM",
52 | s0zTranslatedBugDescription = "The application was unable to allocate enough memory.",
53 | ),
54 | # Assert:HRESULT -> OOM
55 | cBugTranslation(
56 | azs0rbAppliesOnlyToTopStackFrame = [
57 | rb".*!wil::details::in1diag3::_?FailFast_NullAlloc",
58 | ],
59 | s0zTranslatedBugTypeId = "OOM",
60 | s0zTranslatedBugDescription = "The application was unable to allocate enough memory.",
61 | ),
62 | ];
63 |
--------------------------------------------------------------------------------
/mDisassembler/__init__.py:
--------------------------------------------------------------------------------
1 | from .cDisassembly import cDisassembly;
2 | from .cInstruction import cInstruction;
3 | from .fo0GetDisassemblyForProcessStartAddressAndNumberOfBytes import fo0GetDisassemblyForProcessStartAddressAndNumberOfBytes;
4 | from .fo0GetDisassemblyForProcessStartAddressAndNumberOfInstructions import fo0GetDisassemblyForProcessStartAddressAndNumberOfInstructions;
5 | from .fo0GetInstructionForProcessAndAddress import fo0GetInstructionForProcessAndAddress;
6 | from .fo0GetInstructionForProcessAndBeforeAddress import fo0GetInstructionForProcessAndBeforeAddress;
7 |
8 | __all__ = [
9 | "cDisassembly",
10 | "cInstruction",
11 | "fo0GetDisassemblyForProcessStartAddressAndNumberOfBytes",
12 | "fo0GetDisassemblyForProcessStartAddressAndNumberOfInstructions",
13 | "fo0GetInstructionForProcessAndAddress",
14 | "fo0GetInstructionForProcessAndBeforeAddress",
15 | ];
--------------------------------------------------------------------------------
/mDisassembler/cDisassembly.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertTypes;
2 |
3 | from .cInstruction import cInstruction;
4 |
5 | class cDisassembly(object):
6 | def __init__(oSelf, aoInstructions):
7 | fAssertTypes({
8 | "aoInstructions": (aoInstructions, [cInstruction]),
9 | });
10 | oSelf.__aoInstructions = aoInstructions;
11 |
12 | @property
13 | def uLength(oSelf):
14 | return len(oSelf.__aoInstructions);
15 |
16 | def foGetInstruction(oSelf, uIndex):
17 | fAssertTypes({
18 | "uIndex": (uIndex, int),
19 | });
20 | return oSelf.__aoInstructions[uIndex];
21 |
22 | def fo0GetInstructionAtAddress(oSelf, uAddress):
23 | for oInstruction in oSelf.__aoInstructions:
24 | if oInstruction.uAddress == uAddress:
25 | return oInstruction;
26 | return None;
27 |
28 | def __len__(oSelf):
29 | return len(oSelf.__aoInstructions);
30 |
31 | def __str__(oSelf):
32 | return "\r\n".join(
33 | str(oInstruction)
34 | for oInstruction in oSelf.__aoInstructions
35 | );
36 |
--------------------------------------------------------------------------------
/mDisassembler/cInstruction.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertType, fAssertTypes;
2 | from mWindowsAPI import fsHexNumber;
3 |
4 | class cInstruction(object):
5 | def __init__(oSelf, uAddress, sbBytes, tsbPrefixes, sbName, tsbArguments):
6 | fAssertTypes({
7 | "uAddress": (uAddress, int),
8 | "sbBytes": (sbBytes, bytes),
9 | "tsbPrefixes": (tsbPrefixes, tuple),
10 | "sbName": (sbName, bytes),
11 | "tsbArguments": (tsbArguments, tuple),
12 | });
13 | for uIndex in range(len(tsbPrefixes)):
14 | fAssertType(f"tsbPrefixes[{uIndex}]", tsbPrefixes[uIndex], bytes);
15 | for uIndex in range(len(tsbArguments)):
16 | fAssertType(f"tsbArguments[{uIndex}]", tsbArguments[uIndex], bytes);
17 | oSelf.__uAddress = uAddress;
18 | oSelf.__sbBytes = sbBytes;
19 | oSelf.__tsbPrefixes = tsbPrefixes;
20 | oSelf.__sbName = sbName;
21 | oSelf.__tsbArguments = tsbArguments;
22 |
23 | @property
24 | def uAddress(oSelf):
25 | return oSelf.__uAddress;
26 |
27 | @property
28 | def sbBytes(oSelf):
29 | return oSelf.__sbBytes;
30 | @property
31 | def sBytes(oSelf):
32 | return " ".join("%02X" % uByte for uByte in oSelf.__sbBytes);
33 | @property
34 | def uSize(oSelf):
35 | return len(oSelf.sbBytes);
36 |
37 | @property
38 | def tsbPrefixes(oSelf):
39 | return oSelf.__tsbPrefixes;
40 | @property
41 | def sPrefixes(oSelf):
42 | return str(b" ".join(oSelf.__tsbPrefixes), "ascii", "strict");
43 |
44 | @property
45 | def sbName(oSelf):
46 | return oSelf.__sbName;
47 | @property
48 | def sName(oSelf):
49 | return str(oSelf.__sbName, "ascii", "strict");
50 |
51 | @property
52 | def tsbArguments(oSelf):
53 | return oSelf.__tsbArguments; # Does not prevent overwriting them!
54 | @property
55 | def sArguments(oSelf):
56 | return str(b", ".join(oSelf.__tsbArguments), "ascii", "strict");
57 |
58 | @property
59 | def sInstruction(oSelf):
60 | return "%s%-7s %s" % (
61 | (oSelf.sPrefixes + " ") if oSelf.__tsbPrefixes else "",
62 | oSelf.sName,
63 | oSelf.sArguments
64 | );
65 |
66 | def __str__(oSelf):
67 | return "%-10s | %-20s | %s" % (
68 | fsHexNumber(oSelf.uAddress),
69 | oSelf.sBytes,
70 | oSelf.sInstruction,
71 | );
72 |
--------------------------------------------------------------------------------
/mDisassembler/fo0GetDisassemblyForProcessStartAddressAndNumberOfBytes.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertTypes;
2 |
3 | from mWindowsAPI import fsHexNumber;
4 | from .fo0GetDisassemblyForProcessAndCdbCommand import fo0GetDisassemblyForProcessAndCdbCommand;
5 |
6 | def fo0GetDisassemblyForProcessStartAddressAndNumberOfBytes(
7 | oProcess,
8 | uStartAddress,
9 | uNumberOfBytes,
10 | ):
11 | fAssertTypes({
12 | "uStartAddress": (uStartAddress, int),
13 | "uNumberOfBytes": (uNumberOfBytes, int),
14 | });
15 | assert 0 <= uNumberOfBytes < 0x1000, \
16 | "Request to disassemble %d bytes seems a little excessive!" % uNumberOfBytes;
17 | return fo0GetDisassemblyForProcessAndCdbCommand(
18 | oProcess,
19 | sbCommand = b"u 0x%X 0x%X" % (uStartAddress, uStartAddress + uNumberOfBytes),
20 | sbComment = b"Disassemble %d bytes at %s" % (uNumberOfBytes, bytes(fsHexNumber(uStartAddress), "ascii", "strict")),
21 | );
22 |
23 |
--------------------------------------------------------------------------------
/mDisassembler/fo0GetDisassemblyForProcessStartAddressAndNumberOfInstructions.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertTypes;
2 |
3 | from mWindowsAPI import fsHexNumber;
4 |
5 | from .fo0GetDisassemblyForProcessAndCdbCommand import fo0GetDisassemblyForProcessAndCdbCommand;
6 |
7 | def fo0GetDisassemblyForProcessStartAddressAndNumberOfInstructions(
8 | oProcess,
9 | uStartAddress,
10 | uNumberOfInstructions,
11 | ):
12 | fAssertTypes({
13 | "uStartAddress": (uStartAddress, int),
14 | "uNumberOfInstructions": (uNumberOfInstructions, int),
15 | });
16 | assert 0 <= uNumberOfInstructions < 0x100, \
17 | "Request to disassemble %d instructions seems a little excessive!" % uNumberOfInstructions;
18 | return fo0GetDisassemblyForProcessAndCdbCommand(
19 | oProcess,
20 | sbCommand = b"u 0x%X L%d" % (uStartAddress, uNumberOfInstructions),
21 | sbComment = b"Disassemble %d instructions at %s" % (uNumberOfInstructions, bytes(fsHexNumber(uStartAddress), "ascii", "strict")),
22 | );
23 |
24 |
--------------------------------------------------------------------------------
/mDisassembler/fo0GetInstructionForProcessAndAddress.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertTypes;
2 |
3 | from mWindowsAPI import fsHexNumber;
4 |
5 | from .fo0GetDisassemblyForProcessAndCdbCommand import fo0GetDisassemblyForProcessAndCdbCommand;
6 |
7 | def fo0GetInstructionForProcessAndAddress(
8 | oProcess,
9 | uAddress,
10 | ):
11 | fAssertTypes({
12 | "uAddress": (uAddress, int),
13 | });
14 | o0Disassembly = fo0GetDisassemblyForProcessAndCdbCommand(
15 | oProcess,
16 | sbCommand = b"u 0x%X L%d" % (uAddress, 1),
17 | sbComment = b"Disassemble instruction at %s" % (bytes(fsHexNumber(uAddress), "ascii", "strict"),),
18 | );
19 | return o0Disassembly.foGetInstruction(0) if o0Disassembly and len(o0Disassembly) == 1 else None;
20 |
21 |
--------------------------------------------------------------------------------
/mDisassembler/fo0GetInstructionForProcessAndBeforeAddress.py:
--------------------------------------------------------------------------------
1 | from mNotProvided import fAssertTypes;
2 |
3 | from mWindowsAPI import fsHexNumber;
4 |
5 | from .fo0GetDisassemblyForProcessAndCdbCommand import fo0GetDisassemblyForProcessAndCdbCommand;
6 |
7 | def fo0GetInstructionForProcessAndBeforeAddress(
8 | oProcess,
9 | uAddress,
10 | ):
11 | fAssertTypes({
12 | "uAddress": (uAddress, int),
13 | });
14 | # Disassemble the 32 bytes before the address; we're hoping that is enough to
15 | # "align" the disassembly by the time it gets to the instruction we want
16 | # but this is not guaranteed.
17 | o0Disassembly = fo0GetDisassemblyForProcessAndCdbCommand(
18 | oProcess,
19 | sbCommand = b"u 0x%X 0x%X" % (uAddress - 32, uAddress),
20 | sbComment = b"Disassemble instructions before %s" % (bytes(fsHexNumber(uAddress), "ascii", "strict"),),
21 | );
22 | if o0Disassembly is None or o0Disassembly.uLength == 0:
23 | return None;
24 | # Check if one of the instructions in the disassembly ends at the address.
25 | # It is not guaranteed that that was indeed the last executed instruction
26 | # but it is likely (sorry, no idea how likely).
27 | for uIndex in range(len(o0Disassembly)):
28 | oInstruction = o0Disassembly.foGetInstruction(uIndex);
29 | if oInstruction.uAddress + oInstruction.uSize == uAddress:
30 | return oInstruction;
31 | return None;
32 |
33 |
--------------------------------------------------------------------------------
/mExceptions.py:
--------------------------------------------------------------------------------
1 | class cNoAccessToProcessException(Exception):
2 | def __init__(oSelf, uProcessId: int):
3 | oSelf.uProcessId = uProcessId;
4 | Exception.__init__(oSelf, "The process with id %d/0x%X cannot be accessed." % (uProcessId, uProcessId));
5 |
--------------------------------------------------------------------------------
/mExports.py:
--------------------------------------------------------------------------------
1 | from .cBugId import cBugId;
2 |
3 | __all__ = [
4 | "cBugId",
5 | ];
--------------------------------------------------------------------------------
/mHeapManager/__init__.py:
--------------------------------------------------------------------------------
1 | from .cPageHeapManagerData import cPageHeapManagerData;
2 | from .cWindowsHeapManagerData import cWindowsHeapManagerData;
3 |
4 | __all__ = [
5 | "cPageHeapManagerData",
6 | "cWindowsHeapManagerData",
7 | ];
--------------------------------------------------------------------------------
/mHeapManager/cPageHeapManagerData/__init__.py:
--------------------------------------------------------------------------------
1 | from .cPageHeapManagerData import cPageHeapManagerData;
2 |
3 | __all__ = [
4 | "cPageHeapManagerData",
5 | ];
--------------------------------------------------------------------------------
/mHeapManager/cPageHeapManagerData/fo0GetAllocationHeaderForVirtualAllocationAndPointerSize.py:
--------------------------------------------------------------------------------
1 | from mWindowsAPI import fsHexNumber;
2 |
3 | from .mPageHeapStructuresAndStaticValues import (
4 | DPH_ALLOCATION_HEADER32,
5 | DPH_ALLOCATION_HEADER64,
6 | auValidPageHeapAllocationHeaderMarkers,
7 | );
8 |
9 | def fo0GetAllocationHeaderForVirtualAllocationAndPointerSize(oHeapBlockVirtualAllocation, uPointerSize, bDebugOutput):
10 | assert oHeapBlockVirtualAllocation.bAllocated, \
11 | "Please check oHeapBlockVirtualAllocation.bAllocated == True before making this call\r\n%s" % \
12 | str(oHeapBlockVirtualAllocation);
13 | # A page heap allocation for a heap block starts with a DPH_ALLOCATION_HEADER structure:
14 | DPH_ALLOCATION_HEADER = {4: DPH_ALLOCATION_HEADER32, 8: DPH_ALLOCATION_HEADER64}[uPointerSize];
15 | oAllocationHeader = oHeapBlockVirtualAllocation.foReadStructureForOffset(
16 | cStructure = DPH_ALLOCATION_HEADER,
17 | uOffset = 0,
18 | );
19 | if not oAllocationHeader.uMarker in auValidPageHeapAllocationHeaderMarkers:
20 | if bDebugOutput:
21 | print("cPageHeapManagerData: Allocation Header marker %s not valid in %s => None\r\n%s" % (
22 | fsHexNumber(oAllocationHeader.uMarker.fuGetValue()),
23 | oHeapBlockVirtualAllocation,
24 | "\r\n".join(oAllocationHeader.fasDump()),
25 | ));
26 | return None;
27 | # Maybe this should be enabled in a "strict" setting, as I would like to know what other values are common. But I've
28 | # missed bugs because this assertion terminated cBugId while reporting one, which is not good.
29 | # if hasattr(oAllocationHeader, "uPadding"):
30 | # assert oAllocationHeader.uPadding in auValidPageHeapAllocationHeaderPaddings, \
31 | # "Page heap allocation header padding has unhandled value 0x%X (expected %s):\r\n%s" % \
32 | # (oAllocationHeader.uPadding, " or ".join(["0x%X" % uValidMarker for uValidMarker in auValidPageHeapAllocationHeaderPaddings]),
33 | # "\r\n".join(oAllocationHeader.fasDump()));
34 | if bDebugOutput:
35 | print(("┌─ oAllocationHeader ").ljust(80, "─"));
36 | for sLine in oAllocationHeader.fasDump():
37 | print("│ %s" % sLine);
38 | print("└".ljust(80, "─"));
39 | return oAllocationHeader;
40 |
--------------------------------------------------------------------------------
/mHeapManager/cPageHeapManagerData/fo0GetPageHeapBlockForProcessAndAddress.py:
--------------------------------------------------------------------------------
1 | from mWindowsAPI import cVirtualAllocation, fsHexNumber;
2 |
3 | from .mPageHeapStructuresAndStaticValues import (
4 | DPH_HEAP_BLOCK32,
5 | DPH_HEAP_BLOCK64,
6 | );
7 |
8 | def fo0GetPageHeapBlockForProcessAndAddress(oProcess, uPageHeapBlockStartAddress, bDebugOutput = False):
9 | # DPH_HEAP_BLOCK structures are stored sequentially in a virtual allocation.
10 | oPageHeapBlockVirtualAllocation = cVirtualAllocation(
11 | uProcessId = oProcess.uId,
12 | uAddress = uPageHeapBlockStartAddress,
13 | );
14 | if not oPageHeapBlockVirtualAllocation.bAllocated:
15 | if bDebugOutput: print(
16 | "cPageHeapManagerData fo0GetPageHeapBlockForProcessAndAddress: "\
17 | "no memory allocated at page heap block address %s." % (
18 | fsHexNumber(uPageHeapBlockStartAddress),
19 | ));
20 | # The memory for this heap block has been freed: we cannot determine the
21 | # location for the DPH_ALLOCATION_HEADER structure, and thus cannot
22 | # provide any result.
23 | return None;
24 | # Try to read the page heap allocation information
25 | DPH_HEAP_BLOCK = {4: DPH_HEAP_BLOCK32, 8: DPH_HEAP_BLOCK64}[oProcess.uPointerSize];
26 | o0PageHeapBlock = oProcess.fo0ReadStructureForAddress(
27 | DPH_HEAP_BLOCK,
28 | uPageHeapBlockStartAddress,
29 | );
30 | if bDebugOutput:
31 | if o0PageHeapBlock:
32 | print(
33 | "cPageHeapManagerData fo0GetPageHeapBlockForProcessAndAddress: " \
34 | "page heap block:"
35 | );
36 | print(("┌─ DPH_HEAP_BLOCK ").ljust(80, "─"));
37 | for sLine in o0PageHeapBlock.fasDump():
38 | print("│ %s" % sLine);
39 | print("└".ljust(80, "─"));
40 | else:
41 | print(
42 | "cPageHeapManagerData fo0GetPageHeapBlockForProcessAndAddress: " \
43 | "page heap block vould not be read from address %s." % (
44 | fsHexNumber(uPageHeapBlockStartAddress),
45 | )
46 | );
47 | return o0PageHeapBlock;
48 |
--------------------------------------------------------------------------------
/mHeapManager/cWindowsHeapManagerData.py:
--------------------------------------------------------------------------------
1 | from .iHeapManagerData import iHeapManagerData;
2 |
3 | class cWindowsHeapManagerData(iHeapManagerData):
4 | def __init__(oSelf,
5 | oVirtualAllocation,
6 | uHeapEntryStartAddress,
7 | uHeapEntrySize,
8 | uHeapBlockStartAddress,
9 | uHeapBlockSize,
10 | bAllocated,
11 | ):
12 | oSelf.oVirtualAllocation = oVirtualAllocation;
13 |
14 | oSelf.uHeapEntryStartAddress = uHeapEntryStartAddress;
15 | oSelf.uHeapEntrySize = uHeapEntrySize;
16 | oSelf.uHeapEntryEndAddress = uHeapEntryStartAddress + uHeapEntrySize;
17 |
18 | oSelf.uHeapBlockStartAddress = uHeapBlockStartAddress;
19 | oSelf.uHeapBlockSize = uHeapBlockSize;
20 | oSelf.uHeapBlockEndAddress = uHeapBlockStartAddress + uHeapBlockSize;
21 |
22 | oSelf.bAllocated = bAllocated;
23 | oSelf.bFreed = not bAllocated;
24 |
25 | oSelf.bCorruptionDetected = False;
26 |
27 | if oSelf.uHeapEntrySize and oSelf.uHeapEntryEndAddress == uHeapBlockStartAddress:
28 | # The heap entry is right before the heap block; include both in the dump
29 | oSelf.uMemoryDumpStartAddress = uHeapEntryStartAddress;
30 | oSelf.uMemoryDumpEndAddress = oSelf.uHeapBlockEndAddress;
31 | else:
32 | oSelf.uMemoryDumpStartAddress = uHeapBlockStartAddress;
33 | oSelf.uMemoryDumpEndAddress = oSelf.uHeapBlockEndAddress;
34 | # Convenience
35 | oSelf.uMemoryDumpSize = oSelf.uMemoryDumpEndAddress - oSelf.uMemoryDumpStartAddress;
36 |
37 | def fatxGetMemoryRemarks(oSelf):
38 | return [tx for tx in [
39 | ("Allocation start", oSelf.oVirtualAllocation.uStartAddress, None),
40 | oSelf.uHeapBlockHeaderSize and
41 | ("Heap block header start", oSelf.uHeapBlockHeaderStartAddress, None),
42 | oSelf.uHeapBlockHeaderSize and
43 | ("Heap block header end", oSelf.uHeapBlockHeaderEndAddress, None),
44 | ("Heap block start", oSelf.uHeapBlockStartAddress, None),
45 | ("Heap block end", oSelf.uHeapBlockEndAddress, None),
46 | ("Allocation end", oSelf.oVirtualAllocation.uEndAddress, None),
47 | ] if tx];
--------------------------------------------------------------------------------
/mHeapManager/iHeapManagerData.py:
--------------------------------------------------------------------------------
1 | from ..ftsGetMemoryBlockSizeAndOffsetIdAndDescriptionForAddress import \
2 | ftsGetMemoryBlockSizeAndOffsetIdAndDescriptionForAddress;
3 |
4 | class iHeapManagerData(object):
5 | def __init__(oSelf,
6 | oVirtualAllocation,
7 | uHeapBlockStartAddress,
8 | uHeapBlockSize,
9 | bAllocated,
10 | ):
11 | oSelf.oVirtualAllocation = oVirtualAllocation;
12 |
13 | oSelf.uHeapBlockStartAddress = uHeapBlockStartAddress;
14 | oSelf.uHeapBlockSize = uHeapBlockSize;
15 | oSelf.uHeapBlockEndAddress = uHeapBlockStartAddress + uHeapBlockSize;
16 |
17 | oSelf.bAllocated = bAllocated;
18 | oSelf.bFreed = not bAllocated;
19 |
20 | oSelf.bCorruptionDetected = False;
21 |
22 | oSelf.uMemoryDumpStartAddress = uHeapBlockStartAddress - oSelf.uHeapBlockHeaderSize;
23 | oSelf.uMemoryDumpEndAddress = (
24 | oSelf.uAllocationEndPaddingEndAddress if oSelf.uAllocationEndPaddingSize
25 | else oSelf.uHeapBlockEndAddress
26 | );
27 | oSelf.uMemoryDumpSize = oSelf.uMemoryDumpEndAddress - oSelf.uMemoryDumpStartAddress;
28 |
29 | def ftsGetIdAndDescriptionForAddress(oSelf, uAddress):
30 | return ftsGetMemoryBlockSizeAndOffsetIdAndDescriptionForAddress(
31 | uBlockStartAddress = oSelf.uHeapBlockStartAddress,
32 | uBlockSize = oSelf.uHeapBlockSize,
33 | sBlockType = "%sheap" % ("freed " if oSelf.bFreed else "",),
34 | uAddress = uAddress,
35 | );
36 |
37 | def fatxGetMemoryRemarks(oSelf):
38 | return [tx for tx in [
39 | ("Allocation start", oSelf.oVirtualAllocation.uStartAddress, None),
40 | ("Heap block start", oSelf.uHeapBlockStartAddress, None),
41 | ("Heap block end", oSelf.uHeapBlockEndAddress, None),
42 | ("Allocation end", oSelf.oVirtualAllocation.uEndAddress, None),
43 | ] if tx];
44 |
--------------------------------------------------------------------------------
/mModule/__init__.py:
--------------------------------------------------------------------------------
1 | from .cModule import cModule;
2 |
3 | __all__ = [
4 | "cModule",
5 | ];
--------------------------------------------------------------------------------
/mProcess/__init__.py:
--------------------------------------------------------------------------------
1 | from .cProcess import cProcess;
2 |
3 | __all__ = [
4 | "cProcess",
5 | ];
--------------------------------------------------------------------------------
/mProcess/cProcess_fEnsurePageHeapIsEnabled.py:
--------------------------------------------------------------------------------
1 | import re;
2 |
3 | from mRegistry import cRegistryHiveKey;
4 |
5 | # Cache which binaries have page heap enabled/disabled. this assumes that the user does not modify the page heap
6 | # settings while BugId is running.
7 | gdbPageHeapEnabled_by_sBinaryName = {};
8 | guRequiredFlags = 0x02109870;
9 |
10 | def cProcess_fEnsurePageHeapIsEnabled(oProcess):
11 | if oProcess.bPageHeapEnabled is not None:
12 | return; # We have ensured this before.
13 | if oProcess.sBinaryName in gdbPageHeapEnabled_by_sBinaryName:
14 | oProcess.bPageHeapEnabled = gdbPageHeapEnabled_by_sBinaryName[oProcess.sBinaryName];
15 | return;
16 | oRegistryHiveKey = cRegistryHiveKey(
17 | sHiveName = "HKLM",
18 | sKeyPath = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\%s" % oProcess.sBinaryName,
19 | );
20 | o0GlobalFlags = oRegistryHiveKey.fo0GetValueForName("GlobalFlag");
21 | if o0GlobalFlags and o0GlobalFlags.sTypeName == "REG_SZ" and re.match("^0x[0-9a-fA-F]{8}$", o0GlobalFlags.xValue):
22 | uValue = int(o0GlobalFlags.xValue[2:], 16);
23 | if uValue & guRequiredFlags == guRequiredFlags:
24 | # Page heap is enabled with all the required options:
25 | gdbPageHeapEnabled_by_sBinaryName[oProcess.sBinaryName] = True;
26 | oProcess.bPageHeapEnabled = True;
27 | return;
28 | # Page heap is not enabled or not all the required options are enabled
29 | gdbPageHeapEnabled_by_sBinaryName[oProcess.sBinaryName] = False;
30 | oProcess.bPageHeapEnabled = False;
31 | # The "id" cdb uses to identify modules in symbols is normally based on the name of the module binary file.
32 | # However, for unknown reasons, cdb will sometimes use "imageXXXXXXXX", where XXXXXXXX is the hex address at
33 | # which the module is loaded (this has only been seen on x86 so far). In such cases, page heap appears to be
34 | # disabled; I believe whatever keeps cdb from determining the module binary's file name is also keeping page heap
35 | # from doing the same. In such cases, it appears that page heap cannot be enabled by the user, so we'll report it
36 | # with the second argument as "False" (not preventable).
37 | # NOTE: DISABLED TO AVOID ACCESSING oMainModule before the process is fully loaded and since `cModule.sbCdbId`
38 | # has been removed.
39 | bPreventable = True;#re.match(rb"image[0-9a-f]{8}", oProcess.oMainModule.sbCdbId, re.I) is None;
40 | # Report it
41 | if not oProcess.oCdbWrapper.fbFireCallbacks("Page heap not enabled", oProcess, bPreventable):
42 | # This is fatal if it's preventable and there is no callback handler
43 | assert not bPreventable, \
44 | "Full page heap is not enabled for %s in process 0x%X." % (oProcess.sBinaryName, oProcess.uId);
45 |
--------------------------------------------------------------------------------
/mProcess/cProcess_fLoadSymbols.py:
--------------------------------------------------------------------------------
1 | def cProcess_fLoadSymbols(oSelf):
2 | # Running this more than once would make no sense.
3 | if oSelf.oCdbWrapper.bDoNotLoadSymbols:
4 | return;
5 | if oSelf.bSymbolsLoaded:
6 | return;
7 | oSelf.fasbExecuteCdbCommand(
8 | sbCommand = b".symopt+ 0x80000000",
9 | sb0Comment = b"Enable symbol loading debug messages",
10 | );
11 | for oModule in oSelf.doModule_by_uStartAddress.values():
12 | oModule.fLoadSymbols();
13 | oSelf.fasbExecuteCdbCommand(
14 | sbCommand = b"lm a 0x%X" % oModule.uStartAddress,
15 | sb0Comment = b"Enable symbol loading debug messages",
16 | );
17 | oSelf.fasbExecuteCdbCommand(
18 | sbCommand = b".symopt- 0x80000000",
19 | sb0Comment = b"Disable symbol loading debug messages",
20 | );
21 | oSelf.bSymbolsLoaded = True;
22 |
--------------------------------------------------------------------------------
/mProcess/cProcess_fa0txGetRegistersForThreadId.py:
--------------------------------------------------------------------------------
1 | from .dttxRelevantRegisters_by_sISA import dttxRelevantRegisters_by_sISA;
2 | from ..mCP437 import fsCP437FromBytesString;
3 |
4 | def cProcess_fa0txGetRegistersForThreadId(oProcess, uThreadId):
5 | oWindowsAPIThread = oProcess.oWindowsAPIProcess.foGetThreadForId(uThreadId);
6 | d0uRegisterValue_by_sbName = oWindowsAPIThread.fd0uGetRegisterValueByName();
7 | if d0uRegisterValue_by_sbName is None:
8 | return None;
9 | duRegisterValue_by_sbName = d0uRegisterValue_by_sbName;
10 | atxRegisters = [];
11 | for (sbRegisterName, uBitSize, bFindDetails) in dttxRelevantRegisters_by_sISA[oProcess.sISA]:
12 | uRegisterValue = duRegisterValue_by_sbName[sbRegisterName];
13 | s0Details = None;
14 | if bFindDetails:
15 | s0Details = oProcess.fs0GetDetailsForAddress(uRegisterValue);
16 | atxRegisters.append((sbRegisterName, uRegisterValue, uBitSize, s0Details));
17 | return atxRegisters;
18 |
--------------------------------------------------------------------------------
/mProcess/cProcess_fasbGetStack.py:
--------------------------------------------------------------------------------
1 | import os, re;
2 |
3 | from ..dxConfig import dxConfig;
4 |
5 | def cProcess_fasbGetStack(oProcess, sbGetStackCommand):
6 | # Get the stack, which should make sure all relevant symbols are loaded or at least marked as requiring loading.
7 | # Noisy symbol loading is turned on during the command, so there will be symbol loading debug messages in between
8 | # the stack output, which makes the stack hard to parse: it is therefore discarded and the command is executed
9 | # again later (without noisy symbol loading) when symbols are loaded.
10 | # This only makes sense if we're using symbol servers, so we can download the symbols again if they fail.
11 | oProcess.fLoadSymbols();
12 | # Get the stack for real. At this point, no output from symbol loader is expected or handled.
13 | return oProcess.fasbExecuteCdbCommand(
14 | sbCommand = sbGetStackCommand,
15 | sb0Comment = b"Get stack",
16 | bOutputIsInformative = True,
17 | );
18 |
--------------------------------------------------------------------------------
/mProcess/cProcess_fo0GetFunctionForAddress.py:
--------------------------------------------------------------------------------
1 | def cProcess_fo0GetFunctionForAddress(oProcess, uAddress):
2 | sb0Symbol = oProcess.fsb0GetSymbolForAddress(uAddress, b"Get function symbol for address 0x%X" % uAddress);
3 | if sb0Symbol is None:
4 | return None;
5 | (
6 | u0Address,
7 | sb0UnloadedModuleFileName, o0Module, u0ModuleOffset,
8 | o0Function, i0OffsetFromStartOfFunction
9 | ) = oProcess.ftxSplitSymbolOrAddress(sb0Symbol);
10 | return o0Function;
--------------------------------------------------------------------------------
/mProcess/cProcess_fo0GetModuleForCdbId.py:
--------------------------------------------------------------------------------
1 |
2 | gbDebugOutput = False;
3 |
4 | def cProcess_fo0GetModuleForCdbId(oProcess, sbCdbId):
5 | # First check if we have cached this cdb id:
6 | for oModule in oProcess.doModule_by_uStartAddress.values():
7 | if oModule.fbIsCdbIdCached() and oModule.sbCdbId == sbCdbId:
8 | return oModule;
9 | # TODO remove this once issue 131 is fixed.
10 | # https://github.com/SkyLined/BugId/issues/131
11 | asbLoadedModulesInCdbForDebugging = oProcess.fasbExecuteCdbCommand(
12 | b"lm;",
13 | b"Get list of loaded modules for debugging"
14 | );
15 | asLoadedModulesByStartAddressForDebugging = [
16 | "%s: %s (%s)" % (
17 | oModule.uStartAddress,
18 | oModule.s0BinaryName or "