Add COFF objects whose relocations and tables run past the file - #223
Add COFF objects whose relocations and tables run past the file#223zardus wants to merge 3 commits into
Conversation
cle's COFF backend takes a relocation's patch address as the section's PointerToRawData plus the relocation's VirtualAddress and never checks the result. These two objects give that check something to fail on. coff_reloc_outside_section.obj holds a .text of 0x10 bytes and a .data of 0x10 bytes, and puts .text's only relocation at offset 0x10, so its four-byte field starts on the first byte of .data. .data is filled with 0xaa, so a loader that resolves the relocation against the whole file leaves visibly rewritten bytes in a section no relocation names. coff_reloc_outside_file.obj puts its relocation at offset 0x4000000 of a 108-byte object, past the end of the file rather than merely past the section. No toolchain emits either shape, so both are assembled by build_coff_objects.py beside the other hand-built COFF objects, and its docstring names the new shape alongside the ones it already enumerates.
cle's COFF parser reads the section table, the symbol and string table and each section's relocation table at offsets and counts the file supplies, and bounds none of them. These three objects declare each of those tables larger than the file that holds it. coff_truncated_section_table.obj and coff_truncated_symbol_table.obj are the first 512 and 2048 bytes of the tracked x86/fauxware.obj, so they need no assembly at all. Its header declares 29 sections, whose table ends at 0x49c, and 152 symbols at 0x31c1 with the string table after them. 512 bytes cuts the section table; 2048 keeps the section table whole and cuts the symbol and string table, so each object isolates one read. coff_reloc_table_past_file.obj is assembled, because a well-formed 108-byte object whose .text points its relocation table at 0x4000000 is not something a toolchain emits. Everything else in it is in range, so the parser reaches the relocation table with nothing else to complain about first. The builder's docstring says which objects are cut from a tracked file rather than assembled.
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head
Caveat: this pull request has to merge before the consumer, or cle master will load fixtures that are not there yet. |
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Full output of a scan for the two shapes these fixtures supply, at this pull request's merge Before — nothing in the repository carries either shape, so neither bound cle is missing angr/binaries at the merge baseAfter — two objects carry a loose relocation and three declare a table the file does not with this change |
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
cle's COFF backend computes read and write addresses from fields in the object's own header and
checks none of them against the file, so a relocation can write outside its section and a
truncated object can leave the loader by an exception a caller cannot name. Nothing here tests
either. At this pull request's merge base, the 1068 files tracked under
tests/hold 5 COFFobjects with an I386 or AMD64 machine type, none with a relocation field outside its section or
the file, and none declaring a table the file does not hold.
Root cause
No toolchain emits these shapes, so the repository has never picked one up.
Fix
Five objects. Two carry a relocation whose four-byte field falls outside the section that owns
it,
tests/x86/coff_reloc_outside_section.objon the first byte of the next section andtests/x86/coff_reloc_outside_file.objpast the end of the file.Three declare a table larger than the file holding it, one per table the parser reads.
tests/x86/coff_truncated_section_table.objandtests/x86/coff_truncated_symbol_table.objneed no assembly at all: they are the first 512 and 2048 bytes of the tracked
tests/x86/fauxware.obj, whose header declares 29 sections in a table ending at0x49cand152 symbols at
0x31c1with the string table after them, so 512 cuts the section table and2048 keeps it whole and cuts the symbol and string table.
tests/x86/coff_reloc_table_past_file.objis assembled, because a well-formed 108-byte objectpointing its relocation table past the file is not something a toolchain produces.
All five come from
tests_src/coff/build_coff_objects.py, whose docstring says which are cutfrom a tracked file rather than assembled. Sizes, hashes and header fields are in the
validation record.
Testing
The same scan at this pull request's head finds 10 such COFF objects, 2 with a loose relocation
and 3 declaring a short table, and both runs are in the comment below. Rerunning the builder at
the head reproduces all eleven objects it owns byte for byte, so nothing already committed
moves.
The consumer is a cle pull request that bounds those offsets and adds five regressions that
load these objects; it references this pull request by number. This one has to merge first, or
those tests load fixtures that are not on master yet.
Validation: #223 (comment)
session: sharpen