Skip to content

Commit

Permalink
docs: update all examples with pip-based installation as a default
Browse files Browse the repository at this point in the history
  • Loading branch information
OleksiiOleksenko committed Apr 4, 2023
1 parent 73643e1 commit fd44f07
Show file tree
Hide file tree
Showing 10 changed files with 292 additions and 345 deletions.
230 changes: 111 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,160 +1,159 @@
# Revizor

This is Revizor, a microarchitectural fuzzer.
It is a rather unconventional fuzzer as, instead of finding bugs in programs, Revizor searches for microarchitectural vulnerabilities in CPUs.
![GitHub](https://img.shields.io/github/license/microsoft/sca-fuzzer)
![PyPI](https://img.shields.io/pypi/v/revizor-fuzzer)
![GitHub all releases](https://img.shields.io/github/downloads/microsoft/sca-fuzzer/total)
![GitHub contributors](https://img.shields.io/github/contributors/microsoft/sca-fuzzer)
<!-- ![PyPI - Downloads](https://img.shields.io/pypi/dm/revizor-fuzzer) -->

What is a microarchitectural vulnerability?
In the context of Revizor, it is a violation of out expectations about the CPU behavior, expressed as contract violations (see [Contracts](https://arxiv.org/abs/2006.03841)).
The most prominent examples would be [Spectre](https://spectreattack.com/), [Meltdown](https://meltdownattack.com/), and other speculative execution vulnerabilities.
Alternatively, a "bug" could also be in a form of a microarchitectural backdoor, although we are yet to encounter one of those.
Revizor is a security-oriented fuzzer for detecting information leaks in CPUs, such as [Spectre and Meltdown](https://meltdownattack.com/).
It tests CPUs against [Leakage Contracts](https://arxiv.org/abs/2006.03841) and searches for unexpected leaks.

For more details, see our [Paper](https://dl.acm.org/doi/10.1145/3503222.3507729) (open access [here](https://arxiv.org/abs/2105.06872)), and the [follow-up paper](https://arxiv.org/pdf/2301.07642.pdf).

# Getting Started

If you find a bug in Revizor, don't hesitate to [open an issue](https://github.com/microsoft/sca-fuzzer/issues).
If something is confusing or you need help in using Revizor, we have a [discussion page](https://github.com/microsoft/sca-fuzzer/discussions).

## Before you use Revizor
## Installation

Keep in mind that Revizor executes randomly-generated code in kernel space.
**Warning**:
Keep in mind that the Revizor runs randomly-generated code in kernel space.
As you can imagine, things could go wrong.
We are doing our best to avoid it by thoroughly testing the tool and making sure it is stable, but still, no software is perfect.
Make sure you're not running these experiments on an important machine.

## Requirements & Dependencies
Make sure you're not running Revizor on an important machine.

### 1. Hardware Requirements
### 1. Check Requirements

Revizor supports Intel and AMD x86-64 CPUs.
* Architecture: Revizor supports Intel and AMD x86-64 CPUs.
We also have experimental support for ARM CPUs (see `arm-port` branch) but it is at very early stages, use it on your own peril.

We also have experimental support for ARM CPUs (see `arm-port` branch) but use it on your own peril.
* No virtualization: You will need a bare-metal OS installation.
Testing from inside a VM is not (yet) supported.

### 2. Software Requirements
* OS: The target machine has to be running Linux v4.15 or later.

* OS and virtualization:
You will need a Linux bare-metal installation.
Other operating systems and testing from inside a VM is not (yet) supported.
### 2. Install Revizor Python Package

* Linux kernel: v4.15 or later.
Older kernels may or may not work - we have not tested on them.
If you use `pip`, you can install Revizor with:

To check your current Linux kernel version:
```shell
cat /proc/version
```bash
pip install revizor-fuzzer
```

* Linux Kernel Headers

```shell
# On Ubuntu
sudo apt-get install linux-headers-$(uname -r)
Alternatively, install Revizor from sources:
```bash
# run from the project root directory
make install
```

* [Python 3.9+](https://www.python.org/downloads/)
### 3. Install Revizor Executor (kernel module)

If your distribution has an older python by default, the best practice is to use a virtual environment.
```shell
# On Ubuntu 18
sudo apt install python3.9 python3.9-distutils
Then build and install the kernel module:

```bash
# building a kernel module require kernel headers
sudo apt-get install linux-headers-$(uname -r)

python3.9 -m venv venv
# get the source code
git clone https://github.com/microsoft/sca-fuzzer.git

# re-run this command every time you open a new terminal session
source ./venv/bin/activate
# build the executor
cd sca-fuzzer/src/x86/executor
make uninstall # the command will give an error message, but it's ok!
make clean
make
make install
```

* [Unicorn 1.0.2+](https://www.unicorn-engine.org/docs/).
Preferably, use version 1.0.2 or 1.0.3 as they seem to be currently the most stable.
We've encountered several bugs when using the most recent version 2.0.

### 4. Download ISA spec

```shell
sudo apt install unicorn
```bash
rvzr download_spec -a x86-64 --extensions BASE SSE SSE2 CLFLUSHOPT CLFSH --outfile base.json
```

* Python bindings to Unicorn
### 5. (Optional) System Configuration

```shell
pip3 install --user unicorn
For more stable results, disable hyperthreading (there's usually a BIOS option for it).
If you do not disable hyperthreading, you will see a warning every time you invoke Revizor; you can ignore it.

# OR, if installed from sources
cd bindings/python
sudo make install
Optionally (and it *really* is optional), you can boot the kernel on a single core by adding `-maxcpus=1` to the boot parameters ([how to add a boot parameter](https://wiki.ubuntu.com/Kernel/KernelBootParameters)).

# if you're using venv, copy the installation (the paths in your installation may differ)
cp -r /usr/local/lib/python3.6/site-packages/unicorn-1.0.3-py3.8.egg/unicorn/ venv/lib64/python3.9/site-packages/
```

* Python packages `pyyaml`, `types-pyyaml`, `numpy`:
## Command Line Interface

```shell
pip3 install --user pyyaml types-pyyaml numpy # skip --user if you're installing in venv
```
The fuzzer is controlled via a single command line interface `rvzr` (or `revizor.py` if you're running directly from the source directory).

### 3. Software Requirements for Revizor Development
It accepts the following arguments:
* `-s, --instruction-set PATH` - path to the ISA description file
* `-c, --config PATH` - path to the fuzzing configuration file
* `-n , --num-test-cases N` - number of test cases to be tested
* `-i , --num-inputs N` - number of input classes per test case. The number of actual inputs = input classes * inputs_per_class, which is a configuration option
* `-t , --testcase PATH` - use an existing test case instead of generating random test cases
* `--timeout TIMEOUT` - run fuzzing with a time limit [seconds]
* `-w` - working directory where the detected violations will be stored

Tests:
* [Bash Automated Testing System](https://bats-core.readthedocs.io/en/latest/index.html)
* [mypy](https://mypy.readthedocs.io/en/latest/getting_started.html#installing-and-running-mypy)
* [flake8](https://flake8.pycqa.org/en/latest/index.html)
For example, this command
```bash
rvzr fuzz -s base.json -n 100 -i 10 -c config.yaml -w ./violations
```
will run the fuzzer for 100 iterations (i.e., 100 test cases), with 10 inputs per test case.
The fuzzer will use the ISA spec stored in the `base.json` file, and will read the configuration from `config.yaml`. If the fuzzer finds a violation, it will be stored in the `./violations` directory.

See [docs](https://microsoft.github.io/sca-fuzzer/cli/) for more details.

Documentation:
* [pdoc3](https://pypi.org/project/pdoc3/)
## How To Fuzz With Revizor

### 4. (Optional) System Configuration
The fuzzing process is controlled by a configuration file in the YAML format, passed via `--config` option. At the very minimum, this file should contain the following fields:
* `contract_observation_clause` and `contract_execution_clause` describe the contract that the CPU-under-test is tested against. See [this page](https://microsoft.github.io/sca-fuzzer/config/) for a list of available contracts. If you don't know what a contract is, Sec. 3 of [this paper](https://arxiv.org/pdf/2105.06872.pdf) will give you a high-level introduction to contracts, and [this paper](https://www.microsoft.com/en-us/research/publication/hardware-software-contracts-for-secure-speculation/) will provide a deep dive into contracts.
* `instruction_categories` is a list of instruction types that will be tested. Effectively, Revizor uses this list to filter out instructions from `base.json` (the file you downloaded via `rvzr download_spec`).

For more stable results, disable hyperthreading (there's usually a BIOS option for it).
If you do not disable hyperthreading, you will see a warning every time you invoke Revizor; you can ignore it.
For a full list of configuration options, see [docs](https://microsoft.github.io/sca-fuzzer/config/).

Optionally (and it *really* is optional), you can boot the kernel on a single core by adding `-maxcpus=1` to the boot parameters ([how to add a boot parameter](https://wiki.ubuntu.com/Kernel/KernelBootParameters)).
### Baseline Experiment

In addition, you might want to stop any other actively-running software on the tested machine. We never encountered issues with it, but it might be useful.
After a fresh installation, it is normally a good idea to do a quick test run to check that everything works ok.

## Installation
For example, we can create a configuration file `config.yaml` with only simple arithmetic instructions. As this instruction set does not include any instructions that would trigger speculation on Intel or AMD CPUs (at least that we know of), the expected contract would be `CT-SEQ`:

### 1. Get the x86-64 ISA description:
```yaml
# config.yaml
instruction_categories:
- BASE-BINARY # arithmetic instructions
max_bb_per_function: 1 # no branches!
min_bb_per_function: 1

```bash
cd src/x86/isa_spec
./get_spec.py --extensions BASE SSE SSE2 CLFLUSHOPT CLFSH
contract_observation_clause: loads+stores+pc # aka CT
contract_execution_clause:
- no_speculation # aka SEQ
```
### 2. Install the executor kernel module:

Start the fuzzer:
```bash
cd src/x86/executor
make uninstall # the command will give an error message, but it's ok!
make clean
make
make install
rvzr fuzz -s base.json -i 50 -n 100 -c config.yaml -w .
```

## Running Tests
This command should terminate with no violations.

```bash
cd src/tests
./runtests.sh
```

If a few (up to 3) "Detection" tests fail, it's fine, you might just have a slightly different microarchitecture. But if other tests fail - something is broken.
### Detection of a Simple Contract Violation

## Basic Usability Test
Next, we could intentionally make a mistake in a contract to check that Revizor can detect it.
To this end, we can modify the config file from the previous example to include instructions that trigger speculation (e.g., conditional branches) but keep the contract the same:
```yaml
# config.yaml
instruction_categories:
- BASE-BINARY # arithmetic instructions
- BASE-COND_BR
max_bb_per_function: 5 # up to 5 branches per test case
min_bb_per_function: 1

1. Fuzz in a violation-free configuration:
```bash
./cli.py fuzz -s x86/isa_spec/base.json -i 50 -n 100 -c tests/test-nondetection.yaml
contract_observation_clause: loads+stores+pc # aka CT
contract_execution_clause:
- no_speculation # aka SEQ
```
No violations should be detected.

2. Fuzz in a configuration with a known contract violation (Spectre V1):
Start the fuzzer:
```bash
./cli.py fuzz -s x86/isa_spec/base.json -i 20 -n 1000 -c tests/test-detection.yaml
rvzr fuzz -s base.json -i 50 -n 1000 -c config.yaml -w .
```

A violation should be detected within a few minutes, with a message similar to this:
As your CPU-under-test almost definitely implements branch prediction, Revizor should detect a violation within a few minutes, with a message similar to this:

```
================================ Violations detected ==========================
Expand All @@ -169,36 +168,29 @@ A violation should be detected within a few minutes, with a message similar to t
```

Congratulations, you just found your first Spectre! You can find the violating test case in `generated.asm`.
You can find the violating test case as well as the violation report in the directory named `./violation-*/`.
It will contain an assembly file `program.asm` that surfaced a violation, a sequence of inputs `input-*.bin` to this program, and some details about the violation in `report.txt`.

# Fuzzing Example
### Full-Scale Fuzzing Campaign

To start a real fuzzing campaign, write your own configuration file (see description [here](docs/config.md) and an example config [here](src/tests/big-fuzz.yaml)), and launch the fuzzer.

Below is a example launch command, which will start a 24-hour fuzzing session, with 100 input classes per test case:
To start a full-scale test, write your own configuration file (see description [here](config.md) and an example config [here](https://github.com/microsoft/sca-fuzzer/tree/main/src/tests/big-fuzz.yaml)), and launch the fuzzer.

Below is a example launch command, which will start a 24-hour fuzzing session, with 100 input classes per test case, and which uses [big-fuzz.yaml](https://github.com/microsoft/sca-fuzzer/tree/main/src/tests/big-fuzz.yaml) configuration:
```shell
./cli.py fuzz -s x86/isa_spec/base.json -c tests/big-fuzz.yaml -i 100 -n 100000000 --timeout 86400 -w `pwd` --nonstop
rvzr fuzz -s base.json -c src/tests/big-fuzz.yaml -i 100 -n 100000000 --timeout 86400 -w `pwd` --nonstop
```

For more examples, see the `demo/` directory.
When you find a violation, you will have to do some manual investigation to understand the source of it; [this guide](fuzzing-guide.md) is an example of how to do such an investigation.

# Command line interface
## Need Help with Revizor?

The fuzzer is controlled via a single command line interface `cli.py` (located in `src/cli.py`). It accepts the following arguments:
If you find a bug in Revizor, don't hesitate to [open an issue](https://github.com/microsoft/sca-fuzzer/issues).

* `-s, --instruction-set PATH` - path to the ISA description file
* `-c, --config PATH` - path to the fuzzing configuration file
* `-n , --num-test-cases N` - number of test cases to be tested
* `-i , --num-inputs N` - number of input classes per test case. The number of actual inputs = input classes * inputs_per_class, which is a configuration option
* `-t , --testcase PATH` - use an existing test case instead of generating random test cases
* `--timeout TIMEOUT` - run fuzzing with a time limit [seconds]
* `--nonstop` - don't stop after detecting a contract violation
* `-w` - working directory where the detected violations will be stored
If something is confusing or you need help in using Revizor, we have a [discussion page](https://github.com/microsoft/sca-fuzzer/discussions).

# Documentation
## Documentation

For more details, see [docs/main.md](docs/main.md).
For more details, see [the website](https://microsoft.github.io/sca-fuzzer/).

## Contributing

Expand Down
14 changes: 6 additions & 8 deletions demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,33 @@ For example, if you fuzz an Intel CPU with `conf-v1.yaml`, you will likely detec

This demo targets Intel CPUs. Other microarchitectures are not yet supported (but coming soon!).

The commands below assume that the ISA spec (downloaded via `rvzr download_spec`) is stored in `base.json`.

* Spectre V1 ([description](https://meltdownattack.com/)):

```
cd src
./cli.py fuzz -s x86/isa_spec/base.json -c ../demo/conf-v1.yaml -i 50 -n 10000
rvzr fuzz -s base.json -c demo/conf-v1.yaml -i 50 -n 10000
```
Expected duration - several seconds.

* MDS or LVI-Null, depending on the CPU model ([description of MDS](https://mdsattacks.com/) and [LVI](https://lviattack.eu/)):

```
cd src
./cli.py fuzz -s x86/isa_spec/base.json -c ../demo/conf-v1.yaml -i 50 -n 10000
rvzr fuzz -s base.json -c demo/conf-v1.yaml -i 50 -n 10000
```
Expected duration - several minutes.

* Spectre V4 ([description](https://www.cyberus-technology.de/posts/2018-05-22-intel-store-load-spectre-vulnerability.html)):

```
cd src
./cli.py fuzz -s x86/isa_spec/base.json -c ../demo/conf-v4.yaml -i 50 -n 10000
rvzr fuzz -s base.json -c demo/conf-v4.yaml -i 50 -n 10000
```
Expected duration - 5-20 minutes.


* Spectre V1-Var ([description](https://dl.acm.org/doi/10.1145/3503222.3507729) and [here](https://eprint.iacr.org/2022/715.pdf))

```
cd src
./cli.py fuzz -s x86/isa_spec/base.json -c ../demo/conf-v1.yaml -i 50 -n 10000
rvzr fuzz -s base.json -c demo/conf-v1.yaml -i 50 -n 10000
```
Expected duration - several minutes.
Loading

0 comments on commit fd44f07

Please sign in to comment.