The goal of this transformation is to disrupt static analysis tools that
make use of inter-procedural alias analysis. The current implementation
is simplistic: we simply replace all direct function calls with indirect
ones.
A call to x = foo(n) turns into
void *arr[] = {..., & foo, ... }; int main () { int x = ((int (*)(int n ))arr[expr=42])(n); }where arr is a global array containing function addresses, and expr=42 is an opaque expression computing the index of foo's address in arr.
To make analysis a bit harder, we can also insert bogus elements in arr, and insert updates to these bogus elements. Here, both arr[6] and arr[7] are bogus:
int main () { int x; arr[expr=6] = arr[expr=42]; arr[expr=7] = &x; }
Options
Option | Arguments | Description |
---|---|---|
--Transform | AntiAliasAnalysis | Transform the code by replacing direct function calls with indirect ones, making alias analysis become less precise. |
--AntiAliasAnalysisObfuscateIndex | BOOLSPEC | Use opaque expressions to compute function addresses. Default=true. |
--AntiAliasAnalysisBogusEntries | BOOLSPEC | Add bogus function addresses, and bogus updates to them. Default=true. |
Issues
It is best to perform this transformation at the end of the transformation sequence, when all functions (including new ones generated by the virtualize, split, and merge transformations) are known. The reason is that, by definition, this transformation makes alias analysis difficult, which trips up subsequent transformations. This is particularly true for the EncodeData transformation which relies on alias analysis. The --AntiAliasAnalysisBogusEntries=true option seems to be particularly troublesome.