2

I'm trying to understand this array overflow attack on Solidity. (https://www.youtube.com/watch?v=gUqHgFuSsqg)

In that video, the code is basically like this

pragma solidity ^0.4.17; 

contract ArrayOverflow{
    uint256 public target = 10;
    uint256[] public array = [9,8];

    function modifyArray (uint256 _index, uint256 _value){
        array[_index] = _value;
    }

    function popLength() public{
        // cause overflow
        array.length--;
    }

    function getLength() constant returns(uint256){
        return array.length;
    }

}

What he did is call popLength() three times to make the array overflowed.

After the above step, we can see the storage loaded is like this

enter image description here

So the 0xfffffff...fff is the length value.

Then we convert the hexadecimal value to address.

   web3.sha3('0x0000000000000000000000000000000000000000000000000000000000000001', {encoding: 'hex'})
// => 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6

The following part is what I felt confused.

He exeuted the following command to find the address of target

perl -Mbigint -E 'say ((2**256 - 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6 + 0)->as_hex)'

The output magically becomes the address of target, how does that happen?

2
  • I think you mean the address of target.
    – user19510
    May 5, 2019 at 16:05
  • Sorry, that's my fault. I 've edited it.
    – rj487
    May 5, 2019 at 17:10

1 Answer 1

4

I believe you mean the address of target, not the address of X (which is a smart contract). In the video you linked to, that variable is called x (lowercase).

https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/ may help you understand the layout of storage.

array is the second state variable in the contract, so it's located at slot 1. For a dynamic array, that means the length is stored at slot 1, and the actual array data starts at keccak256(uint256(1)). You've computed that as 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6. The second element of the array will be at 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7, etc. (adding 1 each time).

Now the trick is to figure out what element of the array occupies the same storage as target. Because target is the first state variable in the contract, it's located at slot 0. Due to integer overflow, we can also find this at 2**256. So we take 2**256 - 0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6, and that gives us our offset (array index).

1
  • Thanks for your effort, that's a good explanation!
    – rj487
    May 5, 2019 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.