Skip to content

Commit b8d21f6

Browse files
Merge InSpectre Gadget V0
Co-authored-by: Sander Wiebing <45387038+SanWieb@users.noreply.github.com>
1 parent a8686f6 commit b8d21f6

File tree

381 files changed

+505410
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

381 files changed

+505410
-2
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
__pycache__
2+
.vscode/
3+
code/range/distribution/smt_samples
4+
results
5+
.venv/

README.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,44 @@
1-
# inspectre-gadget
2-
InSpectre Gadget
1+
![](./docs/img/inspectre-gadget-circle.png)
2+
3+
# InSpectre Gadget
4+
5+
This is the official repository for the InSpectre Gadget tool.
6+
7+
This code has been developed as part of our "InSpectre Gadget" paper, which is
8+
currently under submission. Access is limited to interested parties for now.
9+
10+
**Disclaimer**
11+
12+
This tool is a research project still under development. It should not be
13+
considered a production-grade tool by any means.
14+
15+
## Description
16+
17+
InSpectre Gadget is a tool for inspecting potential Spectre disclosure gadgets
18+
and performing exploitability analysis.
19+
20+
Documentation can be found at `docs/_build/html/index.html`.
21+
22+
## Usage
23+
24+
A typical workflow might look something like this:
25+
26+
```sh
27+
# Run the analyzer on a binary to find transmissions.
28+
mkdir out
29+
inspectre analyze <BINARY> --address-list <CSV> --config config_all.yaml --output out/gadgets.csv --asm out/asm
30+
31+
# Evaluate exploitability.
32+
inspectre reason gadgets.csv gadgets-reasoned.csv
33+
34+
# Import the CSV in a database and query the results.
35+
# You can use any DB, this is just an example with sqlite3.
36+
sqlite3 :memory: -cmd '.mode csv' -cmd '.separator ;' -cmd '.import gadgets-reasoned.csv gadgets' -cmd '.mode table' < queries/exploitable_list.sql
37+
38+
# Manually inspect interesting candidates.
39+
inspectre show <UUID>
40+
```
41+
42+
## Demo
43+
44+
![](docs/img/inspectre.gif)

analyzer/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Component that analyzes the binary to extract Spectre transmissions and their properties.
3+
"""

analyzer/analysis/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Set of analysis passes that are performed on transmission/dispatch gadgets.
3+
"""
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"""BaseControlAnalysis
2+
3+
This analysis is responsible of checking if the base of the transmission
4+
can be controlled independently from the secret and the secret address.
5+
"""
6+
7+
from enum import Enum
8+
import claripy
9+
import sys
10+
11+
from .dependencyGraph import DepGraph, is_expr_controlled
12+
13+
# autopep8: off
14+
from ..scanner.annotations import *
15+
from ..scanner.memory import *
16+
from ..shared.transmission import *
17+
from ..shared.logger import *
18+
from ..shared.astTransform import *
19+
# autopep8: on
20+
21+
l = get_logger("BaseControlAnalysis")
22+
23+
class BaseControlType(Enum):
24+
NO_BASE = 0,
25+
CONSTANT_BASE = 1,
26+
COMPLEX_TRANSMISSION = 2,
27+
# All symbols of the base are contained in the secret expression.
28+
BASE_DEPENDS_ON_SECRET_EXPR = 3,
29+
# All symbols of the base are either contained in the secret expression or
30+
# are loaded from an address that depends on the value of the secret.
31+
BASE_INDIRECTLY_DEPENDS_ON_SECRET_EXPR = 4,
32+
# All symbols of the base are contained in the secret address expression.
33+
# aka alias type 1.
34+
BASE_DEPENDS_ON_SECRET_ADDR = 5,
35+
# All symbols of the base are either contained in the expression of the
36+
# secret address or they are loaded from an address that depends on the
37+
# secret address.
38+
# aka alias type 2.
39+
BASE_INDIRECTLY_DEPENDS_ON_SECRET_ADDR = 6,
40+
41+
BASE_INDEPENDENT_FROM_SECRET = 7,
42+
UNKNOWN = 8
43+
44+
def get_expr_base_control(base_expr, transmitted_secret_expr, secret_address_expr, d: DepGraph, constraints: bool):
45+
secrets = set(get_vars(transmitted_secret_expr))
46+
47+
# If the base is not symbolic, we're done.
48+
if not is_sym_expr(base_expr) or not is_expr_controlled(base_expr):
49+
return BaseControlType.CONSTANT_BASE
50+
# Check if the base depends on the transmitted secret.
51+
elif not d.is_independently_controllable(base_expr, secrets, check_constraints=constraints, check_addr=False):
52+
return BaseControlType.BASE_DEPENDS_ON_SECRET_EXPR
53+
elif not d.is_independently_controllable(base_expr, secrets, check_constraints=constraints, check_addr=True):
54+
return BaseControlType.BASE_INDIRECTLY_DEPENDS_ON_SECRET_EXPR
55+
56+
else:
57+
# Check if the base depends on the secret address.
58+
secrets.update(get_vars(secret_address_expr))
59+
if not d.is_independently_controllable(base_expr, secrets, check_constraints=constraints, check_addr=False):
60+
return BaseControlType.BASE_DEPENDS_ON_SECRET_ADDR
61+
elif not d.is_independently_controllable(base_expr, secrets, check_constraints=constraints, check_addr=True):
62+
return BaseControlType.BASE_INDIRECTLY_DEPENDS_ON_SECRET_ADDR
63+
64+
# If none of the above are true, we conclude that the base is independent.
65+
else:
66+
return BaseControlType.BASE_INDEPENDENT_FROM_SECRET
67+
68+
69+
def get_base_control(t: Transmission, d: DepGraph, constraints: bool):
70+
if t.base != None:
71+
return get_expr_base_control(t.base.expr, t.transmitted_secret.expr, t.secret_address.expr, d, constraints)
72+
73+
# If there's no base expression, there might still be some symbol in the
74+
# transmission expression that does not depend on the secret.
75+
else:
76+
secrets = set(get_vars(t.secret_address.expr))
77+
secrets.add(t.secret_val.expr)
78+
if d.is_independently_controllable(t.transmission.expr, secrets, check_constraints=constraints, check_addr=True):
79+
return BaseControlType.COMPLEX_TRANSMISSION
80+
else:
81+
return BaseControlType.NO_BASE
82+
83+
84+
def analyse(t: Transmission):
85+
"""
86+
Check if the base depends on the secret or secret address.
87+
"""
88+
l.warning(f"========= [BASE] ==========")
89+
90+
# 1. Get dependency graph of all symbols involved in this transmission.
91+
d = t.properties["deps"]
92+
93+
# 2. Check control ignoring branches.
94+
t.properties["base_control_type"] = get_base_control(t, d, False)
95+
l.warning(f"Base control: {t.properties['base_control_type']}")
96+
97+
t.properties["base_control_w_constraints"] = get_base_control(t, d, True)
98+
l.warning(f"Base control with constraints: {t.properties['base_control_w_constraints']}")
99+
100+
# 3. Check control considering also branch constraints.
101+
if len(t.branches) > 0:
102+
d.add_constraints(map(lambda x: x[1], t.branches))
103+
d.resolve_dependencies()
104+
t.properties["base_control_w_branches_and_constraints"] = get_base_control(t, d, True)
105+
else:
106+
t.properties["base_control_w_branches_and_constraints"] = t.properties["base_control_w_constraints"]
107+
108+
l.warning(f"Base control including branches: {t.properties['base_control_w_branches_and_constraints']}")
109+
110+
t.properties["deps"] = d
111+
112+
l.warning(f"===========================")

0 commit comments

Comments
 (0)