Virtual Machine (VM)
The VM is what runs the guest OS. Its purpose is to emulate a physical machine.
Host Operating System (host OS)
The host OS is the primary OS where CRETE will be built, installed and executed from.
Guest Operating System (guest OS)
The guest OS is the OS that runs on the virtual machine.
A modest familiarity with Unix-style systems is required. You must be able to make your way around the system in a terminal and interact with files from command line.
CRETE requires the use of Ubuntu 12.04-amd64 or Ubuntu 14.04-amd64 for the host OS. While various guest OS should work, only Ubuntu-12.04.5-server-i386, Ubuntu-12.04.5-server-amd64, Ubuntu-14.04.5-server-amd64, and Debian-7.11.0-i386 have been tested.
The following apt-get packages are required:
sudo apt-get update
sudo apt-get install build-essential libcap-dev flex bison cmake libelf-dev git libtool libpixman-1-dev minisat zlib1g-dev libglib2.0-dev
LLVM 3.4 is also required to build CRETE, and the LLVM packages provided by LLVM itself is recommended. Please check LLVM Package Repository for details. For the recent Ubuntu (≥ 12.04 and ≤ 15.10, e.g. 14.04 LTS) or Debian, please use the following instructions to install LLVM 3.4:
echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.4 main" | sudo tee -a /etc/apt/sources.list
echo "deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.4 main" | sudo tee -a /etc/apt/sources.list
wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
sudo apt-get update
sudo apt-get install clang-3.4 llvm-3.4 llvm-3.4-dev llvm-3.4-tools
CRETE uses Boost 1.59.0. If any other version of Boost is installed on the system, there may be conflicts. It is recommended that you remove any conflicting Boost versions.
CRETE requires a C++11 compatible compiler. We recommend clang++-3.4 or g++-4.9 or higher versions of these compilers.
Grab a copy of the source tree:
git clone --recursive https://github.com/SVL-PSU/crete-dev.git crete
From outside of CRETE's top-level directory:
mkdir crete-build
cd crete-build
CXX=clang++-3.4 cmake ../crete
make # use -j to speedup
As documented on the STP and KLEE website, it is essential to setup the limit on open files and stack size. In most cases, the hard limit will have to be increased first, so it is best to directly edit the /etc/security/limits.conf file. For example, add the following lines to limits.config.
* soft stack unlimited
* hard stack unlimited
* soft nofile 65000
* hard nofile 65000
If you like, you can add the executables and libraries to your .bashrc file:
echo '# Added by CRETE' >> ~/.bashrc
echo export PATH='$PATH':`readlink -f ./bin` >> ~/.bashrc
echo export LD_LIBRARY_PATH='$LD_LIBRARY_PATH':`readlink -f ./bin` >> ~/.bashrc
echo export LD_LIBRARY_PATH='$LD_LIBRARY_PATH':`readlink -f ./bin/boost` >> ~/.bashrc
source ~/.bashrc
At this point, you're all set!
You may skip this section by using a prepared VM image crete-demo.img. This image has Ubuntu-14.04.5-server-amd64 installed as the Guest OS along with all CRETE guest utilities.
Root username: test
Password: crete
The front-end of CRETE is an instrumented VM (crete-qemu). You need to setup a QEMU-compatible VM image to performa a certain test upon CRETE. To get best performance, native qemu with kvm enabled is recommended for all setups on the guest VM image.
$ qemu-img create -f qcow2 <img-name>.img <img-size>G
Where <img-name> is the desired name of your image, and <img-size> is the upper bound of how large the image can grow to in Gigabytes. See this page for more details.
$ crete-native-qemu-system-x86_64 -hda <img-name>.img -m <memory> -k en-us -enable-kvm -cdrom <iso-name>.iso -boot d
Where <memory> is the amount of RAM (Megabytes), <img-name> is the name of the image, and <iso-name> is the name of the .iso. The iso of ubuntu-12.04.5-server-amd64, for example, can be downloaded here. From this point, follow the installation procedure to install the OS to the image.
See this page for more boot options.
Once the OS is installed to the image, it can be booted with:
$ crete-native-qemu-system-x86_64 -hda <img-name>.img -m <memory> -k en-us -enable-kvm
Where <memory> is the amount of RAM (megabytes), <img-name> is the name of the image.
If Booting Ubuntu 12.04 hangs, first boot to recovery mode, then resume to normal boot. This is likely caused by driver display problems in Ubuntu.
Install the following dependencies on the guest OS at first:
$ sudo apt-get update
$ sudo apt-get install build-essential cmake libelf-dev libcap2-bin -y
Compile CRETE utilties on the guest OS:
$ scp -r <host-user-name>@10.0.2.2:</path/to/crete/guest> .
$ mkdir guest-build
$ cd guest-build
$ cmake ../guest
$ make
Address Space Layout Randomization (ASLR) must be disabled on account of the need for program addresses to remain consistent across executions/iterations. To disable ASLR (Ubuntu 12.04):
echo "" | sudo tee --append /etc/sysctl.conf
echo '# Added by CRETE' | sudo tee --append /etc/sysctl.conf
echo '# Disabling ASLR:' | sudo tee --append /etc/sysctl.conf
echo 'kernel.randomize_va_space = 0' | sudo tee --append /etc/sysctl.conf
Set the following enviroment variables for using crete guest utilities (the following script works on ubuntu 12.04 and assumes the "guest-build" locates at the home folder):
echo "" >> ~/.bashrc
echo '# Added by CRETE' >> ~/.bashrc
echo 'export PATH=$PATH:~/guest-build/bin' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/guest-build/bin' >> ~/.bashrc
echo 'export C_INCLUDE_PATH=$C_INCLUDE_PATH:~/guest/lib/include' >> ~/.bashrc
echo 'export LIBRARY_PATH=$LIBRARY_PATH:~/guest-build/bin' >> ~/.bashrc
echo 'export LD_BIND_NOW=1' | sudo tee --append /etc/sysctl.conf
Now, the guest OS is all set for using CRETE.
When QEMU is running, it provides a monitor console for interacting with QEMU. The monitor can be accessed from within QEMU by using the hotkey combinations ctrl+alt+2, while ctrl+alt+1 allows you to switch back to the Guest OS. One of the most useful functionality of the monitor is saving and loading shopshots.
Swith to monitor by pressing ctrl+alt+2 and use command:
$ savevm <snapshot-name>Where <snapshot-name> is the name you want to identify the snapshot by.
To load a snapshot while launching QEMU from the host OS:
$ crete-native-qemu-system-x86_64 -hda <img-name>.img -m <memory> -k en-us -loadvm <snapshot-name>Note that the boot command of QEMU that loads a snopshot has to stay consistant with the boot command of QEMU while saving snopshot, such as using the same on the same image. Also, saving and loading snapshots cannot be done across non-kvm and kvm modes.
The simplest way to transfer files to and from the guest OS is with the scp command.
The host OS has a special address in the guest OS: 10.0.2.2
Here's an example that copies a file from the host to the guest:
scp <host-user-name>@10.0.2.2:<path-to-source-file> <path-to-destination-file>When working with snapshots, it's often easiest to save a snapshot and close the VM from the monitor console rather than resorting to killing it or shutting it down. To gracefully close the VM:
ctrl+alt+2 q <enter>
Where <enter> means depress the Enter key on your keyboard.
Try to aviod running more than one VM instance on a given image at a time, as it may cause image corruption.
This section will show how to use CRETE to generate test cases for unmodified Linux binaries. In this section, I will use "crete-demo.img" as the VM image prepared for CRETE. Also, I will use echo from GNU CoreUtils as the target binary under test.
Boot the VM image using native qemu without kvm-enabled first by:
$ crete-native-qemu-system-x86_64 -hda crete-demo.img -m 256 -k en-us
A sample configuration file, crete.demo.echo.xml, for echo is given as follows :
<crete>
<exec>/bin/echo</exec>
<args>
<arg index="1" size="8" value="abc" concolic="true"/>
</args>
</crete>
A briefly explaination for each pertinent node is as follows (See 5. CRETE Configuration Optionts for more information):
<exec>/bin/echo</exec>
This is the path to the executable under test.
<arg index="1" size="8" value="abc" concolic="true"/>
In this way, we will test the binary with one concolic argument with size of 8 bytes and its initial value is "abc".
With the configuration file, we are ready to use crete-qemu to start the test on the target binary.
We take advantage of the snapshot functionality of qemu to boost the process of booting the guest OS by using crete-qemu. We first save a snapshot and quit from the native qemu by:
ctrl+alt+2
$ savevm test
enter
$ q
enter
From the host OS, luanch crete-qeum by loading the snapshot we just saved:
$ crete-qemu-2.3-system-x86_64 -hda crete-demo.img -m 256 -k en-us -loadvm test
On the guest OS, execute CRETE guest utility with the guest configuration file:
$ crete-run -c crete.demo.echo.xml
Now, the guest OS is all set and should be waiting for CRETE back-end on the Host OS to start.
CRETE back-end has three parts: crete-vm-node, for managing VM instances, crete-svm-node, for managing symbolic VM instances, and crete-dispatch, for coordinating the whole process.
A sample configuration file, crete.dispatch.xml, for crete-dispatch is:
<crete>
<mode>developer</mode>
<vm>
<arch>x64</arch>
</vm>
<svm>
<args>
<symbolic>
--max-memory=1000
--disable-inlining
--use-forked-solver
--max-sym-array-size=4096
--max-instruction-time=5
--max-time=150
--randomize-fork=false
--search=dfs
</symbolic>
</args>
</svm>
<test>
<interval>
<trace>10000</trace>
<tc>10000</tc>
<time>900</time>
</interval>
</test>
<profile>
<interval>10</interval>
</profile>
</crete>
Start crete-dispatch with the sample configuration file:
$ crete-dispatch -c crete.dispatch.xml
A sample configuration file, crete.vm-node.xml, for crete-vm-node is:
<crete>
<vm>
<count>1</count>
</vm>
<master>
<ip>localhost</ip>
<port>10012</port>
</master>
</crete>
Start crete-vm-node with the sample configuration file (crete_vm_node must be started from the same folder where the crete-qemu was started):
$ crete-vm-node -c crete.vm-node.xml
A sample configuration file, crete.svm-node.xml, for crete-svm-node is:
<crete>
<svm>
<count>1</count>
</svm>
<master>
<ip>localhost</ip>
<port>10012</port>
</master>
</crete>
Start crete-svm-node with the sample configuration file:
$ crete-svm-node -c crete.svm-node.xml
TBA
Configuration is done within the guest OS via an XML file that is passed as an argument to crete-run.
Example:
crete-run -c crete.xml
The configuration file (crete.xml) may be arbitrarily named, but the contents must match the following structure (order does not matter).
<crete>
<exec>string</exec>
<args>
<arg index="<uint>" size="<uint>" value="<string>" concolic="<bool>"/>
</args>
<files>
<file path="<string>" size="<uint>" concolic="<bool>"/>
</files>
<stdin size="<uint>" value="<string>" concolic="<bool>"/>
</crete>
Item-by-item:
<exec>string</exec>
- Type: string.
- Description: the full path to the executable to be tested.
- Optional: no.
<args></args>
Command line arguments to the executable are defined here.
There is a single default argument for index="0", as defined by the system (typically a path to the executable). By listing an arg element for index="0", you will overwrite this default argument.
<args>
<arg index="<uint>" size="<uint>" value="<string>" concolic="<bool>"/>
</args>
index:
- Type: unsigned int.
- Description: index of argv[] that this element will apply to.
- Optional: no.
size:
- Type: unsigned int.
- Description: number of bytes of the argument not including the null terminator.
- Optional: yes, if value is given (from which size can be derived).
value:
- Type: string.
- Description: the initial value of the argument (if concolic), or the constant value of the argument (if not concolicp).
- Optional: yes, if size is given.
concolic:
- Type: boolean
- Description: designate this argument to have test values generated for it.
- Optional: yes - defaults to false.
TBA
TBA
TBA
The most likely cause of this is the VM Image is corrupted.
There is no way to undo the damage. Forfeit the image, make a new one, and backup regularly. Try to not run more than one VM instance on a given image at a time.
A solution for this is forwarding the monitor to a local port through telnet while launching qemu on the host OS:
$ crete-qemu-2.3-system-x86_64 -hda crete-demo.img -m 256 -k en-us -loadvm test -monitor telnet:127.0.0.1:1234,server,nowait
Use the following command to access QEMU's monitor on the host OS:
$ telnet 127.0.0.1 1234
To resolve this, use the following command from the guest OS:
$ sudo rm -rf /var/lib/apt/lists/*