Maintained by: Lang Feng, Jeff Huang, Jiang Hu and Abhijith Reddy
Contact: flang@nju.edu.cn, jeffhuang@tamu.edu, jianghu@tamu.edu, abreddy@tamu.edu
This repository is the source code of FastCFI. Several parts are included in this repository. More details can be found in the following paper:
L. Feng, J. Huang, J. Hu and A. Reddy, "FastCFI: Real-Time Control Flow Integrity using FPGA without Code Instrumentation," International Conference on Runtime Verification, 2019.
A demo video can be found at: https://youtu.be/PIzojt2opvE
Please send your comments to flang@nju.edu.cn. We would highly appreciate your comments.
UPDATE 04/07/2021: Added the CFG optimization. The folders with "_opt_included" are the projects with CFG optimization enabled.
This is the program generating the Verilog file of CFG Checker.
For a program's executable file "prog", users need to use "objdump -d prog > objdump_prog" to convert it to assembly code. Then use the following command to extract information:
>> python cfitable.py extract objdump_prog
There will be two files: "out_funcs" and "raw". Users should not modify "out_funcs". For "raw", users may see similar lines as below:
branch: start 8378 source 8380 to ?? fix 1 ind 1 remark n
or
branch: start 83f6 source 83f6 to r3+++++++++++++++++++++ fix 1 ind 1 remark n
These are indirect branches which haven't been analyzed. Users can replace the "??" or "rx++++++++" with the target address of the branch instruction manually. The address of the branch instruction is specified after key word "source". The format of user specified target address is "[addr1]|[addr2]|...|[addrn]".
For example:
branch: start 8378 source 8380 to 84a0 fix 1 ind 1 remark n
or
branch: start 83f6 source 83f6 to 85e0|8670 fix 1 ind 1 remark n
NOTE: Users can skip specifying the target address, and enable "-auto_fixind" option in the next step to make the program finding the target address automatically.
After this, write a function file "funcs". "funcs" should contain the names of the functions that users want to verify. For example, if an user want to verify CFI of "func1" and "func2", the "funcs" file should be written as below:
\\\\\\\\\\\\
func1
func2
\\\\\\\\\\\\
Then use the following command to generate the CFG Checker Verilog code (The "funcs_sys" file is needed):
>> python cfitable.py gencase funcs
There are some options:
-r [address range begin] [address range end] : Will only monitor the codes in this specified address range.
-f [function index i1] [function index i2] : Will only monitor the codes from the i1-th function to the i2-th function in the "funcs" file.
-e : This means "exclude". Instead of monitoring the codes in the functions of the "funcs" file, our design will only monitor the functions that is not in the "funcs" file.
-a : Will monitor all the functions.
-nosys : Will exclude some functions generated by the compiler.
-random : Will randomly select functions in the "funcs" file to monitor.
-name [name] : The name of the generated file will be "CFI_kernel[name].v".
-split [num] : The number of the blocks in each submodule of CFG Checker will be [num]. (Not recommend to specify this option)
-auto_fixind : The target addresses of the indirect branches will be automatically calculated, if possible.
This is a Quartus project. Please use CFG Checker Generator to generate the "CFI_kernelxxx.v" file, add it into the Quartus project, and synthesis the project.
NOTE: Before synthesis, please modify the parameters below in the module "CFI_comb_verification" to the same values in the CFG Checker Verilog file:
parameter nodes=xxx;
parameter func_bits=xxx;
parameter block_bits=xxx;
After the bitstream is programmed to FPGA of DE1-SoC board, the program which is used to generate "CFI_kernelxxx.v" can be run on the Linux system of DE1-SoC board. If there is a CFI violation, "ERROR" will be displayed on the 8-segment LED.
This RIPE benchmark is modified based on:
https://github.com/johnwilander/RIPE
Wilander, J., Nikiforakis, N., Younan, Y., Kamkar, M., and Joosen, W. "RIPE: Runtime Intrusion Prevention Evaluator", Annual Computer Security Applications Conference (2011), 41-50.
The executable file is ./RIPE_ARM/build/ripe_attack_generator
The use of the modified benchmark is the same as the original benchmark which can be found in the link above.
We add another feature to the original benchmark: Users can run the benchmark without any attacks by using the following command:
>> ./ripe_attack_generator -t direct -i returnintolibc -c structfuncptrdata -l data -f noattack > /tmp/ripe_log 2>&1
NOTE: We haven't recovered the full functions of the attacks, which means when some attacks are applied, the program will crash. However, for the attacks listed in our paper, at least the first step of each attack will happen, which means the attacks can change the program's execution to a wrong place. This is enough for checking CFI.