From c1c9e0da2c69948dbcbd63ea40ff5a956a479973 Mon Sep 17 00:00:00 2001 From: Nikhil Parasaram Date: Thu, 8 Sep 2022 17:32:26 +0200 Subject: [PATCH] Fix JSON serialisation issue (#1687) --- README.md | 18 +++++++++++++----- mythril/analysis/report.py | 12 ++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) 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: