angr / angr/cle

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

Aperta
#746 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Python
Stelle
485
Fork
135
Merge medio
2g 2h
PR unite (30g)
15

Descrizione

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.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.