{"id":13631981,"url":"https://github.com/FuzzingLabs/octopus","last_synced_at":"2025-04-18T01:32:19.825Z","repository":{"id":38177181,"uuid":"137232093","full_name":"FuzzingLabs/octopus","owner":"FuzzingLabs","description":"Security Analysis tool for WebAssembly module (wasm) and Blockchain Smart Contracts (BTC/ETH/NEO/EOS)","archived":true,"fork":false,"pushed_at":"2023-11-24T18:39:20.000Z","size":5640,"stargazers_count":475,"open_issues_count":13,"forks_count":82,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-04-12T14:12:31.236Z","etag":null,"topics":["blockchain","call-flow-analysis","control-flow-analysis","disassembler","eos","ethereum","evm-bytecode","neo","security","security-analysis","smart-contracts","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://fuzzinglabs.com/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FuzzingLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["pventuzelo"]}},"created_at":"2018-06-13T15:06:12.000Z","updated_at":"2024-03-25T11:00:19.000Z","dependencies_parsed_at":"2024-01-24T04:12:16.012Z","dependency_job_id":"8be29c76-d692-43f7-9445-bcbe4bf0dd9d","html_url":"https://github.com/FuzzingLabs/octopus","commit_stats":{"total_commits":229,"total_committers":10,"mean_commits":22.9,"dds":"0.15283842794759828","last_synced_commit":"e8b8c5a9d5f6d9c63605afe9ef1528ab481ec983"},"previous_names":["pventuzelo/octopus"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuzzingLabs%2Foctopus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuzzingLabs%2Foctopus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuzzingLabs%2Foctopus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuzzingLabs%2Foctopus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FuzzingLabs","download_url":"https://codeload.github.com/FuzzingLabs/octopus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223502362,"owners_count":17155938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","call-flow-analysis","control-flow-analysis","disassembler","eos","ethereum","evm-bytecode","neo","security","security-analysis","smart-contracts","wasm","webassembly"],"created_at":"2024-08-01T22:02:47.038Z","updated_at":"2024-11-09T00:30:30.690Z","avatar_url":"https://github.com/FuzzingLabs.png","language":"Python","funding_links":["https://github.com/sponsors/pventuzelo"],"categories":["Python","dApps directory","\u003ca name=\"tools\"\u003e\u003c/a\u003e Tools"],"sub_categories":["Blockchain Security Tools","\u003ca name=\"sast\"\u003e SAST/DAST/Unity Test Analysis"],"readme":"# Octopus\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"/images/logo-medium.png\" height=\"300px\"/\u003e\n\u003c/p\u003e\n\n[![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/)\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nHuge thanks to [QuoScient](https://www.quoscient.io/) for having sponsored this project.\n\n**Octopus is a security analysis framework for WebAssembly module and Blockchain Smart Contract.**\n\nThe purpose of Octopus is to provide an easy way to analyze closed-source WebAssembly module and smart contracts bytecode to understand deeper their internal behaviours.\n\n\n## Features\n\n- **Explorer**: Octopus JSON-RPC client implementation to communicate with blockchain platforms\n- **Disassembler**: Octopus can translate bytecode into assembly representation\n- **Control Flow Analysis**: Octopus can generate a Control Flow Graph (CFG) \n- **Call Flow Analysis**: Octopus can generate a Call Flow Graph (function level) \n- **IR conversion (SSA)**: Octopus can simplify assembly into Static Single Assignment (SSA) representation\n- **Symbolic Execution**: Octopus use symbolic execution to find new paths into a program\n\n## Platforms / Architectures\n\nOctopus support the following types of programs/smart contracts:\n* WebAssembly module (WASM)\n* Bitcoin script (BTC script)\n* Ethereum smart contracts (EVM bytecode \u0026 Ewasm)\n* EOS smart contracts (WASM)\n* NEO smart contracts (AVM bytecode)\n\n\n|| BTC | ETH (EVM) | ETH (WASM) | EOS | NEO || WASM |\n|:--------------------:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n| **Explorer** | :heavy_check_mark: | :heavy_check_mark:| :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :o: |\n|**Disassembler** | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: |\n|**Control Flow Analysis** | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :heavy_check_mark: |\n|**Call Flow Analysis** | :heavy_multiplication_x: | :heavy_plus_sign: | :heavy_check_mark: | :heavy_check_mark: | :heavy_plus_sign: | | :heavy_check_mark: |\n|**IR conversion (SSA)** | :heavy_multiplication_x: | :heavy_check_mark: | :heavy_plus_sign: | :heavy_plus_sign: | :heavy_multiplication_x: | | :heavy_check_mark: |\n|**Symbolic Execution** | :heavy_multiplication_x: | :heavy_plus_sign: | :heavy_plus_sign: | :heavy_plus_sign: | :heavy_multiplication_x: | | :heavy_plus_sign: |\n\n\n* PyPI package :heavy_check_mark:\n* Docker :heavy_check_mark:\n\n:heavy_check_mark: **DONE** / :heavy_plus_sign: **WIP** / :heavy_multiplication_x: **TODO** / :o: **N/A**\n\n\n## Requirements\n\nOctopus is supported on Linux (ideally Ubuntu 16.04) and requires Python \u003e=3.5 (ideally 3.6).\n\nDependencies:\n* Graph generation: [graphviz](https://graphviz.gitlab.io/download/)\n* Explorer: [requests](http://docs.python-requests.org/en/master/#)\n* Symbolic Execution: [z3-solver](https://pypi.org/project/z3-solver/)\n* Wasm: [wasm](https://github.com/athre0z/wasm)\n\n## Quick Start\n\n- Install system dependencies\n```\n# Install system dependencies\nsudo apt-get update \u0026\u0026 sudo apt-get install python-pip graphviz xdg-utils -y\n```\n\n- Install Octopus:\n```\n# Download Octopus\ngit clone https://github.com/pventuzelo/octopus\ncd octopus\n\n# Install Octopus library/CLI and its dependencies\npython3 setup.py install\n```\nor\n```\n# but prefer the first way to install if possible\npip3 install octopus\n```\n\n- Run tests\n```\n# Run tests for all platforms (disassembly, CFG, ...)\n./run_tests.sh\n# Run tests that require internet access (explorer tests)\n./run_explorer_tests.sh\n\n# Run tests for only one platforms\n# {btc, eth, eos, neo, wasm}_run_tests.sh\ncd octopus/tests/\n./wasm_run_tests.sh\n```\n\n#### Docker container\n\nA docker container providing the toolset is available at [docker hub](https://hub.docker.com/r/smartbugs/octopus). \nIn a terminal, run the following commands:\n\n```\ndocker pull smartbugs/octopus\ndocker run -it smartbugs/octopus\ncd octopus\npython3 octopus_eth_evm.py -s -f examples/ETH/evm_bytecode/61EDCDf5bb737ADffE5043706e7C5bb1f1a56eEA.bytecode\n```\n\n## Command-line tools\n\n* WebAssembly: [octopus_wasm.py](octopus_wasm.py)\n* Ethereum (EVM): [octopus_eth_evm.py](octopus_eth_evm.py)\n\n\n## In-depth Examples using APIs\n\n\u003cdetails\u003e\u003csummary\u003eWebAssembly\u003c/summary\u003e\n\u003cp\u003e\n\n#### Disassembler\n\nDisassembly of a Wasm module:\n```python\nfrom octopus.arch.wasm.disassembler import WasmDisassembler\n\nFILE = \"examples/wasm/samples/helloworld.wasm\"\n\nwith open(FILE, 'rb') as f:\n    module_bytecode = f.read()\n\ndisasm = WasmDisassembler()\n# return list of functions instructions (list)\nprint(disasm.disassemble_module(module_bytecode))\n#[[\u003coctopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904278\u003e,\u003coctopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904f60\u003e,\u003coctopus.arch.wasm.instruction.WasmInstruction at 0x7f85e4904ef0\u003e]]\n\nprint()\n# return text of functions code\nprint(disasm.disassemble_module(module_bytecode, r_format='text'))\n# func 0\n# i32.const 0\n# call 0\n# end\n```\n\nDisassembly of wasm bytecode:\n```python\nfrom octopus.arch.wasm.disassembler import WasmDisassembler\n\n# bytecode in WebAssembly is the function code (i.e. function body)\nbytecode = b'\\x02\\x7fA\\x18\\x10\\x1cA\\x00\\x0f\\x0b'\n# create a WasmDisassembler object\ndisasm = WasmDisassembler(bytecode)\n\n# disassemble bytecode into a list of WasmInstruction\n# attributes r_format='list' by default\nprint(disasm.disassemble())\n\n#[\u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904eb8\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048\u003e]\nprint()\nprint(disasm.disassemble(r_format='reverse'))\n\n#{0: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048\u003e, 1: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904240\u003e, 2: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60\u003e, 3: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0\u003e, 4: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278\u003e, 5: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390\u003e}\nprint()\nprint(disasm.disassemble(r_format='text'))\n# block -1\n# i32.const 24\n# call 28\n# i32.const 0\n# return\n# end\n```\n\n#### ModuleAnalyzer\n\n```python\nfrom octopus.arch.wasm.analyzer import WasmModuleAnalyzer\n\nFILE = \"examples/wasm/samples/hello_wasm_studio.wasm\"\n\nwith open(FILE, 'rb') as f:\n    module_bytecode = f.read()\n\n# return list of functions instructions (list)\n# attributes analysis=True by default\nanalyzer = WasmModuleAnalyzer(module_bytecode)\n\n# show analyzer attributes\nprint(analyzer.func_prototypes)\n# [('putc_js', 'i32', ''),\n#  ('__syscall0', 'i32', 'i32'),\n#  ('__syscall3', 'i32 i32 i32 i32', 'i32'),\n#  ('__syscall1', 'i32 i32', 'i32'),\n#  ('__syscall5', 'i32 i32 i32 i32 i32 i32', 'i32'),\n#  ('__syscall4', 'i32 i32 i32 i32 i32', 'i32'),\n#  ('$func6', '', ''),\n#  ('main', '', 'i32'),\n#  ('writev_c', 'i32 i32 i32', 'i32'),\n#  ('$func9', '', 'i32'),\n#  ('$func10', 'i32', 'i32'),\n#  ('$func11', 'i32', 'i32'),\n#  ('$func12', 'i32', ''),\n#  ('$func13', 'i32', 'i32'),\n#  ('$func14', 'i32 i32 i32 i32', 'i32'),\n#  ('$func15', 'i32 i32', 'i32'),\n#  ('$func16', 'i32 i32', 'i32'),\n#  ('$func17', 'i32', 'i32'),\n#  ('$func18', 'i32', 'i32'),\n#  ('$func19', 'i32', 'i32'),\n#  ('$func20', 'i32 i32 i32', 'i32'),\n#  ('$func21', 'i32 i32 i32', 'i32'),\n#  ('$func22', 'i32 i64 i32', 'i64'),\n#  ('$func23', 'i32 i32 i32', 'i32'),\n#  ('$func24', 'i32', 'i32'),\n#  ('$func25', 'i32 i32 i32 i32', '')]\nprint()\nprint(analyzer.contains_emscripten_syscalls())\n#[('__syscall0', 'restart_syscall'),\n# ('__syscall3', 'read'),\n# ('__syscall1', 'exit'),\n# ('__syscall5', 'open'),\n# ('__syscall4', 'write')]\n```\n\n#### Control Flow Analysis\n\n```python\nfrom octopus.arch.wasm.cfg import WasmCFG\n\n# complete wasm module\nfile_name = \"examples/wasm/samples/fib.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = WasmCFG(raw)\n\n# visualize CFGGraph \n# generate graph.dot and graph.pdf file\ncfg.visualize()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/wasm-cfg-fib.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n\n#### Functions' instructions analytics\n\n```python\nfrom octopus.arch.wasm.cfg import WasmCFG\n\n# complete wasm module\nfile_name = \"examples/wasm/samples/hello_wasm_studio.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = WasmCFG(raw)\n\n# visualization\ncfg.visualize_instrs_per_funcs()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/wasm-instr-func-analytics.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n#### Call Flow Analysis\n\n```python\nfrom octopus.arch.wasm.cfg import WasmCFG\n\n# fibonacci wasm module\nfile_name = \"examples/wasm/samples/hello_wasm_studio.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = WasmCFG(raw)\n\n# visualize Call Flow Graph\n# generate call_graph.dot and call_graph.pdf file\n# \n# color similar to https://webassembly.studio/\n# imported func == turquoise / exported func == grey\n# edge label = number of different calls to the function\ncfg.visualize_call_flow()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/wasm-callflow-hello-studio.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\nLegend:  \n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/legend_callgraph.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n#### IR conversion (SSA)\n\n```python\nfrom octopus.arch.wasm.emulator import WasmSSAEmulatorEngine\n\n# complete wasm module\nfile_name = \"examples/wasm/samples/fib.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n\n# run the emulator for SSA\nemul = WasmSSAEmulatorEngine(raw)\nemul.emulate_one_function('fib')\n# or emul.emulate_functions(['fib'])\n# or emul.emulate_functions() # emulate all the function\n\n# visualization of the cfg with SSA\nemul.cfg.visualize(ssa=True)\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/ssa-cfg-fib-wasm.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eEthereum (ETH) - EVM\u003c/summary\u003e\n\u003cp\u003e\n\n#### Explorer\n\n```python\nfrom octopus.platforms.ETH.explorer import EthereumInfuraExplorer\nfrom octopus.platforms.ETH.explorer import INFURA_ROPSTEN\n\nKEY_API = \"bHuaQhX91nkQBac8Wtgj\"\n# connection to ROPSTEN network (testnet)\nexplorer = EthereumInfuraExplorer(KEY_API, network=INFURA_ROPSTEN)\n\n# connection to MAINNET network (mainnet)\n# explorer = EthereumInfuraExplorer(KEY_API)\n\n# Test ROPSTEN network current block number\nblock_number = explorer.eth_blockNumber()\nprint(block_number)\n# 3675552\n\n# Retrieve code of this smart contract\naddr = \"0x3c6B10a5239B1a8A27398583F49771485382818F\"\ncode = explorer.eth_getCode(addr)\nprint(code)\n# 0x6060604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c14606e575b600080fd5b3415605857600080fd5b606c60048080359060200190919050506094565b005b3415607857600080fd5b607e609e565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820e1f98c821c12eea52047d7324b034ddccc41eaa7365d369b34580ab73c71a8940029\n```\n\n#### Disassembler\n\n```python\nfrom octopus.platforms.ETH.disassembler import EthereumDisassembler\n\n# smart contract bytecode\nbytecode_hex = \"60606040526000357c0100000000000000000000000000000000000000000000000000000000900480635fd8c7101461004f578063c0e317fb1461005e578063f8b2cb4f1461006d5761004d565b005b61005c6004805050610099565b005b61006b600480505061013e565b005b610083600480803590602001909190505061017d565b6040518082815260200191505060405180910390f35b3373ffffffffffffffffffffffffffffffffffffffff16611111600060005060003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060005054604051809050600060405180830381858888f19350505050151561010657610002565b6000600060005060003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050819055505b565b34600060005060003373ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055505b565b6000600060005060008373ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000505490506101b6565b91905056\"\n\ndisasm = EthereumDisassembler()\ndisasm.disassemble(bytecode_hex)\n\n# disassemble bytecode into a list of EthereumInstruction\n# attributes r_format='list' by default\nprint(disasm.disassemble(bytecode_hex))\n\n#[\u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4add5c0\u003e, \u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8588\u003e, \u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8c50\u003e]\n\nprint()\nprint(disasm.disassemble(bytecode_hex, r_format='reverse'))\n\n# {0: \u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8160\u003e, ..., 229: \u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad8630\u003e, 230: \u003coctopus.platforms.ETH.instruction.EthereumInstruction object at 0x7f85d4ad87b8\u003e}\n\nprint()\nprint(disasm.disassemble(bytecode_hex,r_format='text'))\n# PUSH1 0x60\n# PUSH1 0x40\n# MSTORE\n# PUSH1 0x0\n# CALLDATALOAD\n# PUSH29 0x100000000000000000000000000000000000000000000000000000000\n# SWAP1\n# DIV\n# DUP1\n# PUSH4 0x5fd8c710\n# EQ\n# PUSH2 0x4f\n# JUMPI\n# ...\n# SWAP2\n# SWAP1\n# POP\n# JUMP\n```\n\n#### Control Flow Analysis\n\n```python\nfrom octopus.analysis.graph import CFGGraph\nfrom octopus.platforms.ETH.cfg import EthereumCFG\n\n# ethernaut0 bytecode\nfile_name = \"examples/ETH/evm_bytecode/Zeppelin_Hello_ethernaut0.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode_hex = f.read()\n\n# create the CFG\ncfg = EthereumCFG(bytecode_hex)\n\n\n# generic visualization api\n# generate graph.dot and graph.pdf file\ngraph = CFGGraph(cfg)\ngraph.view()\n# or directly using the cfg binding\n# cfg.visualize()\n# and you can get a simplify cfg representation using\n# cfg.visualize(simplify=True) or graph.view(simplify=True)\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eth-cfg-evm.png\"/\u003e\n\u003c/p\u003e\n\n#### IR conversion (SSA)\n\n```python\n# The conversion to SSA is already done by the SSAEmulator\n# when the CFG is reconstruct\n# by default you have just to visualize it\nfrom octopus.platforms.ETH.cfg import EthereumCFG\n\n# ethernaut0 bytecode\nfile_name = \"examples/ETH/evm_bytecode/Zeppelin_Hello_ethernaut0.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode_hex = f.read()\n\n# create the CFG\ncfg = EthereumCFG(bytecode_hex)\n\n# SSA visualization\ncfg.visualize(ssa=True)\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eth-cfg-evm-ssa.png\"/\u003e\n\u003c/p\u003e\n\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eEthereum (WASM)\u003c/summary\u003e\n\u003cp\u003e\n\n#### Explorer\n\n```python\nfrom octopus.platforms.ETH.explorer import EthereumInfuraExplorer\nfrom octopus.platforms.ETH.explorer import INFURA_KOVAN\n\n# connection to ROPSTEN network (testnet)\nexplorer = EthereumInfuraExplorer(\"bHuaQhX91nkQBac8Wtgj\",\n                                  network=INFURA_KOVAN)\n# connection to MAINNET network (mainnet)\n# explorer = EthereumInfuraExplorer(\"bHuaQhX91nkQBac8Wtgj\")\n\n# test infura access\nblock_number = explorer.eth_blockNumber()\nprint('blockNumber = %d' % block_number)\n\n# retrieve code of this smart contract\naddr = \"0x1120e596b173d953ba52ce262f73ce3734b0e40e\"\ncode = explorer.eth_getCode(addr)\nprint()\nprint(code)\n# blockNumber = 8803487\n# \n# 0x0061736d0100000001090260000060027f7f00021a0203656e7603726574000103656e76066d656d6f7279020102100303020000040501700101010501000601000708010463616c6c00010a120205001002000b0a00418008410b1000000b0b1201004180080b0b48656c6c6f20776f726c64000b076c696e6b696e6703010b0066046e616d65015f060003726574010570616e6963020463616c6c032f5f5a4e3134707761736d5f657468657265756d3365787433726574313768363034643830393864313638366338304504066465706c6f790511727573745f626567696e5f756e77696e64\n```\n\n#### Disassembler\n\nDisassembly of a Wasm module:\n```python\nfrom octopus.platforms.ETH.disassembler import EthereumDisassembler\n\nFILE = \"examples/ETH/wasm/helloworld_kovan.bytecode\"\n\nwith open(FILE, 'r') as f:\n    module_bytecode = f.read()\n\ndisasm = EthereumDisassembler(arch='wasm')\n# return list of functions instructions (list)\nprint(disasm.disassemble_module(module_bytecode))\n#[[\u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa898\u003e], [\u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa7b8\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa780\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa748\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa6d8\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7efc0ceaa710\u003e]]\n\nprint()\n# return text of functions code\nprint(disasm.disassemble_module(module_bytecode, r_format='text'))\n# func 0\n# end\n# \n# func 1\n# call 1\n# i32.const 1036\n# i32.const 232\n# call 0\n# end\n\n```\n\nDisassembly of wasm bytecode:\n```python\nfrom octopus.platforms.ETH.disassembler import EthereumDisassembler\n\n# bytecode in WebAssembly is the function code (i.e. function body)\nbytecode = b'\\x02\\x7fA\\x18\\x10\\x1cA\\x00\\x0f\\x0b'\n# create a WasmDisassembler object\ndisasm = EthereumDisassembler(bytecode, arch='wasm')\n\n# disassemble bytecode into a list of WasmInstruction\n# attributes r_format='list' by default\nprint(disasm.disassemble())\n\n#[\u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904eb8\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60\u003e, \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048\u003e]\nprint()\nprint(disasm.disassemble(r_format='reverse'))\n\n#{0: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4901048\u003e, 1: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904240\u003e, 2: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904f60\u003e, 3: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904ef0\u003e, 4: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904278\u003e, 5: \u003coctopus.arch.wasm.instruction.WasmInstruction object at 0x7f85e4904390\u003e}\nprint()\nprint(disasm.disassemble(r_format='text'))\n# block -1\n# i32.const 24\n# call 28\n# i32.const 0\n# return\n# end\n```\n\n#### ModuleAnalyzer\n\n```python\nfrom octopus.arch.wasm.analyzer import WasmModuleAnalyzer\n\nFILE = \"examples/ETH/wasm/helloworld_kovan.bytecode\"\n\nwith open(FILE, 'r') as f:\n    module_bytecode = f.read()\n\n# return list of functions instructions (list)\n# attributes analysis=True by default\nanalyzer = WasmModuleAnalyzer(module_bytecode)\n\n# show analyzer attributes\nprint(analyzer.func_prototypes)\n# [('ret', 'i32 i32', '', 'import'), ('$func1', '', '', 'local'), ('call', '', '', 'export')]\nprint()\nprint(analyzer.exports)\n# [{'field_str': 'call', 'kind': 0, 'index': 2}]\nprint()\nprint(analyzer.imports_func)\n# [('env', 'ret', 1)]\nprint()\nprint(analyzer.datas)\n# [{'data': b'Hello world', 'index': 0, 'offset': None, 'size': 11},\n# {'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',\n# 'index': 0,\n# 'offset': None,\n# 'size': 232}]\n\n```\n\n#### Control Flow Analysis\n\n```python\nfrom octopus.platforms.ETH.cfg import EthereumCFG\n\n# HelloWorld on Kovan Parity Network\nfile_name = \"examples/ETH/wasm/helloworld_kovan.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode_hex = f.read()\n\n# create the CFG\ncfg = EthereumCFG(bytecode_hex, arch='wasm')\ncfg.visualize()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eth-wasm-cfg-hello-parity.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n#### Functions' instructions analytics\n\n```python\nfrom octopus.platforms.ETH.cfg import EthereumCFG\n\n# HelloWorld on Kovan Parity Network\nfile_name = \"examples/ETH/wasm/helloworld_kovan.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode_hex = f.read()\n\n# create the CFG\ncfg = EthereumCFG(bytecode_hex, arch='wasm')\n\n# visualization\ncfg.visualize_instrs_per_funcs()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eth-wasm-func-analytics.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n#### Call Flow Analysis\n\n```python\nfrom octopus.platforms.ETH.cfg import EthereumCFG\n\n# HelloWorld on Kovan Parity Network\nfile_name = \"examples/ETH/wasm/helloworld_kovan.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode_hex = f.read()\n\n# create the CFG\ncfg = EthereumCFG(bytecode_hex, arch='wasm')\n\n# visualization\ncfg.visualize_call_flow()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eth-wasm-callflow-hello-parity.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\nLegend:  \n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/legend_callgraph.png\" height=\"400px\"/\u003e\n\u003c/p\u003e\n\n\n#### IR conversion (SSA)\n\n```python\n# TODO\n```\n\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eNEO\u003c/summary\u003e\n\u003cp\u003e\n\n#### Explorer\n\n```python\nfrom octopus.platforms.NEO.explorer import NeoExplorerRPC\n\n# get list nodes here: http://monitor.cityofzion.io/\nexplorer = NeoExplorerRPC(host='seed2.neo.org')\n\n# get current number of block on the blockchain\nprint(explorer.getblockcount())\n# 2534868\n\n# get information on a contract\n# lock smart contract address: d3cce84d0800172d09c88ccad61130611bd047a4\ncontract = explorer.getcontractstate(\"d3cce84d0800172d09c88ccad61130611bd047a4\")\nprint(contract)\n# {'author': 'Erik Zhang',\n# 'code_version': '2.0',\n# 'description': 'Lock 2.0',\n# 'email': 'erik@neo.org',\n# 'hash': '0xd3cce84d0800172d09c88ccad61130611bd047a4',\n# 'name': 'Lock',\n# 'parameters': ['Integer', 'PublicKey', 'Signature'],\n# 'properties': {'dynamic_invoke': False, 'storage': False},\n# 'returntype': 'Boolean',\n# 'script': '56c56b6c766b00527ac46c766b51527ac46c766b52527ac4616168184e656f2e426c6f636b636861696e2e4765744865696768746168184e656f2e426c6f636b636861696e2e4765744865616465726c766b53527ac46c766b00c36c766b53c36168174e656f2e4865616465722e47657454696d657374616d70a06c766b54527ac46c766b54c3640e00006c766b55527ac4621a006c766b51c36c766b52c3617cac6c766b55527ac46203006c766b55c3616c7566',\n# 'version': 0}\n\n# smart contract code in contract['script']\nprint(contract['script'])\n```\n\n#### Disassembler\n\n```python\nfrom octopus.platforms.NEO.disassembler import NeoDisassembler\n\n# lock contract\nfile_name = \"examples/NEO/samples/Lock.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    bytecode = f.read()\n\ndisasm = NeoDisassembler()\n\nprint(disasm.disassemble(bytecode, r_format='text'))\n# PUSH6\n# NEWARRAY\n# TOALTSTACK\n# FROMALTSTACK\n# DUP\n# TOALTSTACK\n# PUSH0\n# PUSH2\n# ROLL\n# SETITEM\n# FROMALTSTACK\n# ....\n# PICKITEM\n# NOP\n# FROMALTSTACK\n# DROP\n# RET\n```\n\n#### Control Flow Analysis\n\n```python\nfrom octopus.analysis.graph import CFGGraph\nfrom octopus.platforms.NEO.cfg import NeoCFG\n\n# lock contract\nfile_name = \"examples/NEO/samples/Lock.bytecode\"\n\n# read file\nwith open(file_name) as f:\n    raw = f.read()\n\n# create neo cfg - automatic static analysis\ncfg = NeoCFG(raw)\n\n# graph visualization\ngraph = CFGGraph(cfg, filename=\"Lock_cfg\")\ngraph.view_functions()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/neo-cfg.png\"/\u003e\n\u003c/p\u003e\n\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eEOS\u003c/summary\u003e\n\u003cp\u003e\n\n#### Explorer\n\n```python\nfrom octopus.platforms.EOS.explorer import EosExplorer\n\nhost = \"api.cypherglass.com\"\n\n# by defaul the port is 8888\nexplo = EosExplorer(host=host)\n\n# get info about the node\nexplo.get_info()\n\n'''\n{'block_cpu_limit': 180289,\n 'block_net_limit': 1045680,\n 'chain_id': 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906',\n 'head_block_id': '018d6e2bcf6295126cd74cf694b5cca3529eefc42b334b394ef87c3a43876739',\n 'head_block_num': 26045995,\n 'head_block_producer': 'eosswedenorg',\n 'head_block_time': '2018-11-09T14:11:29.500',\n 'last_irreversible_block_id': '018d6cdcff78bbd9f25c605b02fb67c47a337ece78ddcf73089cee4bf6a410ee',\n 'last_irreversible_block_num': 26045660,\n 'server_version': 'c71d2245',\n 'server_version_string': 'mainnet-1.3.0',\n 'virtual_block_cpu_limit': 38092879,\n 'virtual_block_net_limit': 1048576000}\n'''\nexplo.get_block(1337)\n\n'''\n{'action_mroot': 'bcb9763baa3bbf98ed36379b4be0ecb2d9cd21c75df01729c63b2b021001c10c',\n 'block_extensions': [],\n 'block_num': 1337,\n 'confirmed': 0,\n 'header_extensions': [],\n 'id': '00000539d17a03af7126e073be4c4d99a72b7f58793cf2c87b9bfd41b6c711fb',\n 'new_producers': None,\n 'previous': '00000538b374c1cbfaeed7253ad3075ddc72a28f0a0515301fc1bbed675f2316',\n 'producer': 'eosio',\n 'producer_signature': 'SIG_K1_K5jWf36t6j454Hb2fGuV37YTwMTvuQ51ZPBtpru8Ud2axtMTEauWyvtpJuTpnvqzReUndDgEDXvoeEP4jdj2bpnYKBt6g2',\n 'ref_block_prefix': 1944069745,\n 'schedule_version': 0,\n 'timestamp': '2018-06-09T12:09:21.500',\n 'transaction_mroot': '0000000000000000000000000000000000000000000000000000000000000000',\n 'transactions': []}\n'''\n```\n\n#### Disassembler\n\n```python\nfrom octopus.platforms.EOS.disassembler import EosDisassembler\n\n# complete wasm module\nfile_name = \"examples/EOS/samples/eos_ping.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# just disassembly\ndisasm = EosDisassembler()\n\n# because we provide full module bytecode\n# we need to use disassemble_module()\n# otherwise just disassemble() is enough\ntext = disasm.disassemble_module(raw, r_format=\"text\")\nprint(text)\n# func 0\n# get_local 0\n# get_local 1\n# i32.const 32\n# call 12\n# i32.eqz\n# end\n# \n# func 1\n# get_local 0\n# i64.load 3, 0\n# get_local 0\n# i64.load 3, 8\n# call 6\n# end\n# \n# func 2\n# ...\n# end\n# \n# ...\n```\n\n#### ModuleAnalyzer\n\n```python\n\nfrom octopus.platforms.EOS.analyzer import EosAnalyzer\n\n# complete wasm module\nfile_name = \"examples/EOS/samples/eos_ping.wasm\"\n\nwith open(file_name, 'rb') as f:\n    module_bytecode = f.read()\n\n# return list of functions instructions (list)\n# attributes analysis=True by default\nanalyzer = EosAnalyzer(module_bytecode)\n\n# show analyzer attributes\nprint(analyzer.func_prototypes)\n#[('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')]\nprint()\nprint(analyzer.exports)\n# [{'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}]\nprint()\nprint(analyzer.imports_func)\n# [('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)]\n```\n\n#### Control Flow Analysis\n\n```python\nfrom octopus.platforms.EOS.cfg import EosCFG\nfrom octopus.analysis.graph import CFGGraph\n\n# complete wasm module\nfile_name = \"examples/EOS/samples/eos_ping.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = EosCFG(raw)\n\n# visualize\ngraph = CFGGraph(cfg)\ngraph.view_functions()\n```\n\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eos-cfg.png\"/\u003e\n\u003c/p\u003e\n\n#### Call Flow Analysis\n\n```python\nfrom octopus.platforms.EOS.cfg import EosCFG\n\n# complete wasm module\nfile_name = \"examples/EOS/samples/eos_ping.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = EosCFG(raw)\n\n# visualize\ncfg.visualize_call_flow()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eos-callgraph.png\"/\u003e\n\u003c/p\u003e\n\n#### Functions' instructions analytics\n\n```python\nfrom octopus.platforms.EOS.cfg import EosCFG\n\n# complete wasm module\nfile_name = \"examples/EOS/samples/eos_ping.wasm\"\n\n# read file\nwith open(file_name, 'rb') as f:\n    raw = f.read()\n\n# create the cfg\ncfg = EosCFG(raw)\n\n# visualize\ncfg.visualize_instrs_per_funcs()\n```\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"/images/eos-func-instrucs.png\"/\u003e\n\u003c/p\u003e\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eBitcoin\u003c/summary\u003e\n\u003cp\u003e\n\n#### Explorer\n\n```python\nfrom octopus.platforms.BTC.explorer import BitcoinExplorerRPC\n\nRPC_USER = 'test'\nRPC_PASSWORD = 'test'\nRPC_HOST = 'localhost'\n\nhost = '%s:%s@%s' % (RPC_USER, RPC_PASSWORD, RPC_HOST)\n\nexplorer = BitcoinExplorerRPC(host)\n\nexplorer.getbestblockhash()\n# '00000000000000000012085cfe8c79bcdacf81fbd82f6ab52c3cb3a454d4987c'\n\nexplorer.getblockcount()\n#550859\n```\n\n#### Disassembler\n\n```python\nfrom octopus.platforms.BTC.disassembler import BitcoinDisassembler\n\n# Witness Script\nfile_name = \"examples/BTC/witness_script.hex\"\n\n# read file\nwith open(file_name) as f:\n    bytecode = f.read()\n\ndisasm = BitcoinDisassembler()\n\nprint(disasm.disassemble(bytecode, r_format='text'))\n# 0\n# OP_ROT\n# OP_ROT\n# 2\n# 0203f4d01d0b35588638631ebb7d46d8387fd1aeb3dbecfdd3faf7c056b023c833\n# 03aa6677e3ce1bd634f4f2e1cd60a60af002e1b30484d4d1611b183b16d391ee96\n# 03bf164811abb8c91ed39e58d4e307f86cb4e487c83f727a2c482bc71a0f96f1db\n# 3\n# OP_CHECKMULTISIG\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\nPlease find examples in [examples](examples) folder.\n\n## Publications and Videos\n\n* BLACKALPS 2018 [Reversing and Vulnerability research of Ethereum Smart Contracts](https://www.blackalps.ch/ba-18/talks.php#111)\n* Devcon iv. [Reversing Ethereum Smart Contracts to find out what's behind EVM bytecode](https://guidebook.com/guide/117233/event/21956134/)\n* hack.lu 2018 [Reversing and Vulnerability research of Ethereum Smart Contracts](https://2018.hack.lu/talks/#Reversing+and+Vulnerability+research+of+Ethereum+Smart+Contracts)\n* ToorCon XX - 2018 [Reversing Ethereum Smart Contracts (Introduction)](https://frab.toorcon.net/en/toorcon20/public/events/97)\n* ToorCon XX - 2018 [Dissection of WebAssembly module](https://frab.toorcon.net/en/toorcon20/public/events/92)\n* REcon Montreal 2018: [Reverse Engineering Of Blockchain Smart Contracts](https://recon.cx/2018/montreal/schedule/system/event_attachments/attachments/000/000/053/original/RECON-MTL-2018-Reversing_blockchains_smart_contracts.pdf)\n\n## Authors\n\n**Patrick Ventuzelo** - *Creator* - [@Pat_Ventuzelo](https://twitter.com/pat_ventuzelo)\n\nSee also the list of [contributors](https://github.com/quoscient/octopus/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n\n## Acknowledgments\n\nSponsor:\n* [QuoScient](https://www.quoscient.io/)\n\nInspired by:\n* [Manticore](https://github.com/trailofbits/manticore)\n* [Mythril](https://github.com/ConsenSys/mythril)\n* [Rattle](https://github.com/trailofbits/rattle)\n* [ethersplay](https://github.com/trailofbits/ethersplay)\n* ...\n\n# Trainings \u0026 Contact\n\nPatrick Ventuzelo - [@pat_ventuzelo](https://twitter.com/pat_ventuzelo)\n* Independent Security Researcher / Trainer.\n* FREE online courses: [here](https://academy.fuzzinglabs.com/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFuzzingLabs%2Foctopus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFuzzingLabs%2Foctopus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFuzzingLabs%2Foctopus/lists"}