# sailfish
https://github.com/ucsb-seclab/sailfish
Используется ANGELIC-FLAG для построения модели, которая потом проверяется на SAT
reentrancy.sol интерпретирует путь исполнения, собирая value summary analysis для переменных. После этого, используя наложенные ограниченияна перменные, строится математическая модель и производится её решение.
Функции:
- do-solve(json-obj) - solver, принимает на вход загруженный symex_path.json
- interpret-path(i-scope, i-dest-daddrs, i-entry-daddr, attack?) - принимает scope, адрес назначения и адрес входа (в формате machine-get-saddr) и флаг атаки. Последовательно выполняет блоки начиная с точки входа и до точек выхода.
- machine-get-saddr(r-addr, r-scope) - r-addr@r-scope, преобразует относительные адреса в другой формат
- reg-make-type(r-name, r-type) - создаёт переменную с нужной структурой и сохраняет в register-hash
- interpret-block(i-scope, i-insts, dest?, attack?) - принимает scope, список инструкций, флаг назначения и атаки. Выполняет блок и возвращает адрес следующего блока.
- parse-code - строка инструкции преобразуется в структуру
- interpret-inst(i-scope, i-inst, attack?) - интерпретация инструкции
Глобальные объекты:
- block-hash - Хранилище для блоков - хранит в себе блоки инструкций
- register-hash - Хранилище для регистров - хранит в себе перменные, ANGELIC-FLAG
Последовательность вызова при обработке (single_function_malicious.sol):
```mermaid
flowchart TD
Start[/Start/]
--> load_json(Загрузка JSON объекта из файла)
-.-> do-solve(["do-solve(json-obj)"])
--> init_json_struct(Инициализация парсинга json)
--> set_angelic_flag(ANGELIC-FLAG = True)
--> load_global(Загрузка глобальных блоков инструкций __GLOBAL__)
--> load_global_var(Инициализация глобальных перменных)
--> global_var_interpret("Для каждой переменной вызывается interpret-path")
-.-> interpret_path_start
global_var_interpret
subgraph interpret_block
direction TB
interpret_block_start[["interpret-block(i-scope, i-insts, dest?, attack?)"]]
--> angelic_if_dest(Если dest? == True, ANGELIC-FLAG = True)
end
subgraph interpret_path
direction TB
interpret_path_start[["interpret-path(i-scope, i-dest-daddrs, i-entry-daddr, attack?)"]]
--> check_entry{{Точка входа - пустая?}}
-->|Да|interpret_path_fin(Конец функции)
check_entry -->|Нет|interpret_2("Вызвать interpret-block() для точки входа, если текущий блок - одна из точек выхода, задать dest? = True")
--> interpret_next{{interpret-block вернул адреса следующего блока?}}
-->|Да|interpret_rec(Вызываем interpret-path для следующего блока) -.-> interpret_path_start
interpret_next -->|Нет|interpret_path_fin
interpret_2 -.-> interpret_block_start
end
```
## Пометки
global vars:
```
json-global-vars => (
#hasheq((init . ()) (name . "block") (type . ("struct_block")))
#hasheq((init . ("0x6")) (name . "msg") (type . ("struct_msg")))
#hasheq((init . ()) (name . "now") (type . ("integer")))
#hasheq((init . ()) (name . "tx") (type . ("struct_tx")))
#hasheq((init . ("0x7")) (name . "this") (type . ("struct_this")))
#hasheq((init . ("0x8")) (name . "msg_sender") (type . ("integer")))
#hasheq((init . ()) (name . "addmod") (type . ("function3")))
#hasheq((init . ()) (name . "mulmod") (type . ("function3")))
#hasheq((init . ()) (name . "keccak") (type . ("function1")))
#hasheq((init . ()) (name . "sha256") (type . ("function1")))
#hasheq((init . ()) (name . "sha3") (type . ("integer")))
#hasheq((init . ()) (name . "ripemd160") (type . ("function1")))
#hasheq((init . ()) (name . "ecrecover") (type . ("function4")))
#hasheq((init . ()) (name . "blockhash") (type . ("function1")))
#hasheq((init . ()) (name . "userBalance") (type . ("array" "integer" "integer")))
#hasheq((init . ()) (name . "Reentrancy") (type . ("integer")))
)
```
У глобальных переменных в JSON есть поле "init" - оно содержит номер глобального блока который инициализирует эту перменную
Инструкция в виде структуры:
```
msg.sender = 0x6
i-inst => #(struct:inst "struct-assign#rs-rm-li" #("msg" "sender" "0x6"))
```
u-type??
Final registers example:
```
#zhash(
("REF_5" . {[TMP_1$1 (ite TMP_1$1 0 userBalance#6$0)] [(! TMP_1$1) zvoid]})
("CLR_11" . balance$0)
("CLR_7" . 6)
("CLR_13" . {[TMP_1$1 userBalance#6$0] [(! TMP_1$1) zvoid]})
("WRP_0" . (+ balance$0 (- userBalance#6$0)))
("block_timestamp_swap" . timestamp$0)
("block" . #zhash(("number" . number$0)
("timestamp" . timestamp$0)
("difficulty" . difficulty$0)
("coinbase" . coinbase$0)
("gaslimit" . gaslimit$0)))
("this" . #zhash(("address" . 5)
("balance" . (+ balance$0 (- userBalance#6$0)))))
("now" . now$0)
("CLR_12" . {[TMP_1$1 6] [(! TMP_1$1) zvoid]})
("tx" . #zhash(("gasprice" . gasprice$0)
("origin" . origin$0)))
("Reentrancy" . Reentrancy$0)
("CLR_9" . 6)
("msg_sender" . 4)
("CLR_14" . {[TMP_1$1 6] [(! TMP_1$1) zvoid]})
("sha3" . sha3$0)
("msg" . #zhash(("data" . data$0)
("sig" . sig$0)
("value" . value$0)
("sender" . 6)))
("CLR_10" . userBalance#6$0)
("REF_4" . userBalance#6$0)
("CLR_15" . {[TMP_1$1 6] [(! TMP_1$1) zvoid]})
("ANGELIC-FLAG" . TMP_1$1)
("tmp_now" . tmp_now$0)
("TMP_1" . TMP_1$1)
("TMP_3" . {[TMP_1$1 zvoid] [(! TMP_1$1) TMP_3$0]})
("tmp_block_timestamp" . tmp_block_timestamp$0)
("msg_value_swap" . value$0)
("tmp_msg_value" . tmp_msg_value$0)
("userBalance" . (vector
userBalance#0$0
userBalance#1$0
userBalance#2$0
userBalance#3$0
userBalance#4$0
userBalance#5$0
(ite TMP_1$1 0 userBalance#6$0)
userBalance#7$0
userBalance#8$0
userBalance#9$0))
("CLR_16" . {[TMP_1$1 (ite TMP_1$1 0 userBalance#6$0)] [(! TMP_1$1) zvoid]})
("CLR_17" . {[TMP_1$1 6] [(! TMP_1$1) zvoid]})
("CLR_8" . userBalance#6$0)
("now_swap" . now$0)
("TMP_2" . (! TMP_1$1)))
```