
Outil d'analyse de sécurité pour module WebAssembly (wasm) et contrats intelligents blockchain (BTC/ETH/NEO/EOS)
Un grand merci à QuoScient pour avoir sponsorisé ce projet.
Octopus est un framework d'analyse de sécurité pour les modules WebAssembly et les smart contracts de blockchain.
Le but d'Octopus est de fournir un moyen simple d'analyser les modules WebAssembly et le bytecode des smart contracts en source fermée afin de comprendre plus en profondeur leurs comportements internes.
Octopus prend en charge les types de programmes/smart contracts suivants :
| BTC | ETH (EVM) | ETH (WASM) | EOS | NEO | WASM | ||
|---|---|---|---|---|---|---|---|
| Explorer | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⭕ | |
| Désassembleur | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| Analyse de flux de contrôle | ✖️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
| Analyse de flux d'appels | ✖️ | ➕ | ✔️ | ✔️ | ➕ | ✔️ | |
| Conversion en IR (SSA) | ✖️ | ✔️ | ➕ | ➕ | ✖️ | ✔️ | |
| Exécution symbolique | ✖️ | ➕ | ➕ | ➕ | ✖️ | ➕ |
✔️ FAIT / ➕ EN COURS / ✖️ À FAIRE / ⭕ N/A
Octopus est pris en charge sur Linux (idéalement Ubuntu 16.04) et nécessite Python >=3.5 (idéalement 3.6).
Dépendances :
sudo apt-get update && sudo apt-get install python-pip graphviz xdg-utils -y
- Installer Octopus :```
# Download Octopus
git clone https://github.com/pventuzelo/octopus
cd octopus
# Install Octopus library/CLI and its dependencies
python3 setup.py install
ou```
pip3 install octopus
- Exécuter les tests```
# Run tests for all platforms (disassembly, CFG, ...)
./run_tests.sh
# Run tests that require internet access (explorer tests)
./run_explorer_tests.sh
# Run tests for only one platforms
# {btc, eth, eos, neo, wasm}_run_tests.sh
cd octopus/tests/
./wasm_run_tests.sh
Un conteneur Docker fournissant la boîte à outils est disponible sur docker hub. Dans un terminal, exécutez les commandes suivantes:``` docker pull smartbugs/octopus docker run -it smartbugs/octopus cd octopus python3 octopus_eth_evm.py -s -f examples/ETH/evm_bytecode/61EDCDf5bb737ADffE5043706e7C5bb1f1a56eEA.bytecode
## Outils en ligne de commande
* WebAssembly: [octopus_wasm.py](https://github.com/fuzzinglabs/octopus/blob/master/octopus_wasm.py)
* Ethereum (EVM): [octopus_eth_evm.py](https://github.com/fuzzinglabs/octopus/blob/master/octopus_eth_evm.py)
## Exemples approfondis avec les API
<details><summary>WebAssembly</summary>
<p>
#### Désassembleur
Désassemblage d'un module Wasm :```python
from octopus.arch.wasm.disassembler import WasmDisassembler
FILE = "examples/wasm/samples/helloworld.wasm"
with open(FILE, 'rb') as f:
module_bytecode = f.read()
disasm = WasmDisassembler()
# return list of functions instructions (list)
print(disasm.disassemble_module(module_bytecode))
#[[<octopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904278>,<octopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904f60>,<octopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904ef0>]]
print()
# return text of functions code
print(disasm.disassemble_module(module_bytecode, r_format='text'))
# func 0
# i32.const 0
# call 0
# end
Désassemblage du bytecode wasm:```python from octopus.arch.wasm.disassembler import WasmDisassembler
bytecode = b'\x02\x7fA\x18\x10\x1cA\x00\x0f\x0b'
disasm = WasmDisassembler(bytecode)
print(disasm.disassemble())
#[<octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904eb8>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048>] print() print(disasm.disassemble(r_format='reverse'))
#{0: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048>, 1: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904240>, 2: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60>, 3: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0>, 4: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278>, 5: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390>} print() print(disasm.disassemble(r_format='text'))
#### ModuleAnalyzer```python
from octopus.arch.wasm.analyzer import WasmModuleAnalyzer
FILE = "examples/wasm/samples/hello_wasm_studio.wasm"
with open(FILE, 'rb') as f:
module_bytecode = f.read()
# return list of functions instructions (list)
# attributes analysis=True by default
analyzer = WasmModuleAnalyzer(module_bytecode)
# show analyzer attributes
print(analyzer.func_prototypes)
# [('putc_js', 'i32', ''),
# ('__syscall0', 'i32', 'i32'),
# ('__syscall3', 'i32 i32 i32 i32', 'i32'),
# ('__syscall1', 'i32 i32', 'i32'),
# ('__syscall5', 'i32 i32 i32 i32 i32 i32', 'i32'),
# ('__syscall4', 'i32 i32 i32 i32 i32', 'i32'),
# ('$func6', '', ''),
# ('main', '', 'i32'),
# ('writev_c', 'i32 i32 i32', 'i32'),
# ('$func9', '', 'i32'),
# ('$func10', 'i32', 'i32'),
# ('$func11', 'i32', 'i32'),
# ('$func12', 'i32', ''),
# ('$func13', 'i32', 'i32'),
# ('$func14', 'i32 i32 i32 i32', 'i32'),
# ('$func15', 'i32 i32', 'i32'),
# ('$func16', 'i32 i32', 'i32'),
# ('$func17', 'i32', 'i32'),
# ('$func18', 'i32', 'i32'),
# ('$func19', 'i32', 'i32'),
# ('$func20', 'i32 i32 i32', 'i32'),
# ('$func21', 'i32 i32 i32', 'i32'),
# ('$func22', 'i32 i64 i32', 'i64'),
# ('$func23', 'i32 i32 i32', 'i32'),
# ('$func24', 'i32', 'i32'),
# ('$func25', 'i32 i32 i32 i32', '')]
print()
print(analyzer.contains_emscripten_syscalls())
#[('__syscall0', 'restart_syscall'),
# ('__syscall3', 'read'),
# ('__syscall1', 'exit'),
# ('__syscall5', 'open'),
# ('__syscall4', 'write')]
from octopus.arch.wasm.cfg import WasmCFG
file_name = "examples/wasm/samples/fib.wasm"
with open(file_name, 'rb') as f: raw = f.read()
cfg = WasmCFG(raw)
cfg.visualize()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/a317892fc1e0ce1939535b5f1e0fd00188634ec14f21e7f5eee950e4c2f92206.png" height="400px"/>
</p>
#### Analyse des instructions des fonctions```python
from octopus.arch.wasm.cfg import WasmCFG
# complete wasm module
file_name = "examples/wasm/samples/hello_wasm_studio.wasm"
# read file
with open(file_name, 'rb') as f:
raw = f.read()
# create the cfg
cfg = WasmCFG(raw)
# visualization
cfg.visualize_instrs_per_funcs()
from octopus.arch.wasm.cfg import WasmCFG
file_name = "examples/wasm/samples/hello_wasm_studio.wasm"
with open(file_name, 'rb') as f: raw = f.read()
cfg = WasmCFG(raw)
cfg.visualize_call_flow()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/62fcb93f3dcec6856fdcb2618024b5e72da74112e8277d6113c9e2e008c5ecf6.png" height="400px"/>
</p>
Légende :
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/332b97a2eb228b9a43dd7a13857b7e593353ebea1555d2d0efd38964ef902d20.png" height="400px"/>
</p>
#### IR conversion (SSA)```python
from octopus.arch.wasm.emulator import WasmSSAEmulatorEngine
# complete wasm module
file_name = "examples/wasm/samples/fib.wasm"
# read file
with open(file_name, 'rb') as f:
raw = f.read()
# run the emulator for SSA
emul = WasmSSAEmulatorEngine(raw)
emul.emulate_one_function('fib')
# or emul.emulate_functions(['fib'])
# or emul.emulate_functions() # emulate all the function
# visualization of the cfg with SSA
emul.cfg.visualize(ssa=True)
from octopus.platforms.ETH.explorer import EthereumInfuraExplorer from octopus.platforms.ETH.explorer import INFURA_ROPSTEN
KEY_API = "bHuaQhX91nkQBac8Wtgj"
explorer = EthereumInfuraExplorer(KEY_API, network=INFURA_ROPSTEN)
block_number = explorer.eth_blockNumber() print(block_number)
addr = "0x3c6B10a5239B1a8A27398583F49771485382818F" code = explorer.eth_getCode(addr) print(code)
#### Désassembleur```python
from octopus.platforms.ETH.disassembler import EthereumDisassembler
# smart contract bytecode
bytecode_hex = "60606040526000357c0100000000000000000000000000000000000000000000000000000000900480635fd8c7101461004f578063c0e317fb1461005e578063f8b2cb4f1461006d5761004d565b005b61005c6004805050610099565b005b61006b600480505061013e565b005b610083600480803590602001909190505061017d565b6040518082815260200191505060405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff16611111600060005060003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060005054604051809050600060405180830381858888f19350505050151561010657610002565b6000600060005060003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050819055505b565b34600060005060003373ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055505b565b6000600060005060008373ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000505490506101b6565b91905056"
disasm = EthereumDisassembler()
disasm.disassemble(bytecode_hex)
# disassemble bytecode into a list of EthereumInstruction
# attributes r_format='list' by default
print(disasm.disassemble(bytecode_hex))
#[<octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4add5c0>, <octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8588>, <octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8c50>]
print()
print(disasm.disassemble(bytecode_hex, r_format='reverse'))
# {0: <octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8160>, ..., 229: <octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8630>, 230: <octopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad87b8>}
print()
print(disasm.disassemble(bytecode_hex,r_format='text'))
# PUSH1 0x60
# PUSH1 0x40
# MSTORE
# PUSH1 0x0
# CALLDATALOAD
# PUSH29 0x100000000000000000000000000000000000000000000000000000000
# SWAP1
# DIV
# DUP1
# PUSH4 0x5fd8c710
# EQ
# PUSH2 0x4f
# JUMPI
# ...
# SWAP2
# SWAP1
# POP
# JUMP
from octopus.analysis.graph import CFGGraph from octopus.platforms.ETH.cfg import EthereumCFG
file_name = "examples/ETH/evm_bytecode/Zeppelin_Hello_ethernaut0.bytecode"
with open(file_name) as f: bytecode_hex = f.read()
cfg = EthereumCFG(bytecode_hex)
graph = CFGGraph(cfg) graph.view()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/f1ab0983ab68ff22aa4d97893fa25466cf220562fecdffebd6de1333877a8b57.png"/>
</p>
#### Conversion IR (SSA)```python
# The conversion to SSA is already done by the SSAEmulator
# when the CFG is reconstruct
# by default you have just to visualize it
from octopus.platforms.ETH.cfg import EthereumCFG
# ethernaut0 bytecode
file_name = "examples/ETH/evm_bytecode/Zeppelin_Hello_ethernaut0.bytecode"
# read file
with open(file_name) as f:
bytecode_hex = f.read()
# create the CFG
cfg = EthereumCFG(bytecode_hex)
# SSA visualization
cfg.visualize(ssa=True)
from octopus.platforms.ETH.explorer import EthereumInfuraExplorer from octopus.platforms.ETH.explorer import INFURA_KOVAN
explorer = EthereumInfuraExplorer("bHuaQhX91nkQBac8Wtgj", network=INFURA_KOVAN)
block_number = explorer.eth_blockNumber() print('blockNumber = %d' % block_number)
addr = "0x1120e596b173d953ba52ce262f73ce3734b0e40e" code = explorer.eth_getCode(addr) print() print(code)
#### Désassembleur
Désassemblage d'un module Wasm :```python
from octopus.platforms.ETH.disassembler import EthereumDisassembler
FILE = "examples/ETH/wasm/helloworld_kovan.bytecode"
with open(FILE, 'r') as f:
module_bytecode = f.read()
disasm = EthereumDisassembler(arch='wasm')
# return list of functions instructions (list)
print(disasm.disassemble_module(module_bytecode))
#[[<octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa898>], [<octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa7b8>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa780>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa748>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa6d8>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa710>]]
print()
# return text of functions code
print(disasm.disassemble_module(module_bytecode, r_format='text'))
# func 0
# end
#
# func 1
# call 1
# i32.const 1036
# i32.const 232
# call 0
# end
Désassemblage du bytecode wasm:```python from octopus.platforms.ETH.disassembler import EthereumDisassembler
bytecode = b'\x02\x7fA\x18\x10\x1cA\x00\x0f\x0b'
disasm = EthereumDisassembler(bytecode, arch='wasm')
print(disasm.disassemble())
#[<octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904eb8>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60>, <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048>] print() print(disasm.disassemble(r_format='reverse'))
#{0: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048>, 1: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904240>, 2: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60>, 3: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0>, 4: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278>, 5: <octopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390>} print() print(disasm.disassemble(r_format='text'))
#### ModuleAnalyzer```python
from octopus.arch.wasm.analyzer import WasmModuleAnalyzer
FILE = "examples/ETH/wasm/helloworld_kovan.bytecode"
with open(FILE, 'r') as f:
module_bytecode = f.read()
# return list of functions instructions (list)
# attributes analysis=True by default
analyzer = WasmModuleAnalyzer(module_bytecode)
# show analyzer attributes
print(analyzer.func_prototypes)
# [('ret', 'i32 i32', '', 'import'), ('$func1', '', '', 'local'), ('call', '', '', 'export')]
print()
print(analyzer.exports)
# [{'field_str': 'call', 'kind': 0, 'index': 2}]
print()
print(analyzer.imports_func)
# [('env', 'ret', 1)]
print()
print(analyzer.datas)
# [{'data': b'Hello world', 'index': 0, 'offset': None, 'size': 11},
# {'data': b'\x00asm\x01\x00\x00\x00\x01\t\x02`\x00\x00`\x02\x7f\x7f\x00\x02\x1a\x02\x03env\x03ret\x00\x01\x03env\x06memory\x02\x01\x02\x10\x03\x03\x02\x00\x00\x04\x05\x01p\x01\x01\x01\x05\x01\x00\x06\x01\x00\x07\x08\x01\x04call\x00\x01\n\x12\x02\x05\x00\x10\x02\x00\x0b\n\x00A\x80\x08A\x0b\x10\x00\x00\x0b\x0b\x12\x01\x00A\x80\x08\x0b\x0bHello world\x00\x0b\x07linking\x03\x01\x0b\x00f\x04name\x01_\x06\x00\x03ret\x01\x05panic\x02\x04call\x03/_ZN14pwasm_ethereum3ext3ret17h604d8098d1686c80E\x04\x06deploy\x05\x11rust_begin_unwind',
# 'index': 0,
# 'offset': None,
# 'size': 232}]
from octopus.platforms.ETH.cfg import EthereumCFG
file_name = "examples/ETH/wasm/helloworld_kovan.bytecode"
with open(file_name) as f: bytecode_hex = f.read()
cfg = EthereumCFG(bytecode_hex, arch='wasm') cfg.visualize()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/7a8e6cc4ce71f467e09100a231e1916c4101a56094a5883bd42534c419ba0dc2.png" height="400px"/>
</p>
#### Analyse des instructions des fonctions```python
from octopus.platforms.ETH.cfg import EthereumCFG
# HelloWorld on Kovan Parity Network
file_name = "examples/ETH/wasm/helloworld_kovan.bytecode"
# read file
with open(file_name) as f:
bytecode_hex = f.read()
# create the CFG
cfg = EthereumCFG(bytecode_hex, arch='wasm')
# visualization
cfg.visualize_instrs_per_funcs()
from octopus.platforms.ETH.cfg import EthereumCFG
file_name = "examples/ETH/wasm/helloworld_kovan.bytecode"
with open(file_name) as f: bytecode_hex = f.read()
cfg = EthereumCFG(bytecode_hex, arch='wasm')
cfg.visualize_call_flow()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/a3b69354067c4b7c707fc60c7c844688a30bbb6dd4de54528545554148e83d0e.png" height="400px"/>
</p>
Légende :
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/332b97a2eb228b9a43dd7a13857b7e593353ebea1555d2d0efd38964ef902d20.png" height="400px"/>
</p>
#### Conversion en IR (SSA)```python
# TODO
from octopus.platforms.NEO.explorer import NeoExplorerRPC
explorer = NeoExplorerRPC(host='seed2.neo.org')
print(explorer.getblockcount())
contract = explorer.getcontractstate("d3cce84d0800172d09c88ccad61130611bd047a4") print(contract)
print(contract['script'])
#### Désassembleur```python
from octopus.platforms.NEO.disassembler import NeoDisassembler
# lock contract
file_name = "examples/NEO/samples/Lock.bytecode"
# read file
with open(file_name) as f:
bytecode = f.read()
disasm = NeoDisassembler()
print(disasm.disassemble(bytecode, r_format='text'))
# PUSH6
# NEWARRAY
# TOALTSTACK
# FROMALTSTACK
# DUP
# TOALTSTACK
# PUSH0
# PUSH2
# ROLL
# SETITEM
# FROMALTSTACK
# ....
# PICKITEM
# NOP
# FROMALTSTACK
# DROP
# RET
from octopus.analysis.graph import CFGGraph from octopus.platforms.NEO.cfg import NeoCFG
file_name = "examples/NEO/samples/Lock.bytecode"
with open(file_name) as f: raw = f.read()
cfg = NeoCFG(raw)
graph = CFGGraph(cfg, filename="Lock_cfg") graph.view_functions()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/049c210aab8b977951cb7236f6f5d3361f0dd4be330df21392543b1e6538f5de.png"/>
</p>
</p>
</details>
<details><summary>EOS</summary>
<p>
#### Explorateur```python
from octopus.platforms.EOS.explorer import EosExplorer
host = "api.cypherglass.com"
# by defaul the port is 8888
explo = EosExplorer(host=host)
# get info about the node
explo.get_info()
'''
{'block_cpu_limit': 180289,
'block_net_limit': 1045680,
'chain_id': 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906',
'head_block_id': '018d6e2bcf6295126cd74cf694b5cca3529eefc42b334b394ef87c3a43876739',
'head_block_num': 26045995,
'head_block_producer': 'eosswedenorg',
'head_block_time': '2018-11-09T14:11:29.500',
'last_irreversible_block_id': '018d6cdcff78bbd9f25c605b02fb67c47a337ece78ddcf73089cee4bf6a410ee',
'last_irreversible_block_num': 26045660,
'server_version': 'c71d2245',
'server_version_string': 'mainnet-1.3.0',
'virtual_block_cpu_limit': 38092879,
'virtual_block_net_limit': 1048576000}
'''
explo.get_block(1337)
'''
{'action_mroot': 'bcb9763baa3bbf98ed36379b4be0ecb2d9cd21c75df01729c63b2b021001c10c',
'block_extensions': [],
'block_num': 1337,
'confirmed': 0,
'header_extensions': [],
'id': '00000539d17a03af7126e073be4c4d99a72b7f58793cf2c87b9bfd41b6c711fb',
'new_producers': None,
'previous': '00000538b374c1cbfaeed7253ad3075ddc72a28f0a0515301fc1bbed675f2316',
'producer': 'eosio',
'producer_signature': 'SIG_K1_K5jWf36t6j454Hb2fGuV37YTwMTvuQ51ZPBtpru8Ud2axtMTEauWyvtpJuTpnvqzReUndDgEDXvoeEP4jdj2bpnYKBt6g2',
'ref_block_prefix': 1944069745,
'schedule_version': 0,
'timestamp': '2018-06-09T12:09:21.500',
'transaction_mroot': '0000000000000000000000000000000000000000000000000000000000000000',
'transactions': []}
'''
from octopus.platforms.EOS.disassembler import EosDisassembler
file_name = "examples/EOS/samples/eos_ping.wasm"
with open(file_name, 'rb') as f: raw = f.read()
disasm = EosDisassembler()
text = disasm.disassemble_module(raw, r_format="text") print(text)
#### ModuleAnalyzer```python
from octopus.platforms.EOS.analyzer import EosAnalyzer
# complete wasm module
file_name = "examples/EOS/samples/eos_ping.wasm"
with open(file_name, 'rb') as f:
module_bytecode = f.read()
# return list of functions instructions (list)
# attributes analysis=True by default
analyzer = EosAnalyzer(module_bytecode)
# show analyzer attributes
print(analyzer.func_prototypes)
#[('action_data_size', '', 'i32', 'import'), ('eosio_assert', 'i32 i32', '', 'import'), ('eosio_exit', 'i32', '', 'import'), ('memcpy', 'i32 i32 i32', 'i32', 'import'), ('prints', 'i32', '', 'import'), ('read_action_data', 'i32 i32', 'i32', 'import'), ('require_auth2', 'i64 i64', '', 'import'), ('_ZeqRK11checksum256S1_', 'i32 i32', 'i32', 'export'), ('_ZN5eosio12require_authERKNS_16permission_levelE', 'i32', '', 'export'), ('apply', 'i64 i64 i64', '', 'export'), ('$func10', 'i32 i64', '', 'local'), ('$func11', 'i32 i32', 'i32', 'local'), ('memcmp', 'i32 i32 i32', 'i32', 'export'), ('malloc', 'i32', 'i32', 'export'), ('$func14', 'i32 i32', 'i32', 'local'), ('$func15', 'i32', 'i32', 'local'), ('free', 'i32', '', 'export'), ('$func17', '', '', 'local')]
print()
print(analyzer.exports)
# [{'field_str': 'memory', 'kind': 2, 'index': 0}, {'field_str': '_ZeqRK11checksum256S1_', 'kind': 0, 'index': 7}, {'field_str': '_ZN5eosio12require_authERKNS_16permission_levelE', 'kind': 0, 'index': 8}, {'field_str': 'apply', 'kind': 0, 'index': 9}, {'field_str': 'memcmp', 'kind': 0, 'index': 12}, {'field_str': 'malloc', 'kind': 0, 'index': 13}, {'field_str': 'free', 'kind': 0, 'index': 16}]
print()
print(analyzer.imports_func)
# [('env', 'action_data_size', 3), ('env', 'eosio_assert', 5), ('env', 'eosio_exit', 2), ('env', 'memcpy', 6), ('env', 'prints', 2), ('env', 'read_action_data', 4), ('env', 'require_auth2', 1)]
from octopus.platforms.EOS.cfg import EosCFG from octopus.analysis.graph import CFGGraph
file_name = "examples/EOS/samples/eos_ping.wasm"
with open(file_name, 'rb') as f: raw = f.read()
cfg = EosCFG(raw)
graph = CFGGraph(cfg) graph.view_functions()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/18a84dcc6e2fd330c93192f2c9850ddacec3981e2d3f1f0c6eae676791ad0bec.png"/>
</p>
#### Analyse du flux d'appels```python
from octopus.platforms.EOS.cfg import EosCFG
# complete wasm module
file_name = "examples/EOS/samples/eos_ping.wasm"
# read file
with open(file_name, 'rb') as f:
raw = f.read()
# create the cfg
cfg = EosCFG(raw)
# visualize
cfg.visualize_call_flow()
from octopus.platforms.EOS.cfg import EosCFG
file_name = "examples/EOS/samples/eos_ping.wasm"
with open(file_name, 'rb') as f: raw = f.read()
cfg = EosCFG(raw)
cfg.visualize_instrs_per_funcs()
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/6916/c5b52a71702f65f6edc5be98fa1683679313c3be85aaf86202d68c5bad9205f9.png"/>
</p>
</p>
</details>
<details><summary>Bitcoin</summary>
<p>
#### Explorateur```python
from octopus.platforms.BTC.explorer import BitcoinExplorerRPC
RPC_USER = 'test'
RPC_PASSWORD = 'test'
RPC_HOST = 'localhost'
host = '%s:%s@%s' % (RPC_USER, RPC_PASSWORD, RPC_HOST)
explorer = BitcoinExplorerRPC(host)
explorer.getbestblockhash()
# '00000000000000000012085cfe8c79bcdacf81fbd82f6ab52c3cb3a454d4987c'
explorer.getblockcount()
#550859
from octopus.platforms.BTC.disassembler import BitcoinDisassembler
file_name = "examples/BTC/witness_script.hex"
with open(file_name) as f: bytecode = f.read()
disasm = BitcoinDisassembler()
print(disasm.disassemble(bytecode, r_format='text'))
</p>
</details>
Veuillez trouver des exemples dans le dossier [examples](https://github.com/fuzzinglabs/octopus/blob/master/examples).
## Publications et Vidéos
* BLACKALPS 2018 [Recherche de rétro-ingénierie et de vulnérabilités des contrats intelligents Ethereum](https://www.blackalps.ch/ba-18/talks.php#111)
* Devcon iv. [Rétro-ingénierie des contrats intelligents Ethereum pour découvrir ce qui se cache derrière le bytecode EVM](https://guidebook.com/guide/117233/event/21956134/)
* hack.lu 2018 [Recherche de rétro-ingénierie et de vulnérabilités des contrats intelligents Ethereum](https://2018.hack.lu/talks/#Reversing+and+Vulnerability+research+of+Ethereum+Smart+Contracts)
* ToorCon XX - 2018 [Rétro-ingénierie des contrats intelligents Ethereum (Introduction)](https://frab.toorcon.net/en/toorcon20/public/events/97)
* ToorCon XX - 2018 [Dissection d'un module WebAssembly](https://frab.toorcon.net/en/toorcon20/public/events/92)
* REcon Montreal 2018 : [Rétro-ingénierie des contrats intelligents blockchain](https://recon.cx/2018/montreal/schedule/system/event_attachments/attachments/000/000/053/original/RECON-MTL-2018-Reversing_blockchains_smart_contracts.pdf)
## Auteurs
**Patrick Ventuzelo** - *Créateur* - [@Pat_Ventuzelo](https://twitter.com/pat_ventuzelo)
Voir aussi la liste des [contributeurs](https://github.com/quoscient/octopus/contributors) qui ont participé à ce projet.
## Licence
Ce projet est sous licence MIT - voir le fichier [LICENSE](https://github.com/fuzzinglabs/octopus/blob/master/LICENSE) pour plus de détails.
## Remerciements
Sponsor :
* [QuoScient](https://www.quoscient.io/)
Inspiré par :
* [Manticore](https://github.com/trailofbits/manticore)
* [Mythril](https://github.com/ConsenSys/mythril)
* [Rattle](https://github.com/trailofbits/rattle)
* [ethersplay](https://github.com/trailofbits/ethersplay)
* ...
# Formations et Contact
Patrick Ventuzelo - [@pat_ventuzelo](https://twitter.com/pat_ventuzelo)
* Chercheur en sécurité indépendant / Formateur.
* Cours en ligne GRATUITS : [ici](https://academy.fuzzinglabs.com/)