Slide 1

Slide 1 text

NotSurprised @ SITCON [email protected]

Slide 2

Slide 2 text

https://speakerdeck.com/notsurprised/sitcon2019-solidity

Slide 3

Slide 3 text

> • – • – –

Slide 4

Slide 4 text

> NotSurprised • UCCU hacker • ITRI engineer • 中山資管五年學碩士 Email : [email protected]

Slide 5

Slide 5 text

> • • • •

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

> Decentralized (分散性) Anonymity (匿名性) Immutable (不變性) Autonomy (獨立性)

Slide 8

Slide 8 text

>

Slide 9

Slide 9 text

> Ethereum EOA (Externally Owned Account) CA (Contract Account) • Person or Party • Address • Access by Private Key • Ether balance • Send transaction • Trigger contract • Code • Address • Ether balance • Trigger contract • On Blockchain

Slide 10

Slide 10 text

>

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

> solc a soldility compiler Bytecode just for EVM EVM Ethereum VM source smart contract code in soldility

Slide 13

Slide 13 text

> Unit Wei Value Wei wei 1 wei 1 Kwei (babbage) 1e3 wei 1,000 Mwei (lovelace) 1e6 wei 1,000,000 Gwei (shannon) 1e9 wei 1,000,000,000 microether (szabo) 1e12 wei 1,000,000,000,000 milliether (finney) 1e15 wei 1,000,000,000,000,000 ether 1e18 wei 1,000,000,000,000,000,000

Slide 14

Slide 14 text

> Operation Gas Description ADD/SUB 3 Arithmetic operation AND/OR/XOR 3 Bitwise logic operation LT/GT/SLT/SGT/EQ 3 Comparison operation POP 2 Stack operation PUSH/DUP/SWAP 3 Stack operation MLOAD/MSTORE 3 Memory operation JUMP 8 Unconditional jump JUMPI 10 Conditional jump SLOAD 200 Storage operation SSTORE 5,000/20,000 Storage operation BALANCE 400 Get balance of an account CREATE 32,000 Create a new account using CREATE CALL 25,000 Create a new account using CALL

Slide 15

Slide 15 text

> Web3.js 此中介層能把 request 的冗長 JSON-RPC 查詢語句隱藏起來,讓開發者只需要與易懂的(?) JavaScript 互動即可。 • abi – 顯示 Application Binary Interface 以及 subfunction 列表以供 de/encode 。 • web3.eth.getBalance( ) – 取得 address 的 balance (存款)。 • web3.eth.sendTransaction( ) – 發送 transaction 乙太坊網路 (公、私、測試網路)。 • web3.eth.myContract.methods.myMethod( ).send( ) – 傳送 transaction 到 smart contract 執行指定的 method. • web3.eth.myContract.methods.myMethod( ).call( ) – 在不發起 transaction 到網路的狀況下調用 “constant” method 以在 EVM 內執行 smart contract method。

Slide 16

Slide 16 text

> Solidity • payable – 是 modifiers (修飾符) 例如: public、private、onlyOwner、view、pure – payable 函數是 Solidity 和以太坊的核心特色 —— 它正是讓Smart Contract Account 可以接收以太幣的特殊函數。 • msg.sender – 在 Solidity 中,有一些全局變量可以被所有函數調用使用其中一個就是 msg.sender 。 – 它指的是當前調用者(contract owner、contract或EOA)的 address。 • tx.origin – 也是 Solidity 中可以被所有函數調用使用的全局變量。 – 它指的是此交易發起的源頭 address ,不能是合約地址。 •
. balance( ) •
.transfer( uint256 ) :一般的交易,最多耗用 2300 wei 的 Gas。 •
.send( uint256 ) returns ( bool ) :帶交易結果的方式,最多耗用 2300 wei 的 Gas。 •
.call.gas(g).value(v)( methodId, args ) :帶交易結果,預設無 Gas 使用上限。 •
.call ( ) :一般的呼叫方式,執行背景跳到下一個函式的環境(msg的值和合約的Storage)。 •
.callcode ( ) :和 call 相同,只是將被呼叫者的函式搬到呼叫者的環境裡執行。 •
.delegatecall( ):和 callcode 相同,只是差在 msg.sender 的值會保持不變向下傳遞。

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

──

Slide 19

Slide 19 text

> Fallback • 合約可以有一個未命名的函數。這個函數不能有參數也不能有返回值。 • 如果一個合約收到了以太幣( Ether ) (且沒有函數被調用),就會執行 fallback 函數。 • 此外,為了接收以太幣,fallback 函數必須標記為 payable。 • 這就是 Solidity 所說的後備功能。主要用途為 集中處理記錄 預料外的交易內容。

Slide 20

Slide 20 text

> Fallback function Loop 1000*1000+1? If 1 transaction take 10 sec? To steal this 1000 ether: 4 Month + 1000 Ether contract.contribute({value:1}) // 首先使貢獻值大於 0 contract.send(1) // 無合約函數交易觸發 fallback 函數 contract.owner( ) // 確認合約擁有者變換與否 contract.withdraw( ) // 將合約的 balance 清零

Slide 21

Slide 21 text

> Parity Wallet Hack • 在 fallback 函式裡使用: _walletLibrary.delegatecall(msg.data); • 導致 fallback 處理的例外交易可以調用函數中任何函數,包括: function initWallet(address[] _owners, uint _required, uint _daylimit) { } • 損失 150,000 ETH (~30M USD) 這玩意從各種程度上來說都太他媽邪門了

Slide 22

Slide 22 text

──

Slide 23

Slide 23 text

> Construct • Solidity contract 的 construct 繼承自 Java 的 class construct 。 • 在定義 contract時,可以使用「建構函數」(Constructor)來進行 contract 的初始化。

Slide 24

Slide 24 text

>

Slide 25

Slide 25 text

>

Slide 26

Slide 26 text

> Fal1out Fallout contract.Fal1out( ) // 調用錯名初始函數變更擁有者 contract.owner( ) // 確認合約擁有者變換與否 FalIout

Slide 27

Slide 27 text

> Rubixi • 一個龐氏遊戲合約 • 玩家需要發送以太幣到合 約中,以獲得更多的以太 幣。 • 原名DynamicPyramid • 新名字新氣象

Slide 28

Slide 28 text

──

Slide 29

Slide 29 text

> • msg.sender – 在 Solidity 中,有一些全局變量可以被所有函數調用使用其中一個就是 msg.sender 。 – 它指的是當前調用者(或智能合約)的 address。 • tx.origin – 也是 Solidity 中可以被所有函數調用使用的全局變量。 – 它指的是此交易發起的源頭 address ,並且絕不會是 contract address 。

Slide 30

Slide 30 text

>

Slide 31

Slide 31 text

> Hard code importing to fit compiling requirement Header-like importing

Slide 32

Slide 32 text

• Use Remix IDE to test deploy on test net. > Your Contract address

Slide 33

Slide 33 text

>

Slide 34

Slide 34 text

> msg.sender : Client tx.origin : Client msg.sender : ATM tx.origin : Client ATM contract Bank contract Client withdraw Client withdraw

Slide 35

Slide 35 text

> msg.sender : GreenHat tx.origin : GreenHat msg.sender : Bank tx.origin : GreenHat Bank contract Client withdraw Pay Money msg.sender : GreenHat tx.origin : GreenHat function( ){ bank.takeOwnership( ) } GreenHat a.k.a. hack rookie tx.origin 絕不會是 contract address

Slide 36

Slide 36 text

Hacker > msg.sender : Wallet tx.origin : Victim Offer Something Like Rubixi (Careful: Hacker not the one launchs the transaction) Pay Money msg.sender : Hacker tx.origin : Victim function( ){ wallet.takeOwnership( ) } Victim Wallet contract

Slide 37

Slide 37 text

──

Slide 38

Slide 38 text

> • Reentrancy – 是 function 可以在執行過程中被中斷,在上一次執行還沒完成前可以再次進 入這個 function 執行而不會有問題,也就是第二次進入 function 執行結束 後,第一次的執行仍能正確完成。 – 中斷可以是 jump 或 call,也可以是系統的 interrupt 或 signal。 – single thread 下的概念。被系統 interrupt 中斷時 interrupt handler 能 夠再 call 剛剛執行到一半的 function。 • Reentrancy Rule – 不使用 global(或 static)的變數。 如能確保 global 變數或 state 能在執行前後保持一致則可使用。 – 不修改自身的 code – 不 call non-reentrant function

Slide 39

Slide 39 text

> • 雖使用 mapping(address => uint) public balances; 的值, withdraw( ) 依然算 Reentrancy。 • 因為扣存款是在確定完成提款後 ( return true ) • 如果使用具有不斷調用提款的 fallback 函數之合約調用提款, 可行成跨合約遞迴,因為上一輪 提款始終卡在確認完成與否。 • 不斷發起交易會導致提款的 Gas 不段增高。但這裡的 call.value( )( ) 可用盡所有合約 Gas。

Slide 40

Slide 40 text

> The DAO (入股享投票權的天使基金) • ↓ 71% 0.0002505 BTC → 0.0000711 BTC (50M USD)

Slide 41

Slide 41 text

>

Slide 42

Slide 42 text

> 切割三連 離我遠點啊 不可逆是啥 分叉切割刀啊 Ethereum Hard Fork

Slide 43

Slide 43 text

> Reentrancy! Nope!

Slide 44

Slide 44 text

──

Slide 45

Slide 45 text

> • call – 一般的呼叫都是這種方式,執行背景跳到下一個函式的環境 • callcode – 和call相同,只是將被呼叫者的函式搬到呼叫者的環境裡執行。 • delegatecall – 和callcode相同,把被呼叫的函式搬到呼叫者的環境裡執行,只是差在 msg.sender 的值。 B.call(byte4(keccak256("func()"))) //next line of A contract function func(){ //some logic code } A contract call B.call(byte4(keccak256("func()"))) //next line of A contract function func(){ //some logic code } function func(){ //some logic code } delegatecall B contract

Slide 46

Slide 46 text

> • delegatecall( _address ) – 根據 Solidity 的 Contract ABI Specification,如果第一個參數剛好是 4 bytes, Solidity 會認為 4 bytes 指定的是函數的 keccak256 的 Hash 值 ( 在 web3 是 sha3 ) 。

Slide 47

Slide 47 text

> contract.owner() // 確認合約擁有者用於比對 contract.sendTransaction({data:web3.sha3("pwn()").slice(0,10)}); // 發送 ether 觸發 callback 函式 // 將 pwn() 的 hash 4 byte 傳給 If 判斷式中的 delegate // 使 Solidity 自動辨認觸發 pwn() // 用 Solidity 部屬合約則建立一個使用 // byte4(keccak256("pwn()")) 的函式並發送 ether contract.owner() // 確認合約擁有者變換與否 • 複寫函數再宣告建立物件也只會得到屬 於自己的 delegate 物件。 • 使用 delegatecall() 會改變 msg.sender 的特性,來搶奪 delegation 宣告的 delegate 物件。

Slide 48

Slide 48 text

──

Slide 49

Slide 49 text

> Storage Slot (32bytes) Value slot 0 (var1) 1 -> 4 slot 1 (var2) 2 -> 5 slot 2 (var3) 3 Storage Slot (32bytes) Value slot 0 (var1) 1 slot 1 (var2) 2 slot 2 (var3) 3 web3.eth.getStorageAt(contract.address, 1, function(x, y) {alert(web3.toAscii(y))});

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

>

Slide 52

Slide 52 text

HITCON Pacific 2018 Speaker NCCST Security Engineer 台灣好厲駭講師 讓我知道直接帶實作會爆炸

Slide 53

Slide 53 text

https://www.facebook.com/tdohacker/ https://t.me/BorgEnt/

Slide 54

Slide 54 text

No content