You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Minidump.__init__ builds its regions from the two base classes in cle/backends/region.py directly: one Segment per dumped memory range (cle/backends/minidump/__init__.py:62) and one Section per loaded module (:72).
Neither base class can describe permissions. Section.is_readable, .is_writable, .is_executable and .only_contains_uninitialized_data all raise NotImplementedError(), and Segment inherits Region, which answers True to all three unconditionally — the same defect reported in #743.
The dump loads fine. Anything that then asks where code lives does not, because CFGBase._executable_memory_regions prefers sections when an object has them and reads section.is_executable (angr/analyses/cfg/cfg_base.py:870). The fixture already in angr/binaries is enough:
importangr, cleld=cle.Loader("binaries/tests/x86/windows/jusched_x86.dmp", auto_load_libs=False)
ld.main_object.sections[0].is_executable# NotImplementedErrorld.main_object.segments[0].is_executable# True, for every one of the 173 segmentsangr.Project("binaries/tests/x86/windows/jusched_x86.dmp", auto_load_libs=False).analyses.CFGFast()
# NotImplementedError, from cle/backends/region.py:190, before CFGFast does any work
So CFGFast cannot run on any minidump that has at least one loaded module. In a sweep of a large object corpus, 1,879 of 1,969 minidump observations end this way; the other 90 fail earlier for unrelated reasons. All 1,859 distinct dumps behind those observations reproduce it on current master.
Fixing this is not a matter of picking a subclass, because the dump does not always carry the answer.
The permission stream is optional.MINIDUMP_MEMORY_INFO_LIST holds a real PAGE_* value per range, but MiniDumpWriteDump writes it only when passed MiniDumpWithFullMemoryInfo. jusched_x86.dmp has it (251 entries: 85 PAGE_READONLY, 55 PAGE_READWRITE, 52 PAGE_NOACCESS, 33 PAGE_EXECUTE_READ), so a fix tested against the fixture alone will look complete. Of the 1,859 dumps above, 1,857 have no such stream. That number needs a caveat: 1,856 of them come from one generating harness, so it measures that harness more than it measures the world. The corpus holds only three dumps captured from real crashes, and one of those three also has no MemoryInfoListStream, which is enough to say the absent case is not hypothetical.
A Section here is a whole loaded module — a mapped PE image with r-x text beside r-- and rw- data. One permission triple cannot describe it honestly whichever value it takes.
The Segments are the regions that could carry per-range permissions, and they are the ones currently claiming rwx. Making the sections answer without touching the segments leaves that in place; removing the sections so the segments are consulted turns every dumped heap, stack and guard page into executable memory, which is #743 in a second backend.
Options, none of which is obviously the intended one:
Give Segment real permissions from MemoryInfoListStream and drop the per-module Sections, accepting that dumps without that stream have no executable map at all. CFGFast then recovers nothing from them rather than crashing, which is quieter but not better.
Keep the per-module Sections and read each module's own section table out of the dumped image. The module headers are mapped: MZ is present at module.baseaddress for every module of every dump checked, including the ones with no MemoryInfoListStream. This gives per-section permissions from the module itself rather than from the optional stream, at the cost of parsing a child PE per module.
#682 is open against this and takes option 1. As written it does not survive a dump with no MemoryInfoListStream: DumpSection is then constructed with protect = 0, and is_readable evaluates self.protect.value, so NotImplementedError becomes AttributeError: 'int' object has no attribute 'value'. Loading all 1,859 dumps on that branch and querying the permissions of every section, 1,857 raise AttributeError and the 2 with the stream answer. It also splits each module into one section per overlapping segment, taking the fixture from 30 sections to 127 and breaking tests/test_minidump.py, which is the objection already raised on it.
The TE and UEFI backends had the same crash from the same base class and were fixed in #713 by giving TESection permissions from the PE/COFF section characteristics. That worked because a TE image carries per-section permissions. A minidump often does not, which is why this one is a report rather than the same patch again.
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Minidump.__init__builds its regions from the two base classes incle/backends/region.pydirectly: oneSegmentper dumped memory range (cle/backends/minidump/__init__.py:62) and oneSectionper loaded module (:72).Neither base class can describe permissions.
Section.is_readable,.is_writable,.is_executableand.only_contains_uninitialized_dataallraise NotImplementedError(), andSegmentinheritsRegion, which answersTrueto all three unconditionally — the same defect reported in #743.The dump loads fine. Anything that then asks where code lives does not, because
CFGBase._executable_memory_regionspreferssectionswhen an object has them and readssection.is_executable(angr/analyses/cfg/cfg_base.py:870). The fixture already inangr/binariesis enough:So CFGFast cannot run on any minidump that has at least one loaded module. In a sweep of a large object corpus, 1,879 of 1,969 minidump observations end this way; the other 90 fail earlier for unrelated reasons. All 1,859 distinct dumps behind those observations reproduce it on current master.
Fixing this is not a matter of picking a subclass, because the dump does not always carry the answer.
The permission stream is optional.
MINIDUMP_MEMORY_INFO_LISTholds a realPAGE_*value per range, butMiniDumpWriteDumpwrites it only when passedMiniDumpWithFullMemoryInfo.jusched_x86.dmphas it (251 entries: 85PAGE_READONLY, 55PAGE_READWRITE, 52PAGE_NOACCESS, 33PAGE_EXECUTE_READ), so a fix tested against the fixture alone will look complete. Of the 1,859 dumps above, 1,857 have no such stream. That number needs a caveat: 1,856 of them come from one generating harness, so it measures that harness more than it measures the world. The corpus holds only three dumps captured from real crashes, and one of those three also has noMemoryInfoListStream, which is enough to say the absent case is not hypothetical.A
Sectionhere is a whole loaded module — a mapped PE image withr-xtext besider--andrw-data. One permission triple cannot describe it honestly whichever value it takes.The
Segments are the regions that could carry per-range permissions, and they are the ones currently claimingrwx. Making the sections answer without touching the segments leaves that in place; removing the sections so the segments are consulted turns every dumped heap, stack and guard page into executable memory, which is #743 in a second backend.Options, none of which is obviously the intended one:
Segmentreal permissions fromMemoryInfoListStreamand drop the per-moduleSections, accepting that dumps without that stream have no executable map at all. CFGFast then recovers nothing from them rather than crashing, which is quieter but not better.Sections and read each module's own section table out of the dumped image. The module headers are mapped:MZis present atmodule.baseaddressfor every module of every dump checked, including the ones with noMemoryInfoListStream. This gives per-section permissions from the module itself rather than from the optional stream, at the cost of parsing a child PE per module.Sectionreport that it does not know, and haveCFGBase._executable_memory_regionsfall back to the segments in that case. This needs the "unknown" state that ELFCore drops the permissions of every core segment it turns into a Blob #743 also asks for.#682 is open against this and takes option 1. As written it does not survive a dump with no
MemoryInfoListStream:DumpSectionis then constructed withprotect = 0, andis_readableevaluatesself.protect.value, soNotImplementedErrorbecomesAttributeError: 'int' object has no attribute 'value'. Loading all 1,859 dumps on that branch and querying the permissions of every section, 1,857 raiseAttributeErrorand the 2 with the stream answer. It also splits each module into one section per overlapping segment, taking the fixture from 30 sections to 127 and breakingtests/test_minidump.py, which is the objection already raised on it.The TE and UEFI backends had the same crash from the same base class and were fixed in #713 by giving
TESectionpermissions from the PE/COFF section characteristics. That worked because a TE image carries per-section permissions. A minidump often does not, which is why this one is a report rather than the same patch again.