#CRETE User Guide
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.
Install the following dependencies at first:
$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test
$ sudo apt-get update
$ sudo apt-get install build-essential libaio1 librbd1 libsdl1.2debian
$ sudo apt-get install --only-upgrade libstdc++6
Install CRETE from debian packages:
$ sudo dpkg -i crete-0.1.1-amd64.deb crete-native-qemu-0.1.1-amd64.deb
Pakcage crete-0.1.1-amd64.deb provides executables and libraries of CRETE. Package crete-native-qemu-0.1.1-amd64.deb contains a native qemu that provides execution dependency and creates tests for CRETE.
On some architectures, you might also need to set the following environment variables (best to put them in a config file like .bashrc):
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
CRETE can be removed by:
$ sudo apt-get remove crete crete-native-qemu
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 -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 CRETE_RAMDISK_PATH=~/tests/ramdisk' >> ~/.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.
####Save Snapshot 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.
####Load Snapshot 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.
####Provide a configuration file for the target binary Boot the VM image using native qemu without kvm-enabledfirst 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.
####Start crete-dispatch on the Host OS: 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
####Start crete-vm-node on the Host OS: 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
####Start crete-svm-node on the Host OS: 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/*