crytic / ethersplay

EVM dissassembler
GNU Affero General Public License v3.0
834 stars 116 forks source link

Jumpdests in immediates should be treated as invalid #29

Closed itszn closed 6 years ago

itszn commented 6 years ago

EVM does not allow jumping to jumpdests that happen to be in immediate values (ie pushed values).

For example something like this contract.

pragma solidity ^0.4.0;
contract Jump {
    function test() public {
        assembly {
            let b := add(0x5b604160425500,1)
            jump(0x5a)
        }
    }
}

When calling test(), EVM will always throw when it tries to execute the jump. However ethersplay shows it falling though to the embedded code:

Geth makes a bitmap of all valid jumpdests to determine if any jumpdests are in immediate values.

Code in this form probably won't be generated naturally, but it could be used for obfuscation. By jumping into a function hash in the dispatch (like my recent challenge did), I was able to confuse ethersplay into producing a loop and being unable to identify the dispatched functions:

(I use a function aekS() which hashes to 0x5b61291c, jumpdest; push2 XX)

joshwatson commented 6 years ago

I pushed a fix for this to the RewriteStackValue branch; it definitely fixes the example contract.