question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Slightly wrong concrete transaction data in multi-tx & multi-contract (delegatecall) scenario

See original GitHub issue

Description

Running Mythril on a relatively complex example appears to detect the correct bug, but returns slightly wrong concrete transaction data to reach it. Here is the code:

pragma solidity ^0.4.24;

contract EvilDelegate {

  bool xyz;

  function abc() public {
    // do nothing
    xyz = false;
  }
}

contract Wallet {

  bool private initialized = false;
  address public owner;
  EvilDelegate private _delegate;

  constructor(address _delegateAddress) public {
    _delegate = EvilDelegate(_delegateAddress);
  }
  
  // The owner can only be set once during initialization.
  function initWallet() public {
    require(initialized == false);
    initialized = true;
    owner = msg.sender;
  }

  // Dangerous! Can only be called by the owner!
  function kill() public {
      require(msg.sender == owner);
      selfdestruct(msg.sender);
  }
  
  function() public payable {
    if (msg.data.length > 0) {
      _delegate.delegatecall(msg.data);
    }
  }
}

Wallet is deployed on Ropsten with address 0xc2e75b81d21831c3bf6a739c3b1495c33045d258 and the owner has been initialized to 0x0583858adfe7d1d3DC7F8447301cf7B7b056d638.

Mythril output is as follows:

$ $MYTH --rpc infura-ropsten -msuicide -xla 0xc2e75b81d21831c3bf6a739c3b1495c33045d258 --transaction-count 3 --verbose-report
==== Unchecked SUICIDE ====
SWC ID: 106
Type: Warning
Contract: 0xc2e75b81d21831c3bf6a739c3b1495c33045d258
Function name: kill()
PC address: 572
A reachable SUICIDE instruction was detected. The remaining Ether is sent to the caller's address.

--------------------
--------------------
DEBUGGING INFORMATION:

Transaction Sequence: {'1': {'calldata': '0x00', 'call_value': None, 'caller': '0x0000000000000000000000000000000000000001'}, '6': {'calldata': '0x3e326048', 'call_value': '0x0', 'caller': '0x0000000000000000000000000000000000000001'}, '16': {'calldata': '0x41c0e1b5', 'call_value': '0x0', 'caller': '0x0000000000000000000000000000000000000001'}}

Expected behavior

Theoretically the correct call data for the 3-tx “exploitation” sequence is:

  • ‘0x92277933’ -> call abc() which is forwarded through the delegate call proxy and sets initialized to false
  • ‘0x3e326048’ -> call initWallet() which set owner to msg.sender
  • ‘0x41c0e1b5’ -> call kill()

The output produced by Mythril is:

  • ‘0x00’ -> empty calldata
  • ‘0x3e326048’ -> call initWallet() which set owner to msg.sender
  • ‘0x41c0e1b5’ -> call kill()

Might be something wrong in processing calldata passed between contracts in the delegatecall, or an issue resolving storage.

Note that without the -l flag no issue is detected (which is expected behavior).

Environment

  • Mythril version: Develop
  • Python version: python -V
  • OS and Version: Mac OS Mojave

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

3reactions
palkeocommented, Aug 7, 2019

I’m finally able to reproduce. I found various regressions before being able to:

  • the mutation pruner will apparently prune transactions where the delegatecall caused SSTORE. This led to not being able to simulate more than one transaction. By propagating the annotations to the parent transaction this fixes it.
  • in Storage, printable_storage is emptied every time it is copied (because of a wrong variable name)
  • after fixing the previous point, the json serialization of reports crashes
  • my fix for #1176 was wrong, and currently is causes the new owner address to be overwritten by another read from the blockchain storage.

I’ll try to come up with fixes for these, and then fix the actual problem. Also I think the current behavior is not so bad: better to unconstrain the input so we catch the bug, even if it’s slightly wrong.

0reactions
nbanmpcommented, Dec 6, 2018

https://github.com/ConsenSys/mythril-classic/pull/739 and #693 have been closed. Some good progress, but not good enough and they don’t fix the issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamic loader does not retrieve map items #1176 - GitHub
Mythril on-chain analysis is unable to dynamically retrieve the content of map items from the blockchain, resulting in false positives.
Read more >
Gnosis Safe: Unexpected Delegate call while sending multiple ...
Due to security reasons this warning is shown if a multisend contract is used that is not "known" by our services. As delegatecalls...
Read more >
Multi Delegatecall | Solidity 0.8 - YouTube
Batch transactions with multi delegatecall.#Solidity #SmartContract #Ethereum #スマートコントラクトRemixhttps://remix.ethereum.
Read more >
Mythril Documentation - Read the Docs
This module contains the detection code to find multiple sends occurring in a single transaction. class mythril.analysis.module.modules.
Read more >
An Automatic Repair Framework for On-Chain Smart Contracts
The core insight of Aroc is to generate patch contracts to abort malicious transactions in advance. Taking the three most serious bug types...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found