angr / angr/cle

COFF undefined externals never reach self.imports, so angr never hooks them

Offen
#746 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
Python
Sterne
485
Forks
135
Ø Merge
2 T. 2 Std.
Gemergte PRs (30 T.)
15

Beschreibung

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

`Coff._add_relocs` resolves a relocation against an undefined external symbol by
allocating it an extern address:

```python
cle_symbol = self.get_symbol(sym_name, produce_extern_symbols=True)
self.relocs.append(reloc_class(self, cle_symbol, patch_offset))
```

but nothing is ever added to `self.imports`; the loader body ends with

```python
# FIXME: Expose __imp_* symbols through self.imports
```

`angr.Project._register_object` iterates `obj.imports` and nothing else, so for
a COFF object it iterates an empty dictionary and hooks nothing. The extern
addresses stay raw zero fill, and a call to an undefined external is decoded as
instructions.

```c
extern int one(int);
extern int two(int);
int entry(int x) { return one(x) + two(x); }
```

```
x86_64-w64-mingw32-gcc -c -o coff2.o coff2.c
```

```python
p = angr.Project("coff2.o", auto_load_libs=False, main_opts={"backend": "COFF"})
print(p.loader.main_object.imports) # {}
for s in p.loader.extern_object.symbols:
print(hex(s.rebased_addr), s.name, p.is_hooked(s.rebased_addr))
```

```
{}
0x500000 one False
0x500008 two False
```

`CFGFast()` then produces a function `one` at 0x500000 whose single block is the
eight zero bytes of the extern slot, reached by `call 0x500000` at 0x400117.
The same happens under symbolic execution: calling the import executes zero fill
instead of a `ReturnUnconstrained` stub.

For contrast, a relocatable ELF populates `imports`, so `_register_object` sees
the same undefined externals and hooks them: the equivalent object built with
`gcc -c` gets a `ReturnUnconstrained` at each extern address and CFGFast decodes
nothing there.

In a block-level sweep of a large mixed corpus this accounts for 17 x86 and
x86_64 COFF objects placing CFG blocks in loader-invented memory. Real objects
show it as clearly as the reduced case: on
sha256 `69ba352d244c317e01aa7ca99d5391e0785f8198f46691039482607b7032cea7`
(`main_opts={"backend": "COFF"}`) the extern object holds `malloc`,
`FcSerializeAlloc` and `FcSerializePtr` at 0x500000, 0x500008 and 0x500010, none
of them hooked, and CFGFast makes a function of each. On
sha256 `df12b231e916f618c8ceab0e2b2a6832bd0f9c34602b81cf48e20372e888a740` there
are 84 of them.

This is a report rather than a pull request because filling in `imports` changes
what every COFF analysis does — every undefined external becomes a
`ReturnUnconstrained` stub rather than decodable memory — and because the FIXME
names `__imp_*` specifically, which suggests a maintainer already has a view on
whether the indirection should be represented and how.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.