3

Many exploits nowadays can be prevented by control flow integrity (CFI). However, there are also data only exploits such as Heartbleed, read arbitrary data/keys which can be prevented by data flow intgerity (DFI).

I wonder how CFI and DFI are co-dependent.

  1. Does it make sense to have DFI and CFI?
  2. Does DFI imply CFI?
  3. Can I still use exploits that alter the control flow graph (CFG) if I have only DFI?
3

Does it make sense to have DFI and CFI?

No.

Does DFI imply CFI?

Yes, because hijacking the control flow means modifying a control-data and DFI ensures the integrity of data whether it is used for control or not.

Can I still use exploits that alter the control flow graph (CFG) if I have only DFI?

No, it will be detected.

DFI enforces a policy on the data-flow observed at runtime. It ensures that a program must follow a data-flow graph generated via a static analysis at compile time. An instrumentation pass on the program adds checks before each read instruction to ensure that they do not read a corrupted data.

The static analysis uses a reaching definition analysis. It is a data-flow analysis that gives us for each read instruction reading a variable, a set of instructions that could have last defined this variable.

For each read instruction the analysis is performed, and each write instruction that defines a variable is assigned an unique identifier.

Then, an instrumentation pass adds checks before each write instruction to update a table mapping an address being written to and the last identifier having written a value at that address.

In addition, the instrumentation adds checks before each read instruction. It fetches the identifier mapped with the address it is reading the value from, and it ensures that the identifier is in the set of reaching definitions found thanks to the static analysis.

For instance, if an attacker manages to corrupt the return address on the stack, the write instruction used to corrupt it updated the table with its identifier. Hence, the instrumentation just before the ret instruction will notice the corruption, because the last identifier used to modify the return address is not in the set of allowed identifiers.

That's why DFI prevents both non-control data attacks and control-data attacks. It also explains why it does not make sense to use both, because it would be redundant.

  • In your example of a return address corruption, would it also be detected if the write comes from an buffer overflow? The write would have started at a legal point but would move towards an illegal point. – user2600312 Jun 21 '16 at 8:07
  • With a buffer overflow, e.g., the attacker control a loop that write to some pointer with an offset that is increasing according to the loop (e.g. a memcpy). So in assembly, you will have something like mov eax, [ecx], or similar, in the body of the loop. Hence, each mov executed by the loop is for one write access to the address ecx, where ecx += 4 at the end of an iteration. But the mov in the body of the loop is instrumented to update the table according to the address it is writing to (i.e. ecx in our case). – Ronny Jun 21 '16 at 16:59

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.