当前位置:主页 > 查看内容

bytectf 2019 hf

发布时间:2021-06-19 00:00| 位朋友查看

简介:知识点 整形下溢出 Uninitialized Storage Pointer WP 源码 pragma solidity ^ 0.4 .24 ; contract hf { address secret ; uint count ; address owner ; mapping ( address uint ) public balanceOf ; mapping ( address uint ) public gift ; struct node……

知识点

  • 整形下溢出
  • Uninitialized Storage Pointer

WP

源码:

pragma solidity ^0.4.24;

contract hf {
    address secret;
    uint count;
    address owner;
    
    mapping(address => uint) public balanceOf;
    mapping(address => uint) public gift;
    
    struct node {
        address nodeadress;
        uint nodenumber;
    }
    
    node public node0;
    
    event SendFlag(string b64email);
    
    constructor()public{
        owner = msg.sender;
    }
    
    function payforflag(string b64email) public {
        require(balanceOf[msg.sender] >= 100000);
        balanceOf[msg.sender]=0;
        owner.transfer(address(this).balance);
        emit SendFlag(b64email);
    }
    

    //to fuck
    
    modifier onlySecret() {
        require(msg.sender == secret);
        _;
    }
    
    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;
        }
    }
    
    function fate(address to,uint value) public onlySecret {
        require(balanceOf[msg.sender]-value>=0);
        balanceOf[msg.sender]-=value;
        balanceOf[to]+=value;
    }
    
}

payforFlag那里要求require(balanceOf[msg.sender] >= 100000);,因此还是要想办法提高balance。经过查看,发现fate函数存在整形下溢出:

require(balanceOf[msg.sender]-value>=0);
balanceOf[msg.sender]-=value;
balanceOf[to]+=value;

原因就是balanceOf[msg.sender]value都是uint类型,因此它们相减的结果也一定是uint类型,一定是>=0的,因此这个require一定满足,然后就是balanceOf[msg.sender]-=value;,存在下溢出,因此非常好利用。

但是问题就是,它是被onlySecret修饰的:

    modifier onlySecret() {
        require(msg.sender == secret);
        _;
    }

没法绕过,就很迷。后来学了一下别的师傅的WP,原来这题还有另外一个考点,就是Uninitialized Storage Pointer。

注意到ubw函数,虽然我一开始也注意到了,就是else里的n是没有初始化的。

    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会被当成一个指针,而且默认指向slot[0]slot[1],因此修改n.nodeaddress和n.nodenumber,就是修改这两个:

    address secret;
    uint count;

因此secret可以覆盖成msg.sender,至此这题就全部绕过了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

其实对于Uninitialized Storage Pointer还是有些懵,还是自己solidity没有学的扎实,接下来应该还会再写一篇关于Uninitialized Storage Pointer的理解,但是可能还是不够那么的理解,也算是正常叭。当时自己学PHP的反序列化的时候也是感觉很懵,后来接触的越来越多,学的东西越来越多,对于原理和基础理解的越来越深,也就渐渐的很明白了,所以慢慢来,循序渐进,先去查一下solidity手册来解一下疑惑。

;原文链接:https://blog.csdn.net/rfrder/article/details/115614955
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐