Esistono molti tipi di CFI. Tuttavia, il CFI che supporta sia la protezione in avanti che quella in retromarcia, è deterministico, ed è anche a grana fine è molto raro che venga (l'unico esempio concreto che conosco è la versione commerciale di PaX RAP). La maggior parte dei CFI è a grana grossa, il che significa che una funzione può restituire non solo quella funzione, ma un certo numero di funzioni con la stessa firma di funzione (cioè, lo stesso tipo di ritorno e lo stesso identico argomenti). I bordi avanti provengono da salti e chiamate, mentre i bordi indietro provengono da ritorni. La grande maggioranza di CFI supporta solo l'uno o l'altro (come il CFG di Microsoft o il CFI di Clang), limitando enormemente le sue capacità.
Un altro problema con CFI è che spesso è probabilistico, utilizzando un valore segreto. Qualsiasi infoleaks che espone quel valore segreto potrebbe essere usato per rompere il CFI. Il CFI deterministico non ne soffre, ma la maggior parte dei CFI deterministici è molto grossolana. In breve:
-
La maggior parte del CFI non è sia in avanti che in retromarcia, limitando gravemente le sue capacità.
-
La maggior parte dei CFI è probabilistica, rendendola vulnerabile agli infoleaks che possono romperli.
-
La maggior parte del CFI è a grana grossa, permettendoti di tornare a gruppi di funzioni con la stessa firma.
Puoi imparare molto di più sulle implementazioni effettive di CFI verificando kCFI e PaX RAP, le uniche due che conosco che forniscono una protezione completa in avanti e indietro. Sfortunatamente, dal momento che CFI è un argomento così complesso e non esiste un'implementazione one o persino una tecnica per il CFI, non c'è modo di rispondere esattamente a come un hacker può aggirarlo senza specificare l'implementazione.