User's Guide

Building Vulncheck

Download and verify vulncheck-0.1.tar.gz:

$ wget http://gcc.vulncheck.org/download/vulncheck-0.1.tar.gz
$ wget http://gcc.vulncheck.org/download/vulncheck-0.1.tar.gz.sig
$ gpg --recv-keys --keyserver pgp.mit.edu 0x09E74104
$ gpg --verify vulncheck-0.1.tar.gz.sig

Unpack the vulncheck source code:

$ tar xfvz vulncheck-0.1.tar.gz
$ cd vulncheck-0.1

Vulncheck is distributed as a patch for the GCC 4.2.1 compiler. To build it, you need to download gcc-4.2.1.tar.bz2 from the GNU ftp site or one of its mirrors.

$ wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.2.1/gcc-4.2.1.tar.bz2

It is recommended that you verify the SHA1 checksum of the downloaded file. It should match the checksum below:

$ sha1sum gcc-4.2.1.tar.bz2
b8a55b13c4e38fae78d5db9a456e2d4ffe003118  gcc-4.2.1.tar.bz2

Extract the source code and apply the Vulncheck patch:

$ tar xfj gcc-4.2.1.tar.bz2
$ cd gcc-4.2.1
$ patch -p 1 < ../gcc-4.2.1.diff
$ cd ..

Configure and build the compiler. This example assumes that you want to install the compiler in /usr/local/vulncheck. If you wish to use a different directory, specify it with the --prefix option of the configure script. On 64-bit Linux systems you might need to add the --disable-multilib option.

$ mkdir gcc-obj
$ cd gcc-obj
$ ../gcc-4.2.1/configure --prefix=/usr/local/vulncheck --enable-languages=c,c++
$ make

Go and get a cup of tea, this will take a while. On my 2.8GHz Xeon box it takes about an hour. Once the build is finished, install the compiler into the target directory. You might need root privileges if you are installing into /usr/local/vulncheck.

$ sudo make install
$ cd ..

The final step of the installation is to copy the vulncheck.data file to the /usr/local/vulncheck directory. This file contains the function signatures for tainting and vulnerable functions.

$ cp -a vulncheck.data /usr/local/vulncheck/

To test Vulncheck, go into the test directory and run the make command, specifying the directory where you installed the compiler in the PREFIX variable.

$ cd test
$ make PREFIX=/usr/local/vulncheck

Vulncheck will detect vulnerabilities in vuln1.c, vuln2.c, vuln3.c and vuln5.c, and will issue the following warnings:

vuln1.c:12: warning: vulnerable call to memcpy
vuln2.c:14: warning: vulnerable call to memcpy
vuln3.c:10: warning: vulnerable call to printf
vuln5.c:16: warning: vulnerable call to memcpy

Using Vulncheck

To use Vulncheck, compile your program with /usr/local/vulncheck/bin/gcc and pass it the -fvulncheck option. By default, the Vulncheck compiler will read the function signatures from /usr/local/vulncheck/vulncheck.data. If you used a different installation directory or want to use a custom signature file, specify it with the -fvulncheck-data option.

The Vulncheck analysis uses the SSA form of the program, which is built only when optimization is enabled with -O1 or higher. If you're compiling with -O0, the Vulncheck pass will not run.

This is a sample command line for compiling a single source file:

/usr/local/vulncheck/bin/gcc -O2 -fvulncheck -fvulncheck-data=/usr/local/vulncheck/vulncheck.data vuln1.c

If you compiling a program with a standard autoconf build system, run the following:

./configure
make CC=/usr/local/vulncheck CFLAGS="-O2 -fvulncheck" | tee vulncheck.log
grep "warning: vulnerable call" vulncheck.log

The output from the Vulncheck analysis is in the form of standard warnings. If you need to get detailed information about what the Vulncheck analysis, use the -fdump-tree-vulncheck-details-vops option. It will create a .c.040t.vulncheck file with debugging output from the analysis. Making sense of the debugging output requires a good understanding of the Vulncheck implementation, but it's better than nothing.

Custom signatures

The vulncheck.data file in /usr/local/vulncheck contains function prototypes with annotations specifying the properties of the function. There are three types of annotations:

The following example shows the use of all four types of annotations:

__USER_DATA__ int fgetc (FILE *stream);
char * fgets (char *s __USER_DATA__, int count, FILE *stream);
int printf (const char *template __VULN_USER__, ...);
void * memcpy (void *restrict to, const void *restrict from, size_t size __VULN_RANGE__);
__VULN_FUNC__ char * gets (char *s __USER_DATA__);

Most large programs use custom wrappers around the system functions. In this case Vulncheck will not be able to identify any vulnerabilities, because of its inability to propagate taint information and value ranges across functions. To deal with this limitation, it is necessary to build a custom signature library.

The custom annotations can be added to the vulncheck.data file in /usr/local/vulncheck, or a custom file can be specified with the -fvulncheck-data option.

/usr/local/vulncheck/bin/gcc -fvulncheck -fvulncheck-data=custom.data vuln.c