SlideShare a Scribd company logo
Porosity
Decompiling Ethereum Smart-Contracts
Matt Suiche (@msuiche)
Founder, Comae Technologies
m@comae.io
Whoami
 @msuiche
 Comae Technologies
 OPCDE - www.opcde.com
 First time in Vegas since BlackHat 2011
 Mainly Windows-related stuff
 CloudVolumes (VMware App Volumes)
 Memory Forensics for DFIR (Hibr2Bin, DumpIt etc.)
 “looks like such fun guy” – TheShadowBrokers
 Didn’t know much about blockchain before this project
Just so you know…
 We won’t talk about POW/POS stuff
 We won’t talk about Merkle Trees
 We won’t talk about how to becoming a crypto-currency millionaire
 We will talk about the Ethereum EVM
 We will talk about Solidity
 We will talk about smart-contract bytecodes
 And yes, the tool isn’t perfect ☺
Agenda
 Ethereum Virtual Machine (EVM)
 Memory Management
 Addresses
 Call Types
 Type Discovery
 Smart-Contract
 Code Analysis
 Known Bugs
 Future
Solidity
 Solidity the quality or state of being firm or strong in
structure.
 But also the name of Ethereum’s smart-contracts compiler
 Porosity is the quality of being porous, or full of tiny holes.
Liquids go right through things that have porosity.
 But also the name of Comae’s smart-contract decompiler.
Accounts
 Normal Accounts: 3,488,419 (July 15)
 Contract Accounts: 930,889 (July 15)
 Verified Contract Accounts: 2285 (July 15)
 Source code is provided.
 40M$ lost in July
 10M$ in CoinDash’s ICO
 http://www.coindesk.com/coindash-ico-hacker-nets-additional-
ether-theft-tops-10-million/
 30M$ due to Parity’s wallet.sol vulnerability
 https://blog.parity.io/security-alert-high-2/
 https://github.com/paritytech/parity/pull/6103
Ethereum Virtual Machine (EVM)
 Account/Contract/Blockchain
 A Smart-Contract is made of bytecode stored in the blockchain.
 An address is a 160-bits value & corresponds to an “account”
 Operates 256-bits pseudo-registers
 EVM does not really have registers, but uses a virtual stack to replace them.
Solidity & “Smart Contracts”
 Solidity compiles JavaScript-like code into Ethereum bytecode.contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
Memory Management
 Stack
 Virtual stack is being used for operations to pass parameters to opcodes.
 256-bit values/entries
 Maximum size of 1024 elements
 Storage (Persistent)
 Key-value storage mapping (256-to-256-bit integers)
 Can’t be enumerated.
 SSTORE/SLOAD
 Memory (Volatile)
 256-bit values (lots of AND operations, useful for type discovery)
 MSTORE/MLOAD
Basic Blocks
 Usually start with the JUMPDEST instruction – except few cases.
 JUMP* instruction jump to the address contained in the 1st element
of the stack.
 JUMP* instruction are (almost always) preceded by PUSH instruction
 This allows to push the destination address in the stack, instead of
hardcoding the destination offset.
 SWAP/DUP/POP stack manipulation instructions can make jump
destination address harder to retrieve
 This requires dynamic analysis to rebuild the relationship between each
basic block.
EVM functions/instructions
 EVM instructions are more like functions, such as:
 Arithmetic, Comparison & Bitwise Logic Operations
 SHA3
 Environmental & Block Information
 Stack, Memory, Storage and Flow Operations
 Logging & System Operations
Instruction call - Addition
 The above translates at the EVM-pseudo code:
 add(0x2, 0x1)
Offset Instruction Stack[0] Stack[2]
n PUSH1 0x1 0x1
n + 1 PUSH1 0x2 0x2 0x1
n + 2 ADD 0x3
EVM Call
 Can be identified by the CALL instruction.
 Call external accounts/contracts pointed by the second
parameter
 The second parameter contains the actual 160 address of the
external contract
 With the exception of 4 hardcoded contracts:
 1 – elliptic curve public key recovery function
 2- SHA2 function
 3- RIPEMD160 function
 4- Identity function
call(
gasLimit,
to,
value,
inputOffset,
inputSize,
outputOffset,
outputSize
)
User-Defined functions (Solidity)
 CALLDATALOAD instruction is used to read the Environmental
Information Block (EIB) such as parameters.
 First 4 bytes of the EIB contains the 32-bits hash of the called
function.
 Followed by the parameters based on their respective types.
 e.g. int would be a 256 bits word.
 a = calldataload(0x4)
 b = calldataload(0x24)
 add(calldataload(0x4), calldataload(0x24)
function foo(int a, int b) {
return a + b;
}
Type Discovery - Addresses
 As an example, addresses are 160-bit words
 Since stack registers are 256-bit words, they can easily be identified
through AND operations using the
0xffffffffffffffffffffffffffffffffffffffff mask.
 Mask can be static or computed dynamically
Ethereum Assembly Translation (msg.sender)
CALLER
PUSH1 0x01
PUSH 0xA0
PUSH1 0x02
EXP
SUB
AND
and(reg256, sub(exp(2, 0xa0), 1)) (EVM)
reg256 & (2 ** 0xA0) - 1) (Intermediate)
address (Solidity)
Bytecode
 The bytecode is divided in two categories:
 Pre-loader code
 Found at the beginning that contains the routine to bootstrap
the contract
 Runtime code of the contract
 The core code written by the user that got compiled by
Solidity
 Each contract contain a dispatch function that redirects the
call to the corresponding function based on the provided
hash function.
Bytecode – Pre-loader
 CODECOPY copies the runtime part of the contract into the EVM
memory – which gets executed at base address 0x0
00000000 6060
00000002 6040
00000004 52
00000005 6000
00000007 6001
00000009 6000
0000000b 610001
0000000e 0a
0000000f 81
00000010 54
00000011 81
00000012 60ff
00000014 02
00000015 19
00000016 16
00000017 90
00000018 83
00000019 02
0000001a 17
0000001b 90
0000001c 55
0000001d 50
0000001e 61bb01
00000021 80
00000022 612b00
00000025 6000
00000027 39
00000028 6000
0000002a f3
PUSH1 60
PUSH1 40
MSTORE
PUSH1 00
PUSH1 01
PUSH1 00
PUSH2 0001
EXP
DUP2
SLOAD
DUP2
PUSH1 ff
MUL
NOT
AND
SWAP1
DUP4
MUL
OR
SWAP1
SSTORE
POP
PUSH2 bb01
DUP1
PUSH2 2b00
PUSH1 00
CODECOPY
PUSH1 00
RETURN
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
calldataload(0x0) / exp(0x2, 0xe0)
Function Hashes
 The 4 bytes of the sha3 (keccak256) value for the string
functionName(param1Type, param2Type, etc)
[
{
"constant":false,
"inputs":[{ "name":"a", "type":"uint256" }],
"name":"double",
"outputs":[{ "name":"", "type":"uint256" }],
"type":"function"
}
]
keccak256("double(uint256)") =>
eee972066698d890c32fec0edb38a360c32b71d0a29ffc75b6ab6d2774ec9901
double(uint256) -> 0xeee97206
triple(uint256) -> 0xf40a049d
Extracting function hash
 calldataload(0x0) / exp(0x2, 0xe0)
 (0x12345678xxxx / 0x00000001xxxx) = 0x12345678
 jumpi(eq(calldataload(0x0) / exp(0x2, 0xe0), 0xeee97206))
PS C:Program FilesGeth> .evm.exe 
--code 60e060020a60003504 
--debug 
--input 12345678aaaaaaaabbbbbbbbccccccccdddddddd
PC 00000009: STOP GAS: 9999999923 COST: 0
STACK = 1
0000: 0000000000000000000000000000000000000000000000000000000012345678
MEM = 0
STORAGE = 0
Ethereum Emulator
Static CFG (--cfg) Emulated CFG (--cfg-full)
Control Flow Graph
Dispatcher – pseudo code
hash = calldataload(0x0) / exp(0x2, 0xe0);
switch (hash) {
case 0xeee97206: // double(uint256)
memory[0x60] = calldataload(0x4) * 2;
return memory[0x60];
break;
case 0xf40a049d: // triple(uint256)
memory[0x60] = calldataload(0x4) * 3;
return memory[0x60];
break;
default:
// STOP
break;
}
contract C {
function double(int arg_4) {
return arg_4 * 2;
}
function triple(int arg_4) {
return arg_4 * 3;
}
}
Pseudo-Code
Translated Code
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
Bytecode – Dispatcher (--list)
loc_00000000:
0x00000000 60 60 PUSH1 60
0x00000002 60 40 PUSH1 40
0x00000004 52 MSTORE
0x00000005 60 e0 PUSH1 e0
0x00000007 60 02 PUSH1 02
0x00000009 0a EXP
0x0000000a 60 00 PUSH1 00
0x0000000c 35 CALLDATALOAD
0x0000000d 04 DIV
0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee
0x00000013 81 DUP2
0x00000014 14 EQ
0x00000015 60 24 PUSH1 24
0x00000017 57 JUMPI
loc_00000018:
0x00000018 80 DUP1
0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4
0x0000001e 14 EQ
0x0000001f 60 35 PUSH1 35
0x00000021 57 JUMPI
loc_00000022:
0x00000022 5b JUMPDEST
0x00000023 00 STOP
double(uint256):
0x00000024 5b JUMPDEST
0x00000025 60 45 PUSH1 45
0x00000027 60 04 PUSH1 04
0x00000029 35 CALLDATALOAD
0x0000002a 60 00 PUSH1 00
0x0000002c 60 4f PUSH1 4f
0x0000002e 82 DUP3
0x0000002f 60 02 PUSH1 02
loc_00000031:
0x00000031 5b JUMPDEST
0x00000032 02 MUL
0x00000033 90 SWAP1
0x00000034 56 JUMP
triple(uint256):
0x00000035 5b JUMPDEST
0x00000036 60 45 PUSH1 45
0x00000038 60 04 PUSH1 04
0x0000003a 35 CALLDATALOAD
0x0000003b 60 00 PUSH1 00
0x0000003d 60 4f PUSH1 4f
0x0000003f 82 DUP3
0x00000040 60 03 PUSH1 03
0x00000042 60 31 PUSH1 31
0x00000044 56 JUMP
DELEGATECALL & $30M Parity Bug
contract Wallet {
address _walletLibrary;
address owner;
// initWallet() is only invoked by the constructor. WalletLibrary is hardcoded.
function Wallet(address _owner) {
_walletLibrary = 0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3;
_walletLibrary.delegatecall(bytes4(sha3("initWallet(address)")), _owner);
}
(…)
// fallback function behaves like a “generic forward” (WTF?)
// Wallet.initWallet(attacker) becomes walletLibrary.initWallet(attacker)
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
Abusing the dispatcher to reinitialize a wallet?
Generic-Forward & Fall back functions
 Typical issue introduce by the lack of upgradeability of smart-
contract
 Software engineering is hard enough, but smart-contracts need to
be:
 Backward-Compatible
 Forward-Compatible
 Does not help to make the language verifiable.
 Fall back functions are undefined behaviors.
 Imagine if your kernel would behave like that.
 Scary, right ? Now, imagine if that’s your bank…
Fixing the initialization bug
- function initMultiowned(address[] _owners, uint _required) {
+ function initMultiowned(address[] _owners, uint _required) internal {
- function initDaylimit(uint _limit) {
+ function initDaylimit(uint _limit) internal {
+ modifier only_uninitialized { if (m_numOwners > 0) throw; _; }
- function initWallet(address[] _owners, uint _required, uint _daylimit) {
+ function initWallet(address[] _owners, uint _required, uint _daylimit)
only_uninitialized {
Code Analysis – Vulnerable Contract
contract SendBalance {
mapping ( address => uint ) userBalances ;
bool withdrawn = false ;
function getBalance (address u) constant returns ( uint ){
return userBalances [u];
}
function addToBalance () {
userBalances[msg.sender] += msg.value ;
}
function withdrawBalance (){
if (!(msg.sender.call.value(
userBalances [msg.sender])())) { throw ; }
userBalances [msg.sender] = 0;
}
}
Code Analysis – Vulnerable Contract
contract SendBalance {
mapping ( address => uint ) userBalances ;
bool withdrawn = false ;
function getBalance (address u) constant returns ( uint ){
return userBalances [u];
}
function addToBalance () {
userBalances[msg.sender] += msg.value ;
}
function withdrawBalance (){
if (!(msg.sender.call.value(
userBalances [msg.sender])())) { throw ; }
userBalances [msg.sender] = 0;
}
}
Caller contract can recall this function
using its fallback function
Understanding the control flow
 In the case of reentrant vulnerability, since we can
record the EVM state at each instruction using
porosity.
 We can track in which basic block SSTORE
instructions are called.
 userBalances [msg.sender] = 0;
 And track states for each basic block.
.demo.ps1
$porosity = 'E:projectsporosityDebugporosity.exe'
$abi =
'[{"constant":false,"inputs":[],"name":"withdrawBalance","outputs":[],"ty
pe":"function"},{"constant":false,"inputs":[],"name":"addToBalance","out
puts":[],"type":"function"},{"constant":true,"inputs":[{"name":"u","ty
pe":"address"}],"name":"getBalance","outputs":[{"name":"","type":"ui
nt256"}],"type":"function"}]'
$code =
'60606040526000357c01000000000000000000000000000000000000000000000000000000009004806
35fd8c7101461004f578063c0e317fb1461005e578063f8b2cb4f1461006d5761004d565b005b61005c6
004805050610099565b005b61006b600480505061013e565b005b6100836004808035906020019091905
05061017d565b6040518082815260200191505060405180910390f35b3373fffffffffffffffffffffff
fffffffffffffffff16611111600060005060003373ffffffffffffffffffffffffffffffffffffffff1
6815260200190815260200160002060005054604051809050600060405180830381858888f1935050505
0151561010657610002565b6000600060005060003373fffffffffffffffffffffffffffffffffffffff
f168152602001908152602001600020600050819055505b565b34600060005060003373fffffffffffff
fffffffffffffffffffffffffff168152602001908152602001600020600082828250540192505081905
5505b565b6000600060005060008373ffffffffffffffffffffffffffffffffffffffff1681526020019
081526020016000206000505490506101b6565b91905056’
& $porosity --abi $abi --runtime-code $code --decompile --verbose 0
A Decompiler for Blackhain-Based Smart Contracts Bytecode
Known class of bugs
 Reentrant Vulnerabilities / Race Condition
 Famously known because of the $50M USD DAO hack (2016) [8]
 Call Stack Vulnerabilities
 Got 1024 frames but a bug ain’t one – c.f. Least Authority [12]
 Time Dependency Vulnerabilities
 @mhswende blogposts are generally awesome, particularly the roulette
one [10]
 Unconditional DELEGATECALL
Porosity + Quorum = <3
 Quorum: Ethereum code fork created by J.P. Morgan
 aimed at enterprises that want to use a permissioned blockchain that adds
private smart contract execution & configurable consensus.
 Quorum now includes Porosity integrated directly into geth out of
the box:
 Scan private contracts sent to your node from other network participants
 Incorporate into security & patching processes for private networks with
formalized governance models
 Automate scanning and analyze risk across semi-public Quorum networks
 https://github.com/jpmorganchase/quorum
A Decompiler for Blackhain-Based Smart Contracts Bytecode
Future
 Ethereum DApps created a new segment for softwares.
 Porosity
 Improving support for conditional and loop statements
 Ethereum / Solidity & Security
 Fast growing community and more tools such as OYENTE or Porosity
 Personally, looking forward seeing the Underhanded Solidity Coding
Contest [10] results
 EVM vulnerabilities triggered by malicious bytecode? CLOUDBURST on the
blockchain
 More Blockchain VMs ?
 Swapping the EVM for Web Assembly (WASM) for 2018
Future - WebAssembly
 New Ethereum Roadmap (March 2017) mentions making the EVM
obsolete and replacing it with WebAssembly for 2018.
 “WebAssembly (or WASM) is a new, portable, size- and load-time-
efficient format.”
 WebAssembly is currently being designed as an open standard by a W3C
Community Group.
 WebAssembly defines an instruction set, intermediate source format
(WAST) and a binary encoded format (WASM).
 Major browser JavaScript engines will notably have native support for
WebAssembly – including V8, Chakra and Spidermonkey.
 https://github.com/ewasm/design
WASM + DApps + Blockchain
 C++ -> WASM is already a thing
 https://mbebenita.github.io/WasmExplorer/
 And a similar thing is planned for eWASM
Acknowledgements
 Mohamed Saher
 Halvar Flake
 DEFCON Review Board Team
 Max Vorobjov & Andrey Bazhan
 Martin H. Swende
 Gavin Wood
 Andreas Olofsson
References
[1] Woods, Gavin. "Ethereum: A Secure Decentralised Generalised Transaction Ledger." Web. https://github.com/ethereum/yellowpaper.pdf
[2] Olofsson, Andreas. "Solidity Workshop." Web. https://github.com/androlo/solidity-workshop
[3] Olofsson, Andreas. "Solidity Contracts." Web. https://github.com/androlo/standard-contracts
[4] Velner, Yarn, Jason Teutsch, and Loi Luu. "Smart Contracts Make Bitcoin Mining Pools Vulnerable." Web. https://eprint.iacr.org/2017/230.pdf
[5] Luu, Loi, Duc-Hiep Chu, Hrishi Olickel, Aquinas Hobor. "Making Smart Contracts Smarter." Web.
https://www.comp.nus.edu.sg/%7Ehobor/Publications/2016/Making%20Smart%20Contracts%20Smarter.pdf
[6] Atzei, Nicola, Massimo Bartoletti, and Tiziana Cimoli. " A Survey of Attacks on Ethereum Smart Contracts." Web.
https://eprint.iacr.org/2016/1007.pdf
[7] Sarkar, Abhiroop. "Understanding the Transactional Nature of Smart-Contracts." Web. https://abhiroop.github.io/Exceptions-and-Transactions
[8] Siegel, David. "Understanding The DAO Attack." Web. http://www.coindesk.com/understanding-dao-hack-journalists
[9] Blockchain software for asset management. "OYENTE: An Analysis Tool for Smart Contracts." Web. https://github.com/melonproject/oyente
[10] Holst Swende, Martin. “Breaking the house.“ Web. http://martin.swende.se/blog/Breaking_the_house.html
[11] Buterin, Vitalik. "Thinking About Smart Contract Security.“Web. https://blog.ethereum.org/2016/06/19/thinking-smart-contract-security
[12] Least Authority. "Gas Economics: Call Stack Depth Limit Errors." Web. https://github.com/LeastAuthority/ethereum-
analyses/blob/master/GasEcon.md#callstack-depth-limit-errors
[13] Underhanded Solidity Coding Contest, Web. http://u.solidity.cc/
[14] Quorum. "A permissioned implementation of Ethereum supporting data privacy." https://github.com/jpmorganchase/quorum
m@comae.io / @msuiche
https://github.com/comaeio/porosity

More Related Content

PPT
Socket programming
PDF
Travaux Dirigée: Equipements d'interconnexion
PPT
Classless addressing
PPTX
IEEE 802.11 Architecture and Services
PPTX
LAN Switching and Wireless: Ch2 - Basic Switch Concepts and Configuration
PPTX
USB protocol
PDF
Pcie basic
PDF
Architecture protocolaire des réseaux mobiles
Socket programming
Travaux Dirigée: Equipements d'interconnexion
Classless addressing
IEEE 802.11 Architecture and Services
LAN Switching and Wireless: Ch2 - Basic Switch Concepts and Configuration
USB protocol
Pcie basic
Architecture protocolaire des réseaux mobiles

What's hot (17)

PPTX
Generation of Computers
PDF
Lab- Full IPsec Implementation.pdf
PDF
Cisco Router Basic Configuration
PDF
Formation vsat
PPTX
intel Sync. & Edge Solution udpate xEng-v1.0.pptx
PPTX
Mac addresses(media access control)
PPT
Concept of networking
PPTX
Bluetooth.ppt
PPT
Ip addressing
PDF
Projet haute disponibilité asterisk pdf
PPTX
ccna networking ppt
PDF
2.10b network layer services i pv4 - variable length subnetting
PDF
Pci express technology 3.0
PPTX
Fragmentation
PPT
Wap ppt
PDF
Wireless communication technology
Generation of Computers
Lab- Full IPsec Implementation.pdf
Cisco Router Basic Configuration
Formation vsat
intel Sync. & Edge Solution udpate xEng-v1.0.pptx
Mac addresses(media access control)
Concept of networking
Bluetooth.ppt
Ip addressing
Projet haute disponibilité asterisk pdf
ccna networking ppt
2.10b network layer services i pv4 - variable length subnetting
Pci express technology 3.0
Fragmentation
Wap ppt
Wireless communication technology
Ad

Similar to A Decompiler for Blackhain-Based Smart Contracts Bytecode (20)

KEY
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
PDF
BlockchainDay "Ethereum Dapp - Asset Exchange YOSEMITE alpha" Session
PPTX
Track c-High speed transaction-based hw-sw coverification -eve
PPT
Writing Metasploit Plugins
PDF
How to be a smart contract engineer
PPTX
PVS-Studio, a solution for resource intensive applications development
PDF
Embedded systemsproject_2020
PDF
Ethereum hackers
PDF
“Create your own cryptocurrency in an hour” - Sandip Pandey
PPTX
Ethereum: Coding Society
PPTX
QuillAudit Smart contracts audit ppt - https://audits.quillhash.com
PDF
0x01 - Breaking into Linux VMs for Fun and Profit.pdf
PDF
DEF CON 27 - XILING GONG PETER PI - exploiting qualcom wlan and modem over th...
PPTX
以太坊代幣付款委託 @ Open Source Developer Meetup #12
PPTX
0x01 - Breaking into Linux VMs for Fun and Profit
PPTX
EVM - The Heart of Ethereum
PDF
MultiThreading-in-system-and-android-logcat-42-.pdf
PPTX
EthereumBlockchainMarch3 (1).pptx
PDF
Buffer Overflow - Smashing the Stack
PDF
BERserk: New RSA Signature Forgery Attack
Post Exploitation Bliss: Loading Meterpreter on a Factory iPhone, Black Hat U...
BlockchainDay "Ethereum Dapp - Asset Exchange YOSEMITE alpha" Session
Track c-High speed transaction-based hw-sw coverification -eve
Writing Metasploit Plugins
How to be a smart contract engineer
PVS-Studio, a solution for resource intensive applications development
Embedded systemsproject_2020
Ethereum hackers
“Create your own cryptocurrency in an hour” - Sandip Pandey
Ethereum: Coding Society
QuillAudit Smart contracts audit ppt - https://audits.quillhash.com
0x01 - Breaking into Linux VMs for Fun and Profit.pdf
DEF CON 27 - XILING GONG PETER PI - exploiting qualcom wlan and modem over th...
以太坊代幣付款委託 @ Open Source Developer Meetup #12
0x01 - Breaking into Linux VMs for Fun and Profit
EVM - The Heart of Ethereum
MultiThreading-in-system-and-android-logcat-42-.pdf
EthereumBlockchainMarch3 (1).pptx
Buffer Overflow - Smashing the Stack
BERserk: New RSA Signature Forgery Attack
Ad

More from Shakacon (20)

PDF
Web (dis)assembly
PDF
Macdoored
PDF
I can be apple and so can you
PDF
Cloud forensics putting the bits back together
PDF
Pwned in Translation - from Subtitles to RCE
PDF
Oversight: Exposing spies on macOS
PDF
Modern Reconnaissance Phase on APT - protection layer
PDF
Shamoon
PPTX
Honey, I Stole Your C2 Server: A Dive into Attacker Infrastructure
PPTX
Dock ir incident response in a containerized, immutable, continually deploy...
PDF
Reviewing the Security of ASoC Drivers in Android Kernel
PDF
Silent Protest: A Wearable Protest Network
PDF
WiFi-Based IMSI Catcher
PPTX
Sad Panda Analysts: Devolving Malware
PDF
reductio [ad absurdum]
PDF
XFLTReat: a new dimension in tunnelling
PDF
Windows Systems & Code Signing Protection by Paul Rascagneres
PDF
When Encryption is Not Enough...Sumanth Naropanth, Chandra Prakash Gopalaiah ...
PDF
The Search for the Perfect Door - Deviant Ollam
PDF
Swift Reversing by Ryan Stortz
Web (dis)assembly
Macdoored
I can be apple and so can you
Cloud forensics putting the bits back together
Pwned in Translation - from Subtitles to RCE
Oversight: Exposing spies on macOS
Modern Reconnaissance Phase on APT - protection layer
Shamoon
Honey, I Stole Your C2 Server: A Dive into Attacker Infrastructure
Dock ir incident response in a containerized, immutable, continually deploy...
Reviewing the Security of ASoC Drivers in Android Kernel
Silent Protest: A Wearable Protest Network
WiFi-Based IMSI Catcher
Sad Panda Analysts: Devolving Malware
reductio [ad absurdum]
XFLTReat: a new dimension in tunnelling
Windows Systems & Code Signing Protection by Paul Rascagneres
When Encryption is Not Enough...Sumanth Naropanth, Chandra Prakash Gopalaiah ...
The Search for the Perfect Door - Deviant Ollam
Swift Reversing by Ryan Stortz

Recently uploaded (20)

PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Cloud computing and distributed systems.
PPTX
MYSQL Presentation for SQL database connectivity
PPT
Teaching material agriculture food technology
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Approach and Philosophy of On baking technology
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Machine learning based COVID-19 study performance prediction
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Cloud computing and distributed systems.
MYSQL Presentation for SQL database connectivity
Teaching material agriculture food technology
Understanding_Digital_Forensics_Presentation.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Unlocking AI with Model Context Protocol (MCP)
20250228 LYD VKU AI Blended-Learning.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Network Security Unit 5.pdf for BCA BBA.
sap open course for s4hana steps from ECC to s4
Agricultural_Statistics_at_a_Glance_2022_0.pdf
MIND Revenue Release Quarter 2 2025 Press Release
Approach and Philosophy of On baking technology
Spectral efficient network and resource selection model in 5G networks
Machine learning based COVID-19 study performance prediction
Diabetes mellitus diagnosis method based random forest with bat algorithm
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx

A Decompiler for Blackhain-Based Smart Contracts Bytecode

  • 1. Porosity Decompiling Ethereum Smart-Contracts Matt Suiche (@msuiche) Founder, Comae Technologies m@comae.io
  • 2. Whoami  @msuiche  Comae Technologies  OPCDE - www.opcde.com  First time in Vegas since BlackHat 2011  Mainly Windows-related stuff  CloudVolumes (VMware App Volumes)  Memory Forensics for DFIR (Hibr2Bin, DumpIt etc.)  “looks like such fun guy” – TheShadowBrokers  Didn’t know much about blockchain before this project
  • 3. Just so you know…  We won’t talk about POW/POS stuff  We won’t talk about Merkle Trees  We won’t talk about how to becoming a crypto-currency millionaire  We will talk about the Ethereum EVM  We will talk about Solidity  We will talk about smart-contract bytecodes  And yes, the tool isn’t perfect ☺
  • 4. Agenda  Ethereum Virtual Machine (EVM)  Memory Management  Addresses  Call Types  Type Discovery  Smart-Contract  Code Analysis  Known Bugs  Future
  • 5. Solidity  Solidity the quality or state of being firm or strong in structure.  But also the name of Ethereum’s smart-contracts compiler  Porosity is the quality of being porous, or full of tiny holes. Liquids go right through things that have porosity.  But also the name of Comae’s smart-contract decompiler.
  • 6. Accounts  Normal Accounts: 3,488,419 (July 15)  Contract Accounts: 930,889 (July 15)  Verified Contract Accounts: 2285 (July 15)  Source code is provided.  40M$ lost in July  10M$ in CoinDash’s ICO  http://www.coindesk.com/coindash-ico-hacker-nets-additional- ether-theft-tops-10-million/  30M$ due to Parity’s wallet.sol vulnerability  https://blog.parity.io/security-alert-high-2/  https://github.com/paritytech/parity/pull/6103
  • 7. Ethereum Virtual Machine (EVM)  Account/Contract/Blockchain  A Smart-Contract is made of bytecode stored in the blockchain.  An address is a 160-bits value & corresponds to an “account”  Operates 256-bits pseudo-registers  EVM does not really have registers, but uses a virtual stack to replace them.
  • 8. Solidity & “Smart Contracts”  Solidity compiles JavaScript-like code into Ethereum bytecode.contract Coin { // The keyword "public" makes those variables // readable from outside. address public minter; mapping (address => uint) public balances; // Events allow light clients to react on // changes efficiently. event Sent(address from, address to, uint amount); // This is the constructor whose code is // run only when the contract is created. function Coin() { minter = msg.sender; } function mint(address receiver, uint amount) { if (msg.sender != minter) return; balances[receiver] += amount; } function send(address receiver, uint amount) { if (balances[msg.sender] < amount) return; balances[msg.sender] -= amount; balances[receiver] += amount; Sent(msg.sender, receiver, amount); } }
  • 9. Memory Management  Stack  Virtual stack is being used for operations to pass parameters to opcodes.  256-bit values/entries  Maximum size of 1024 elements  Storage (Persistent)  Key-value storage mapping (256-to-256-bit integers)  Can’t be enumerated.  SSTORE/SLOAD  Memory (Volatile)  256-bit values (lots of AND operations, useful for type discovery)  MSTORE/MLOAD
  • 10. Basic Blocks  Usually start with the JUMPDEST instruction – except few cases.  JUMP* instruction jump to the address contained in the 1st element of the stack.  JUMP* instruction are (almost always) preceded by PUSH instruction  This allows to push the destination address in the stack, instead of hardcoding the destination offset.  SWAP/DUP/POP stack manipulation instructions can make jump destination address harder to retrieve  This requires dynamic analysis to rebuild the relationship between each basic block.
  • 11. EVM functions/instructions  EVM instructions are more like functions, such as:  Arithmetic, Comparison & Bitwise Logic Operations  SHA3  Environmental & Block Information  Stack, Memory, Storage and Flow Operations  Logging & System Operations
  • 12. Instruction call - Addition  The above translates at the EVM-pseudo code:  add(0x2, 0x1) Offset Instruction Stack[0] Stack[2] n PUSH1 0x1 0x1 n + 1 PUSH1 0x2 0x2 0x1 n + 2 ADD 0x3
  • 13. EVM Call  Can be identified by the CALL instruction.  Call external accounts/contracts pointed by the second parameter  The second parameter contains the actual 160 address of the external contract  With the exception of 4 hardcoded contracts:  1 – elliptic curve public key recovery function  2- SHA2 function  3- RIPEMD160 function  4- Identity function call( gasLimit, to, value, inputOffset, inputSize, outputOffset, outputSize )
  • 14. User-Defined functions (Solidity)  CALLDATALOAD instruction is used to read the Environmental Information Block (EIB) such as parameters.  First 4 bytes of the EIB contains the 32-bits hash of the called function.  Followed by the parameters based on their respective types.  e.g. int would be a 256 bits word.  a = calldataload(0x4)  b = calldataload(0x24)  add(calldataload(0x4), calldataload(0x24) function foo(int a, int b) { return a + b; }
  • 15. Type Discovery - Addresses  As an example, addresses are 160-bit words  Since stack registers are 256-bit words, they can easily be identified through AND operations using the 0xffffffffffffffffffffffffffffffffffffffff mask.  Mask can be static or computed dynamically Ethereum Assembly Translation (msg.sender) CALLER PUSH1 0x01 PUSH 0xA0 PUSH1 0x02 EXP SUB AND and(reg256, sub(exp(2, 0xa0), 1)) (EVM) reg256 & (2 ** 0xA0) - 1) (Intermediate) address (Solidity)
  • 16. Bytecode  The bytecode is divided in two categories:  Pre-loader code  Found at the beginning that contains the routine to bootstrap the contract  Runtime code of the contract  The core code written by the user that got compiled by Solidity  Each contract contain a dispatch function that redirects the call to the corresponding function based on the provided hash function.
  • 17. Bytecode – Pre-loader  CODECOPY copies the runtime part of the contract into the EVM memory – which gets executed at base address 0x0 00000000 6060 00000002 6040 00000004 52 00000005 6000 00000007 6001 00000009 6000 0000000b 610001 0000000e 0a 0000000f 81 00000010 54 00000011 81 00000012 60ff 00000014 02 00000015 19 00000016 16 00000017 90 00000018 83 00000019 02 0000001a 17 0000001b 90 0000001c 55 0000001d 50 0000001e 61bb01 00000021 80 00000022 612b00 00000025 6000 00000027 39 00000028 6000 0000002a f3 PUSH1 60 PUSH1 40 MSTORE PUSH1 00 PUSH1 01 PUSH1 00 PUSH2 0001 EXP DUP2 SLOAD DUP2 PUSH1 ff MUL NOT AND SWAP1 DUP4 MUL OR SWAP1 SSTORE POP PUSH2 bb01 DUP1 PUSH2 2b00 PUSH1 00 CODECOPY PUSH1 00 RETURN
  • 18. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP calldataload(0x0) / exp(0x2, 0xe0)
  • 19. Function Hashes  The 4 bytes of the sha3 (keccak256) value for the string functionName(param1Type, param2Type, etc) [ { "constant":false, "inputs":[{ "name":"a", "type":"uint256" }], "name":"double", "outputs":[{ "name":"", "type":"uint256" }], "type":"function" } ] keccak256("double(uint256)") => eee972066698d890c32fec0edb38a360c32b71d0a29ffc75b6ab6d2774ec9901 double(uint256) -> 0xeee97206 triple(uint256) -> 0xf40a049d
  • 20. Extracting function hash  calldataload(0x0) / exp(0x2, 0xe0)  (0x12345678xxxx / 0x00000001xxxx) = 0x12345678  jumpi(eq(calldataload(0x0) / exp(0x2, 0xe0), 0xeee97206)) PS C:Program FilesGeth> .evm.exe --code 60e060020a60003504 --debug --input 12345678aaaaaaaabbbbbbbbccccccccdddddddd PC 00000009: STOP GAS: 9999999923 COST: 0 STACK = 1 0000: 0000000000000000000000000000000000000000000000000000000012345678 MEM = 0 STORAGE = 0 Ethereum Emulator
  • 21. Static CFG (--cfg) Emulated CFG (--cfg-full) Control Flow Graph
  • 22. Dispatcher – pseudo code hash = calldataload(0x0) / exp(0x2, 0xe0); switch (hash) { case 0xeee97206: // double(uint256) memory[0x60] = calldataload(0x4) * 2; return memory[0x60]; break; case 0xf40a049d: // triple(uint256) memory[0x60] = calldataload(0x4) * 3; return memory[0x60]; break; default: // STOP break; } contract C { function double(int arg_4) { return arg_4 * 2; } function triple(int arg_4) { return arg_4 * 3; } } Pseudo-Code Translated Code
  • 23. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 24. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 25. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 26. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 27. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 28. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 29. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 30. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 31. Bytecode – Dispatcher (--list) loc_00000000: 0x00000000 60 60 PUSH1 60 0x00000002 60 40 PUSH1 40 0x00000004 52 MSTORE 0x00000005 60 e0 PUSH1 e0 0x00000007 60 02 PUSH1 02 0x00000009 0a EXP 0x0000000a 60 00 PUSH1 00 0x0000000c 35 CALLDATALOAD 0x0000000d 04 DIV 0x0000000e 63 06 72 e9 ee PUSH4 06 72 e9 ee 0x00000013 81 DUP2 0x00000014 14 EQ 0x00000015 60 24 PUSH1 24 0x00000017 57 JUMPI loc_00000018: 0x00000018 80 DUP1 0x00000019 63 9d 04 0a f4 PUSH4 9d 04 0a f4 0x0000001e 14 EQ 0x0000001f 60 35 PUSH1 35 0x00000021 57 JUMPI loc_00000022: 0x00000022 5b JUMPDEST 0x00000023 00 STOP double(uint256): 0x00000024 5b JUMPDEST 0x00000025 60 45 PUSH1 45 0x00000027 60 04 PUSH1 04 0x00000029 35 CALLDATALOAD 0x0000002a 60 00 PUSH1 00 0x0000002c 60 4f PUSH1 4f 0x0000002e 82 DUP3 0x0000002f 60 02 PUSH1 02 loc_00000031: 0x00000031 5b JUMPDEST 0x00000032 02 MUL 0x00000033 90 SWAP1 0x00000034 56 JUMP triple(uint256): 0x00000035 5b JUMPDEST 0x00000036 60 45 PUSH1 45 0x00000038 60 04 PUSH1 04 0x0000003a 35 CALLDATALOAD 0x0000003b 60 00 PUSH1 00 0x0000003d 60 4f PUSH1 4f 0x0000003f 82 DUP3 0x00000040 60 03 PUSH1 03 0x00000042 60 31 PUSH1 31 0x00000044 56 JUMP
  • 32. DELEGATECALL & $30M Parity Bug contract Wallet { address _walletLibrary; address owner; // initWallet() is only invoked by the constructor. WalletLibrary is hardcoded. function Wallet(address _owner) { _walletLibrary = 0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3; _walletLibrary.delegatecall(bytes4(sha3("initWallet(address)")), _owner); } (…) // fallback function behaves like a “generic forward” (WTF?) // Wallet.initWallet(attacker) becomes walletLibrary.initWallet(attacker) function () payable { _walletLibrary.delegatecall(msg.data); } } Abusing the dispatcher to reinitialize a wallet?
  • 33. Generic-Forward & Fall back functions  Typical issue introduce by the lack of upgradeability of smart- contract  Software engineering is hard enough, but smart-contracts need to be:  Backward-Compatible  Forward-Compatible  Does not help to make the language verifiable.  Fall back functions are undefined behaviors.  Imagine if your kernel would behave like that.  Scary, right ? Now, imagine if that’s your bank…
  • 34. Fixing the initialization bug - function initMultiowned(address[] _owners, uint _required) { + function initMultiowned(address[] _owners, uint _required) internal { - function initDaylimit(uint _limit) { + function initDaylimit(uint _limit) internal { + modifier only_uninitialized { if (m_numOwners > 0) throw; _; } - function initWallet(address[] _owners, uint _required, uint _daylimit) { + function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
  • 35. Code Analysis – Vulnerable Contract contract SendBalance { mapping ( address => uint ) userBalances ; bool withdrawn = false ; function getBalance (address u) constant returns ( uint ){ return userBalances [u]; } function addToBalance () { userBalances[msg.sender] += msg.value ; } function withdrawBalance (){ if (!(msg.sender.call.value( userBalances [msg.sender])())) { throw ; } userBalances [msg.sender] = 0; } }
  • 36. Code Analysis – Vulnerable Contract contract SendBalance { mapping ( address => uint ) userBalances ; bool withdrawn = false ; function getBalance (address u) constant returns ( uint ){ return userBalances [u]; } function addToBalance () { userBalances[msg.sender] += msg.value ; } function withdrawBalance (){ if (!(msg.sender.call.value( userBalances [msg.sender])())) { throw ; } userBalances [msg.sender] = 0; } } Caller contract can recall this function using its fallback function
  • 37. Understanding the control flow  In the case of reentrant vulnerability, since we can record the EVM state at each instruction using porosity.  We can track in which basic block SSTORE instructions are called.  userBalances [msg.sender] = 0;  And track states for each basic block.
  • 38. .demo.ps1 $porosity = 'E:projectsporosityDebugporosity.exe' $abi = '[{"constant":false,"inputs":[],"name":"withdrawBalance","outputs":[],"ty pe":"function"},{"constant":false,"inputs":[],"name":"addToBalance","out puts":[],"type":"function"},{"constant":true,"inputs":[{"name":"u","ty pe":"address"}],"name":"getBalance","outputs":[{"name":"","type":"ui nt256"}],"type":"function"}]' $code = '60606040526000357c01000000000000000000000000000000000000000000000000000000009004806 35fd8c7101461004f578063c0e317fb1461005e578063f8b2cb4f1461006d5761004d565b005b61005c6 004805050610099565b005b61006b600480505061013e565b005b6100836004808035906020019091905 05061017d565b6040518082815260200191505060405180910390f35b3373fffffffffffffffffffffff fffffffffffffffff16611111600060005060003373ffffffffffffffffffffffffffffffffffffffff1 6815260200190815260200160002060005054604051809050600060405180830381858888f1935050505 0151561010657610002565b6000600060005060003373fffffffffffffffffffffffffffffffffffffff f168152602001908152602001600020600050819055505b565b34600060005060003373fffffffffffff fffffffffffffffffffffffffff168152602001908152602001600020600082828250540192505081905 5505b565b6000600060005060008373ffffffffffffffffffffffffffffffffffffffff1681526020019 081526020016000206000505490506101b6565b91905056’ & $porosity --abi $abi --runtime-code $code --decompile --verbose 0
  • 40. Known class of bugs  Reentrant Vulnerabilities / Race Condition  Famously known because of the $50M USD DAO hack (2016) [8]  Call Stack Vulnerabilities  Got 1024 frames but a bug ain’t one – c.f. Least Authority [12]  Time Dependency Vulnerabilities  @mhswende blogposts are generally awesome, particularly the roulette one [10]  Unconditional DELEGATECALL
  • 41. Porosity + Quorum = <3  Quorum: Ethereum code fork created by J.P. Morgan  aimed at enterprises that want to use a permissioned blockchain that adds private smart contract execution & configurable consensus.  Quorum now includes Porosity integrated directly into geth out of the box:  Scan private contracts sent to your node from other network participants  Incorporate into security & patching processes for private networks with formalized governance models  Automate scanning and analyze risk across semi-public Quorum networks  https://github.com/jpmorganchase/quorum
  • 43. Future  Ethereum DApps created a new segment for softwares.  Porosity  Improving support for conditional and loop statements  Ethereum / Solidity & Security  Fast growing community and more tools such as OYENTE or Porosity  Personally, looking forward seeing the Underhanded Solidity Coding Contest [10] results  EVM vulnerabilities triggered by malicious bytecode? CLOUDBURST on the blockchain  More Blockchain VMs ?  Swapping the EVM for Web Assembly (WASM) for 2018
  • 44. Future - WebAssembly  New Ethereum Roadmap (March 2017) mentions making the EVM obsolete and replacing it with WebAssembly for 2018.  “WebAssembly (or WASM) is a new, portable, size- and load-time- efficient format.”  WebAssembly is currently being designed as an open standard by a W3C Community Group.  WebAssembly defines an instruction set, intermediate source format (WAST) and a binary encoded format (WASM).  Major browser JavaScript engines will notably have native support for WebAssembly – including V8, Chakra and Spidermonkey.  https://github.com/ewasm/design
  • 45. WASM + DApps + Blockchain  C++ -> WASM is already a thing  https://mbebenita.github.io/WasmExplorer/  And a similar thing is planned for eWASM
  • 46. Acknowledgements  Mohamed Saher  Halvar Flake  DEFCON Review Board Team  Max Vorobjov & Andrey Bazhan  Martin H. Swende  Gavin Wood  Andreas Olofsson
  • 47. References [1] Woods, Gavin. "Ethereum: A Secure Decentralised Generalised Transaction Ledger." Web. https://github.com/ethereum/yellowpaper.pdf [2] Olofsson, Andreas. "Solidity Workshop." Web. https://github.com/androlo/solidity-workshop [3] Olofsson, Andreas. "Solidity Contracts." Web. https://github.com/androlo/standard-contracts [4] Velner, Yarn, Jason Teutsch, and Loi Luu. "Smart Contracts Make Bitcoin Mining Pools Vulnerable." Web. https://eprint.iacr.org/2017/230.pdf [5] Luu, Loi, Duc-Hiep Chu, Hrishi Olickel, Aquinas Hobor. "Making Smart Contracts Smarter." Web. https://www.comp.nus.edu.sg/%7Ehobor/Publications/2016/Making%20Smart%20Contracts%20Smarter.pdf [6] Atzei, Nicola, Massimo Bartoletti, and Tiziana Cimoli. " A Survey of Attacks on Ethereum Smart Contracts." Web. https://eprint.iacr.org/2016/1007.pdf [7] Sarkar, Abhiroop. "Understanding the Transactional Nature of Smart-Contracts." Web. https://abhiroop.github.io/Exceptions-and-Transactions [8] Siegel, David. "Understanding The DAO Attack." Web. http://www.coindesk.com/understanding-dao-hack-journalists [9] Blockchain software for asset management. "OYENTE: An Analysis Tool for Smart Contracts." Web. https://github.com/melonproject/oyente [10] Holst Swende, Martin. “Breaking the house.“ Web. http://martin.swende.se/blog/Breaking_the_house.html [11] Buterin, Vitalik. "Thinking About Smart Contract Security.“Web. https://blog.ethereum.org/2016/06/19/thinking-smart-contract-security [12] Least Authority. "Gas Economics: Call Stack Depth Limit Errors." Web. https://github.com/LeastAuthority/ethereum- analyses/blob/master/GasEcon.md#callstack-depth-limit-errors [13] Underhanded Solidity Coding Contest, Web. http://u.solidity.cc/ [14] Quorum. "A permissioned implementation of Ethereum supporting data privacy." https://github.com/jpmorganchase/quorum