diff --git a/README.md b/README.md index 8913b300..4454d793 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ $ myth analyze -a Specify the maximum number of transaction to explore with `-t `. You can also set a timeout with `--execution-timeout `. +Here is an example of running Mythril on the file `killbilly.sol` which is in the `solidity_examples` directory for `3` transactions: + ``` > myth a killbilly.sol -t 3 ==== Unprotected Selfdestruct ==== @@ -58,21 +60,27 @@ Severity: High Contract: KillBilly Function name: commencekilling() PC address: 354 -Estimated Gas Usage: 574 - 999 -The contract can be killed by anyone. -Anyone can kill this contract and withdraw its balance to an arbitrary address. +Estimated Gas Usage: 974 - 1399 +Any sender can cause the contract to self-destruct. +Any sender can trigger execution of the SELFDESTRUCT instruction to destroy this contract account and withdraw its balance to an arbitrary address. Review the transaction trace generated for this issue and make sure that appropriate security controls are in place to prevent unrestricted access. -------------------- In file: killbilly.sol:22 selfdestruct(msg.sender) -------------------- +Initial State: + +Account: [CREATOR], balance: 0x2, nonce:0, storage:{} +Account: [ATTACKER], balance: 0x1001, nonce:0, storage:{} + Transaction Sequence: -Caller: [CREATOR], data: [CONTRACT CREATION], value: 0x0 -Caller: [ATTACKER], function: killerize(address), txdata: 0x9fa299ccbebebebebebebebebebebebedeadbeefdeadbeefdeadbeefdeadbeefdeadbeef, value: 0x0 +Caller: [CREATOR], calldata: , decoded_data: , value: 0x0 +Caller: [ATTACKER], function: killerize(address), txdata: 0x9fa299cc000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, decoded_data: ('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',), value: 0x0 Caller: [ATTACKER], function: activatekillability(), txdata: 0x84057065, value: 0x0 Caller: [ATTACKER], function: commencekilling(), txdata: 0x7c11da20, value: 0x0 + ``` diff --git a/mythril/analysis/report.py b/mythril/analysis/report.py index 403c9e62..b095816d 100644 --- a/mythril/analysis/report.py +++ b/mythril/analysis/report.py @@ -198,6 +198,17 @@ class Issue: step["resolved_input"] = Issue.resolve_input( step["calldata"], sig[0] ) + if step["resolved_input"] is not None: + step["resolved_input"] = list(step["resolved_input"]) + for i, val in enumerate(step["resolved_input"]): + if type(val) != bytes: + continue + # Some of the bytes violate UTF-8 and UTF-16 translates the input to Japanese + # We cannot directly use bytes, as it's not serialisable using JSON, hence this hack. + step["resolved_input"][i] = str(step["resolved_input"][i]) + + step["resolved_input"] = tuple(step["resolved_input"]) + else: step["name"] = "unknown" except ValueError: @@ -288,6 +299,7 @@ class Report: :return: """ result = {"success": True, "error": None, "issues": self.sorted_issues()} + return json.dumps(result, sort_keys=True) def _get_exception_data(self) -> dict: