---
# System prepended metadata

title: Solar reconstruction

---

# Solar reconstruction

[TOC]

Задачи:
- [x] Найти и определить работу функции суммаризации
- [x] Понять вывод vandal, который используется для анализа
- [x] Проверить vandal - правильный ли вывод генерируется
- [ ] Найти и определить функцию синтезации
- [ ] Понять и разработать parallel-eval 


## Связь кода с статьей

Соляр предоставляет:
1. Язык запросов, с помощью которого можно выражать уязвимости. Например, запрос для reentrancy может выглядеть следующим образом:
![](https://i.imgur.com/RCgYFQs.png)

2. Синтезатор атакующих контрактов по данному запросу.

Key ideas:
- attacker typically exploits the vulnerability by making a sequence of transitions
- storage states are preserved across different transitions
- summary of a method soundly models its side-effect over storage variables
- Solar models the executions of a smartcontract as state transitions over registers, memory, and storage

Glossary:
- CFG - control flow graph
- pc - program counter (index of current executable instruction of vm - smth like rip register)
- tod - TOD attack/ front-running
- dao - DAO attack


Атаки заявленные в solar:
- Reentrancy attack
- Time manipulation
- malicious access control
- Security Best Practices
- BatchOverflow Bug (CVE-2018–10299)

Другие инструменты которые реализуют symbolic execution:
- mythril https://github.com/ConsenSys/mythril
- oyente https://github.com/enzymefinance/oyente
- teEther https://github.com/nescio007/teether

Для уменьшения пространства поиска, с помощью rosette оно делится на небольшое количестов

Program state: stack, memory, persistent storage, global properties, pc, (gas)
State transition: Г:s -> Г':v , что значит если успешно выполнить s в состоянии Г, то получим состояние Г' и значение v

R - abstract execution trace (list of events in interest. event = type, list of attrbibutes)

$𝑠@𝜙$: s - изменение состояния, ф - условие при котором изменение будет выполнено

Как solar анализирует контракт:
1. Program -> Intermediate Language
2. Symbolically execute IL code to build trace

Summary construction:
1. 1. Evaluate the method on a program state $Γ_𝑆$ that maps every state variable (i.e., persistent storage location, global property, etc.) to a fresh symbolic variable of the right type. 
    2. Produce a path condition and symbolic inputs for each instruction that capture every possible way to reach and execute the instruction within the given method.
2. Generate summary using following algorithm:
![](https://i.imgur.com/CK8iSDw.png)

При генерации summary учитываются только два вида инструкций - transfer и sstore, так как другие инструкции не имеют прямого влияния на state ($Г$)

Summary - сумма изменений state всех transfer и sstore для public метода


В статье solar представлен следуюшим образом:
![](https://i.imgur.com/gNUFuhp.png)

V - a potential vulnerability expressed as a declarative
specification (expressed in Racket as a boolean predicate
over these state transitions)
Y - union of public methods
K - длина генерируемого эксплойта

> Пояснение насчёт choose*
> Symbolically chooses one of the provided values. The procedure creates n-1 fresh symbolic boolean constants every time it is evaluated, and uses these constants to conditionally select one of the n provided expressions.

Что происходит, по строчкам:
1. -
2. Генерируется набор всех эксплойт-программ (в символическом представлении), длинной K, состоящая из публичных методов контракта
3. Контракт-жертва инициализируется, получаем начальное состояние
4. Символическая эксплойт-программа выполняется на контракте (из изначального состояния), сохраняется полученное состояние
5. Производится поиск конкретного эксплойта соответстующего запросу V
6. -//-

Основные части solar:
1. _interpreter_ (solidity/solidity-interpret.rkt) - implements the semantics from the EVM yellow paper. Интерпретатор не реализует symbolic execution - используется движок символического исполнения rosette. Interpreter выполняет следующие функции:
    1. compute the symbolic summaries of the victim’s public methods
    2. evaluate symbolic attack programs
2. _translator_ (использует vandal или ./smart_opt). Выполняет следующие функции:
    1. convert the stack-based EVM bytecode into its corresponding three-address format in our language

Параллелизм (parallel-driver.rkt? parallel-eval?):
Запрос solve (тяжелый и большой) делится на меньшие запросы, которые могут быть исполнены параллельно и быстро

Так как на 2 строке solar, количество генерируемых программ (при условии что аргументы - символиские) - $N^K$, где N - $|Y|$
Вместо того чтобы решать один запрос solve на 5 строке, мы можем запустить выполнение $N^K$ программ параллельно и убрать  -  !!! Уточнить на созвоне

### Что есть в коде (по статье):
Синтезация эксплойта: solidity/solidity-interpret.rkt (207-261)
check-intefere (проверка, вмешивается ли переменная в выражение): solidity/solidity-interpret.rkt (104-115)
Генерация суммаризации (инициализация анализатора): solidity/solidity-interpret.rkt (270-344)
Интерпретация суммаризации (выполнение символического представления суммаризации над состоянием): solidity/solidity-interpret.rkt (371-410)
Интерпретация программы (выполнение программы, т.е списка публичных методов, над состоянием): solidity/solidity-interpret.rkt (413-909)
Интерпретация программы (выполнение программы, т.е вектора объектов inst над состоянием): - пустая реализация
Измерение performance cost: - пустая реализация


Входная точка для анализа - init-analyzer
Нужно установить доп.флаги для выполнения:
1. (synth-mode #t) для синтезации атаки (по умолчанию #t)
2. (summary-mode #t) для использования суммаризации (по умолчани #f)

gen-summaries -> for each public method m do: progstate-summary(interpret-program(m))

interpret-program работает правильно, выдаёт состояние машины после интерпретации метода
interpret-program должен сразу создавать суммарзиацию, progstate-summary только извлекает поле summary из machine state

fix#7 не давал генерироваться summary для sstore - для исправления нужно найти pc (предположительно, pc - 0 аргумент)

![](https://i.imgur.com/c2rck3J.png)
![](https://i.imgur.com/XE9Nb4X.png)


---
## Доступный код solar:

### Python:
```
src/
    analysis/
        core_analysis.py
    vandal/
        blockparse.py
        cfg.py
        dataflow.py
        default_config.ini
        evm_cfg.py
        exporter.py
        function.py
        lattice.py
        memtypes.py
        opcodes.py
        patterns.py
        settings.py
        tac_cfg.py

eval_parallel.py - Invokes ./smartscopy in several processes
smart_opt - Vandal EVM Decompiler v0.0.3
```

### Тесты:
```
test/
    bin/
    ccs16/
    fuzz-timeout/
    sol/
```

### Racket:
```
solidity/
    main.rkt
    optimize.rkt
    solidity-enumerator.rkt
    solidity-interpret.rkt
    solidity-machine.rkt
    solidity-parser.rkt
    solidity-printer.rkt

enumerator.rkt
inst.rkt
machine.rkt - ABS Base class: machine
memory-racket.rkt
memory-rosette.rkt
ops-racket.rkt
ops-rosette.rkt
parser.rkt - define: struct inst, struct pointer, helper functions for random
printer.rkt
queue-racket.rkt
queue-rosette.rkt
simulator-racket.rkt - class: simulator-racket
simulator.rkt - ABS Base class: simulator
simulator-rosette.rkt - rosette, class: simulator-rosette
smartexe.rkt
special.rkt - define "special" type
```


### Классы:
```plantuml
@startuml
abstract class "simulator" {
    interpret()
    performance-cost()
    +get-constructor()
    +is-valid?()
}

class "simulator-rosette"
class "simulator-racket"

"simulator" <|-- "simulator-rosette"
"simulator" <|-- "simulator-racket"


abstract class "machine" {
    bitwidth
    random-input-bits
    config
    opcodes
    nop-id
    opcode-id-to-class
    classes-info
    argtypes-info
    statetypes-info
    groups-of-opcodes
    max-number-of-args
    vector2scalar
    opcode-pool
    
    progstate-structure()
    +define-instruction-class()
    
    +window-size()
    +get-config()
    +set-config(info)
    +get-opcode-id(opcode)
    +get-opcode-name(id)
    +no-assumption()
    +display-state(x)
    +progstate->vector(x)
    +vector->progstate(x)
    +parse-state-text(str)
    +clean-code(code, prefix)
    +state-eq?(state1, state2, pred)
    +get-state(init, concrete)
    +progstate()
    +inner(x)
    +clone-state(state)
    
    +init-machine-description(opcode-types)
    +define-instruction-class(name, class-opcodes, scalar, vector-width, args, ins, outs, commute, required)
    +check-max-number-of-args(args)
    +filter-statetype(locs, args)
    +all-opcodes-groups(opcodes-groups, args-groups, ins-groups, required)
    +all-opcodes-combinations(opcodes-groups)
    +define-progstate-type(name, get, set, min, max, const, structure)
    +define-arg-type(name, validfunc, progstate)
    +finalize-machine-description()
    +get-arg-range-of-type(type, live, vals)
    +analyze-args-inst(my-inst)
    +get-progstate-ins-outs(opcode-id)
    +get-progstate-at(state, locs, types, args)
}

class printer
class enumerator
class parser

class memory-racket
class memory-rosette

class queue-in-racket
class queue-out-racket

class queue-in-rosette
class queue-out-rosette


class solidity-printer


@enduml
```


---
### Файлы которых нет:
```
parallel-driver.rkt - required by solidity/main.rkt
solidity/
    solidity-simulator-racket.rkt - required by solidity/main.rkt
    solidity-simulator-rosette.rkt - required by solidity/main.rkt
    solidity-validator.rkt - required by solidity/main.rkt
```

### Заметки:
- solidity-simulator-rosette находится в solidity/solidity-interpret.rkt
- solidity-simulator-racket не используется

### Починка solar:
1. smart_opt
```
Traceback (most recent call last):
  File "/home/ucat/Research/solar/./smart_opt", line 13, in <module>
    import src.vandal.exporter as exporter
ModuleNotFoundError: No module named 'src.vandal'
```
fix:
```bash=
touch src/__init__.py
touch src/vandal/__init__.py
```

2. smart_opt

```
Traceback (most recent call last):
  File "/home/ucat/Research/solar/./smart_opt", line 196, in <module>
    dataflow.analyse_graph(cfg)
  File "/home/ucat/Research/solar/src/vandal/dataflow.py", line 60, in analyse_graph
    start_clock = time.clock()
AttributeError: module 'time' has no attribute 'clock'
```
fix:
use python3.6

3. solar
```
solidity/solidity-interpret.rkt:229:29: gasless: unbound identifier
```
fix:
remove has-gasless? - not used

4. solar
```
solidity/solidity-interpret.rkt:231:46: cst: unbound identifier
```
fix:
- cst есть в комментах, два варианта. Расскоментируем с vul-access
- Вероятно cst контролирует вид атаки на который тестируется контракт

5. solar
```
solidity/solidity-interpret.rkt:238:46: has-gasless?: unbound identifier
```
fix:
Вернуть has-gasless, сделать чтобы он возвращал только True

6. solar
```
solidity/solidity-interpret.rkt:247:17: parallel-eval: unbound identifier
```
fix:
solidity-interpret.rkt использует parallel-eval
Реализовать parllel-eval самостоятельно

7. solar
```
solidity/solidity-interpret.rkt:574:79: pc: unbound identifier
```
fix:
pc ?? ipc ??
possibly one of the arguments - now only dirty fix

8. solar
```
smartexe.rkt:5:20: cannot open module file
  module path: rosette/query/debug
```
fix:
this module does not exists, remove file from imports

9. solar
```
boolector: boolector binary is not available
```
fix:
```bash
yay -S boolector
```

### Запуск solar:
- Предположительно точка входа - smartexe.rkt
smartexe.rkt запускает "./smart_opt argv[0]"

```bash=
racket smartexe.rkt test/bin/reentrance.hex
```

### Запуск smart_opt - работает
An EVM bytecode disassembly decompiler that generates three-address code for program analysis. Use config.ini to set further configuration
options.

Читает байткод из входного файла (по умолчанию stdin), выдаёт Control flow graph в виде JSON

smart_opt использует vandal для построения CFG, после чего запускает анализ графа (CostAnalysis)

Формат данных:
Публичная функция представляется в формате 0xAA-B, AA - адрес начальной инструкции, B - количество аргументов

### Проверка vandal

test/bin/reentrance.hex

Публичные методы которые нашёл vandal:
![](https://i.imgur.com/kPZSfVw.png)

Методы которые есть в исходнике:
```
mapping(address => uint) public balances
function donate(address _to) public payable
function balanceOf(address _who) public constant returns (uint balance)
function withdraw(uint _amount) public
function() payable
```

Т.е. вандал нашёл один лишний метод с одним аргументом

Проверим методы которые он нашёл:
1. 0x63-1 = donate(address _to)

decompiler:
![](https://i.imgur.com/hvmujeg.png)
![](https://i.imgur.com/JIbv9On.png)

Блок продолжается до 0x174, где происходят присвоения с использованием keccak256

2. 0xa5-1 = balanceOf(address _who)
![](https://i.imgur.com/DYoYD8G.png)
![](https://i.imgur.com/CSmechh.png)

jump to 0x1c3, return data from storage

3. 0xfc-1 = withdraw(uint _amount)

![](https://i.imgur.com/yqJnITi.png)
![](https://i.imgur.com/JcnqEUV.png)
![](https://i.imgur.com/THWLDJg.png)


jump to 0x1db, check if `storage[addr] < argument`, if not -> jump to 0x29c (return), else -> jump 0x223
0x223 -> call `addr` with `arg` eth, change `storage[addr] = storage[addr] - arg`

4. 0x129-1 = mapping balances
5. 0x61-0 = not a function, stop() if no func found by signature

### Генерация суммаризации

sstore, sload, call - три инструкции которые учитываются при анализе

#### jumpi
![](https://i.imgur.com/oF9AYVm.png)

При интерпретации jumpi интерепретируются блоки pos-succ (условие выполнено) и neg-succ (условие не выполнено)

#### call

Происходит проверка вмешательства (check interfere) с различными перменными storage
По какой-то причине после обработки call анализ блока прерывается. Ниже по блоку происходит работа с storage. т.к. Блок не обработан до конца -> суммаризация функции не генерируется

### parallel-eval
sketch = parallel-eval
query-model sketch ? not uses sketch

get-item method->expr sketch

method->expr is table to translate from (bv method repr) to (struct bv method + args)


get-item - search for a list with first element equal to key in table


# tmp

```
(&& 
  (! 
    (bveq 
      (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) 
    (bvand 
      (bv #x00000000000000000000000000000000000000000000000000000000000000ff 256) store-var$0))) 
  (! (bveq 
  (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) ...)))
```

```
(list
 "summaries:"
 (hash
  (bv #x04 8)
  '()
  
  (bv #x0b 8)
  (list
   (cons
    (bv #x0000000000000000000000000000000000000000000000000000000000000271 256)
    (store-sum
     (bv #x0000000000000000000000000000000000000000000000000000000000000000 256)
     (bvor (ite (bveq (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) arg$3) (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) (bv #x0000000000000000000000000000000000000000000000000000000000000001 256)) (bvand ...)))))
     
  (bv #x0f 8)
  (list
   (cons
    (bv #x00000000000000000000000000000000000000000000000000000000000002b8 256)
    (store-sum
     (app sha3-app (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) (bv #x0000000000000000000000000000000000000000000000000000000000000040 256))
     arg$4)))
     
  (bv #x07 8)
  (list
   (cons
    (bv #x00000000000000000000000000000000000000000000000000000000000001d5 256)
    (store-sum
     (app sha3-app (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) (bv #x0000000000000000000000000000000000000000000000000000000000000040 256))
     (bvadd store-var$1 (bvneg (bvmul arg$1 arg$2)))))
   (cons
    (bv #x000000000000000000000000000000000000000000000000000000000000022d 256)
    (call-sum
     152
     (bvmul (bv #x00000000000000000000000000000000000000000000000000000000000008fc 256) (ite (bveq (bv #x0000000000000000000000000000000000000000000000000000000000000000 256) arg$2) (bv #x0000000000000000000000000000000000000000000000000000000000000001 256) (bv #x0000000000000000000000000000000000000000000000000000000000000000 256)))
     (bvand (bv #x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff 256) var$219)
     arg$2)))))
```