ByteCTF 2019 bet & hf¶
bet¶
本题目是一个以太坊智能合约题目
首先需要进行evm的逆向,逆向出整体程序功能
首先我们想要payforflag,需要有10w余额
function payforflag(string b64email) public { require(balanceOf[msg.sender] >= 100000); emit SendFlag(b64email); }
function deposit() payable{ uint geteth=msg.value/1000000000000000000; balanceOf[msg.sender]+=geteth; } function profit() { require(gift[msg.sender]==0); gift[msg.sender]=1; balanceOf[msg.sender]+=1; }
还有一个betgame
function betgame(uint secretguess){ require(balanceOf[msg.sender]>0); balanceOf[msg.sender]-=1; if (secretguess==secret) { balanceOf[msg.sender]+=2; isbet[msg.sender]=1; } }
只要能够猜对secret 我们就可以用1个token bet出来2个token
Secret可以通过直接读取链上信息获得,也可以利用如下漏洞进行修改
function Bet() public{ owner = msg.sender; }
这里存在构造函数失控问题,通过执行Bet方法可以修改owner
修改owner后可以执行set secret方法
function setsecret(uint secretrcv) only_owner { secret=secretrcv; }
然后我们使用profit可以获得1个token 接下来执行betgame方法,可以获得两个token 并且把msgsender的isbet标志位变为1
因为我们已经是owner了 所以可以执行doublebetgame方法,在这里如果我们只有1个token的话,可以通过故意bet失败的方式,实现整形溢出
function doublebetgame(uint secretguess) only_owner{ require(balanceOf[msg.sender]-2>0); require(isbet[msg.sender]==1); balanceOf[msg.sender]-=2; if (secretguess==secret) { balanceOf[msg.sender]+=2; } }
但是因为isbet标志位的问题,我们现在有两个token,所以我们可以再次执行一次betgame并故意输掉1个token,让我们的token数量保持在1从而执行doublebetgame实现溢出。最后payforflag
hf¶
以太坊智能合约题目,首先需要对evm进行逆向。
目标是执行payforflag。
首先有一个空投函数:
function profit() public{ require(gift[msg.sender]==0); gift[msg.sender]=1; balanceOf[msg.sender]+=1; }
然后我们向合约的转账会变成我们的余额
function hfvote() public payable{ uint geteth=msg.value/1000000000000000000; balanceOf[msg.sender]+=geteth; }
function ubw() public payable{ if (msg.value < 2 ether) { node storage n = node0; n.nodeadress=msg.sender; n.nodenumber=1; } else { n.nodeadress=msg.sender; n.nodenumber=2; } }
函数中的第二个分支不存在初始化,n在执行的时候会形成未初始化漏洞,那么只要我们进入第二个分支就会修改storage中的第一个值为我们的地址,第二个值为2
address secret; uint count; address owner;
require(balanceOf[msg.sender]-value>=0); balanceOf[msg.sender]-=value; balanceOf[to]+=value;
function payforflag(string b64email) public { require(balanceOf[msg.sender] >= 100000); balanceOf[msg.sender]=0; owner.transfer(address(this).balance); emit SendFlag(b64email); }