靶场地址 
Warmup Deploy a contract 连接 MetaMask 即可
Call me 要求调用callme函数
在remix的deploy处将我们挑战的页面里给出的合约地址填上,部署后调用即可
Choose a nickname 设置自己的昵称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pragma solidity ^0.4.21;
同样的在remix里操作即可
注意要将昵称转化为十六进制,并且 return cte.nicknameOf(player)[0] != 0;
Lotteries Guess the number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pragma solidity ^0.4.21;
已知 answer = 42
注意调用guess函数并传参42的同时发送1 ether
Guess the secret number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pragma solidity ^0.4.21;
可以计算答案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 pragma solidity ^0.4.18;
Guess the random number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 pragma solidity ^0.4.21;
可以去交易详情 查看
即77
Guess the new number 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 pragma solidity ^0.4.21;
写一个 constructor() ,部署时打入1ETH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 contract attacker {
Predict the future 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 pragma solidity ^0.4.21;
让answer来就我们,按照规则一次一次地尝试生成answer,当此块的信息得到的answer与我们猜的guess相同时我们再调用settle函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 contract attacker {
Predict the block hash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 pragma solidity ^0.4.21;
我们看到该函数仅适用于最近的 256 个块。如果您尝试调用发生在 300 块前的函数,它会返回零。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 contract attacker {
Math Token sale 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 pragma solidity ^0.4.21;
require(msg.value == numTokens * PRICE_PER_TOKEN); 存在整数乘法上溢
1 2 3 4 5 1  ether = 10 ^18  wei// 最大的uint256 = = 115792089237316195423570985008687907853269984665640564039457584007913129639936 2 **256  / 10 **18  + 1  = 115792089237316195423570985008687907853269984665640564039458 // 10 **18 -2 **256  = 415992086870360064 
value为 0.415992086870360064 ether,要求 msg.value == numTokens * PRICE_PER_TOKEN 可以被满足。
然后我们可以 sell() 1 ether,合约余额现在为 0.41ether
Token whale Find a way to accumulate at least 1,000,000 tokens to solve this challenge.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 pragma solidity ^0.4.21;
_transfer函数存在溢出
account1 transfer(account2,1000) 
account2 approve(account1,1000) 
account1 transferFrom(account2,account3,1000) 
 
由于此时account1的代币余额为0,所以最后调用 _transfer 时会发生下溢
Retirement fund 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 pragma solidity ^0.4.21;
使用selfdestruct函数,使 collectPenalty() 中的 require(withdrawn > 0); 被满足
1 2 3 4 5 6 7 8 9 10 pragma solidity ^0.4.18;
Mapping 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 pragma solidity ^0.4.21;
类似Ethernaut 中的Alien Codex
数组长度越界,计算相对位置覆盖isComplete
Donation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 pragma solidity ^0.4.21;
Solidity中存储方式错误使用所导致的变量覆盖 
使传入的etherAmount,其值等于我们的Account地址
并满足msg.value == etherAmount / scal
1 2 uint (0 x9DC97146b924263A2c8C7237FbeEAFb6ef60b624) 10 **18 *10 **18 )
然后调用withdraw
Fifty years 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 pragma solidity ^0.4.21;
msg.value会覆盖queue的长度,timestamp会覆盖head
queue.push操作,因为其在最后执行增添对象的任务,添加以后它会将queue.length进行+1操作,用queue长度再覆盖contribution.amount一次
首先,我们创建一个新的队列条目,调用upsert准备绕过timestamp检查。我们选择timestamp这样的值,它会queue[queue.length - 1].unlockTimestamp + 1 days以等于零的方式溢出。
1 2 2 **256 -86400 115792089237316195423570985008687907853269984665640564039457584007913129553536 
调用Upset(1,115792089237316195423570985008687907853269984665640564039457584007913129553536)并发送1 wei
调用Upset(1,0)并发送1 wei
调用withdraw(1)
 
Accounts Fuzzy identity 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 pragma solidity ^0.4.21;
要求:
合约的name为smarx 
合约地址里包含 badc0de 
 
以太坊源码中生成合约地址的算法
1 2 3 4 5 6 7 func  CreateAddress (b common.Address, nonce uint64 )  common .Address interface {}{b, nonce}) return  common.BytesToAddress(Keccak256(data)[12 :]) 
使用ethjs-account 来生成地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const  rlp = require ('rlp' );const  js = require ('_js-sha3@0.8.0@js-sha3' );const  generate = require ('ethjs-account' ).generate;'892h@fs8sk^2hSFR*/8s8shfs.jk39hsoi@hohskd51D1Q8E1%^;DZ1-=.@WWRXNI()VF6/*Z%$C51D1QV*<>FE8RG!FI;"./+-*!DQ39hsoi@hoFE1F5^7E%&*QS' function  fuzz (for (var  k=0 ;k<50000 ;k++){Math .random().toString(36 ).substring(12 );for (var  i=0 ;i<1000 ;i++){for  (var  j=0 ;j<10 ;j++){24 ).toString('hex' );if (contractAddress.slice(33 ).match("badc0de" )){console .log(contractAddress);console .log(res);console .log(j);return ;
结果
1 2 3 4 5 6 7 8 76 e9f28df246ee1b3f7d3bb2c4c81e6f0badc0de7391 eb54a48a110345 cbd1ae88',8785 9bb2ad60bf05fd26abb7e77c6f26c492480 3ee9673 a3e55147652 d2f2662 d5a6591 df503f2711 7c182ce1b20d8afaaf2b4d4ed6a0737 9',8128 9dCa9F257fd448264 e18AB1B'8 
nonce为8时部署攻击合约
1 2 3 4 5 6 7 8 9 10 contract attack {
Public Key 1 2 3 4 5 6 7 8 9 10 11 12 pragma solidity ^0.4.21;
由地址得到公钥
椭圆曲线密码学和以太坊中的椭圆曲线数字签名算法应用 
由 w3.eth.getTransaction("0xabc467bedd1d17462fcc7942d0af7874d6f8bdefee2b299c9168a216d3ff0edb") 可以得到
1 AttributeDict ({'blockHash': HexBytes('0 x487183 cd9 eed0970 dab843 c9 ebd577 e6 af3 e1 eb7 c9809 d240 c8735 eab7 cb43 de'), 'blockNumber': 3015083 , 'from': '0 x92 b28647 Ae1 F3264661 f72 fb2 eB9625 A89 D88 A31 ', 'gas': 90000 , 'gasPrice': 1000000000 , 'hash': HexBytes('0 xabc467 bedd1 d17462 fcc7942 d0 af7874 d6 f8 bdefee2 b299 c9168 a216 d3 ff0 edb'), 'input': '0 x5468616 e6 b732 c206 d616 e21 ', 'nonce': 0 , 'r': HexBytes('0 xa5522718 c0 f95 dde27 f0827 f55 de836342 ceda594 d20458523 dd71 a539 d52 ad7 '), 's': HexBytes('0 x5710 e64311 d481764 b5 ae8 ca691 b05 d14054782 c7 d489 f3511 a7 abf2 f5078962 '), 'to': '0 x6 B477781 b0 e68031109 f21887 e6 B5 afEAaEB002 b', 'transactionIndex': 7 , 'type': '0 x0 ', 'v': 41 , 'value': 0 })
使用ethereumjs-tx 库创建一个交易从而利用里面封装的getSenderAddress得到公钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const EthereumTx = require('ethereumjs-tx').Transaction;
Account Takeover 1 2 3 4 5 6 7 8 9 10 11 12 pragma solidity ^0.4.21;
给出了地址求私钥
参考1 
参考2 
有两笔同 from 地址且同 to 地址的交易,且 r 值相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 const  EthereumTx = require ('ethereumjs-tx' ).Transaction;var  rawTx1 =nonce : 0 ,gasPrice : '0x3b9aca00' ,gasLimit : '0x5208' ,to : '0x92b28647ae1f3264661f72fb2eb9625a89d88a31' ,value : '0x1111d67bb1bb0000' ,data : '0x' ,v : 41 ,r : '0x69a726edfb4b802cbf267d5fd1dabcea39d3d7b4bf62b9eeaeba387606167166' ,s : '0x7724cedeb923f374bef4e05c97426a918123cc4fec7b07903839f12517e1b3c8' var  rawTx2 =nonce : 1 ,gasPrice : '0x3b9aca00' ,gasLimit : '0x5208' ,to : '0x92b28647ae1f3264661f72fb2eb9625a89d88a31' ,value : '0x1922e95bca330e00' ,data : '0x' ,v : 41 ,r : '0x69a726edfb4b802cbf267d5fd1dabcea39d3d7b4bf62b9eeaeba387606167166' ,s : '0x2bbd9c2a6285c2b43e728b17bda36a81653dd5f4612a2e0aefdb48043c5108de' new  EthereumTx(rawTx1,{ chain : 'ropsten' , hardfork : 'petersburg'  });new  EthereumTx(rawTx2,{ chain : 'ropsten' , hardfork : 'petersburg'  });false ).toString("hex" );false ).toString("hex" );console .log(z1);console .log(z2);
1 2 3 4 5 6 7 8 9 s1 -s2  = k ^ -1 (z1  + dA * r)-k ^ -1 (z2 + dA * r)1 (z1 -z2 )z1 -z2 )/(s1 -s2 )z1 -z2 )/(s1 -s2 )z1  – z2 )*inverse_mod(s1  – s2 ,p)%p
其中取模反的运算来自于python-ecdsa 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def  inverse_mod ( a, m  ):"""Inverse of a mod m.""" if  a < 0  or  m <= a: a = a % m1 , 0 , 0 , 1 while  c != 0 :divmod ( d, c ) + ( c, )assert  d == 1 if  ud > 0 : return  udelse : return  ud + mdef  derivate_privkey (p, r, s1, s2, z1, z2 ):return  d, k0x4f6a8370a435a27724bbc163419042d71b6dcbeb61c060cc6816cda93f57860c 0x2bbd9c2a6285c2b43e728b17bda36a81653dd5f4612a2e0aefdb48043c5108de 0x69a726edfb4b802cbf267d5fd1dabcea39d3d7b4bf62b9eeaeba387606167166 0x350f3ee8007d817fbd7349c477507f923c4682b3e69bd1df5fbb93b39beb1e04 0x7724cedeb923f374bef4e05c97426a918123cc4fec7b07903839f12517e1b3c8 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 print  ("privatekey:%x\n k:%x"  % derivate_privkey(p,r,s1,s2,z1,z2))
Miscellaneous Assume ownership 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 pragma solidity ^0.4.21;
构造函数拼写错误
Token bank 1 2 3 4 5 6 7 8 9 10 11 12 function transfer(address to, uint256 value, bytes data) public returns (bool) {
这里判断了to地址是否是个合约地址,如果是合约的话就用ITokenReceiver接口来调用to合约的tokenFallback函数,在银行合约里这个函数用更改目标的balance,合约存在重入漏洞。
1 2 3 4 5 6 7 8 function withdraw(uint256 amount) public {
调用该token.transfer函数后余额会更新,允许我们每次重复提取我们的存入资金。重入控制流程将是challenge.withdraw => token.transfer => msg.sender.tokenFallback() => ... 。
在调用攻击合约前,先将player账户withdraw出来,再给攻击合约授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 contract attacker {