コード例 #1
0
def decode(code):
    dis = Disassembly(code)
    asm = dis.get_easm()
    tmp = dict()
    for line in asm.splitlines():
        lst = line.split()
        tmp[lst[0]] = ' '.join(lst[1:])
    return (json.dumps(dis.address_to_function_name), json.dumps(tmp))
コード例 #2
0
    def test_easm_from_solidity_files(self):
        for input_file in TESTDATA_INPUTS.iterdir():
            output_expected = TESTDATA_OUTPUTS_EXPECTED / (input_file.name + ".easm")
            output_current = TESTDATA_OUTPUTS_CURRENT / (input_file.name + ".easm")

            code = input_file.read_text()
            disassembly = Disassembly(code)
            output_current.write_text(disassembly.get_easm())

            if not (output_expected.read_text() == output_current.read_text()):
                self.found_changed_files(input_file, output_expected, output_current)

        self.assert_and_show_changed_files()
コード例 #3
0
ファイル: ethcontract.py プロジェクト: m-zk/Ethsescan
class ETHContract(persistent.Persistent):
    def __init__(self, code, creation_code="", name="Unknown"):

        self.creation_code = creation_code
        self.name = name

        # Workaround: We currently do not support compile-time linking.
        # Dynamic contract addresses of the format __[contract-name]_____________ are replaced with a generic address

        code = re.sub(r'(_+.*_+)', 'aa' * 20, code)

        self.code = code
        self.disassembly = Disassembly(self.code)

    def as_dict(self):

        return {
            'address': self.address,
            'name': self.name,
            'code': self.code,
            'creation_code': self.creation_code,
            'disassembly': self.disassembly
        }

    def get_easm(self):

        return self.disassembly.get_easm()

    def matches_expression(self, expression):

        str_eval = ''
        easm_code = None

        tokens = filter(
            None,
            re.split("(and|or|not)", expression.replace(" ", ""),
                     re.IGNORECASE))

        for token in tokens:

            if token in ("and", "or", "not"):
                str_eval += " " + token + " "
                continue

            m = re.match(r'^code#([a-zA-Z0-9\s,\[\]]+)#', token)

            if (m):
                if easm_code is None:
                    easm_code = self.get_easm()

                code = m.group(1).replace(",", "\\n")
                str_eval += "\"" + code + "\" in easm_code"
                continue

            m = re.match(r'^func#([a-zA-Z0-9\s_,(\\)\[\]]+)#$', token)

            if (m):

                sign_hash = "0x" + utils.sha3(m.group(1))[:4].hex()

                str_eval += "\"" + sign_hash + "\" in self.disassembly.func_hashes"

                continue

        return eval(str_eval.strip())
コード例 #4
0
class EVMContract(persistent.Persistent):
    """This class represents an address with associated code (Smart
    Contract)."""

    def __init__(
        self, code="", creation_code="", name="Unknown", enable_online_lookup=False
    ):
        """Create a new contract.

        Workaround: We currently do not support compile-time linking.
        Dynamic contract addresses of the format __[contract-name]_____________ are replaced with a generic address
        Apply this for creation_code & code

        :param code:
        :param creation_code:
        :param name:
        :param enable_online_lookup:
        """
        creation_code = re.sub(r"(_{2}.{38})", "aa" * 20, creation_code)
        code = re.sub(r"(_{2}.{38})", "aa" * 20, code)

        self.creation_code = creation_code
        self.name = name
        self.code = code
        self.disassembly = Disassembly(code, enable_online_lookup=enable_online_lookup)
        self.creation_disassembly = Disassembly(
            creation_code, enable_online_lookup=enable_online_lookup
        )

    @property
    def bytecode_hash(self):
        """

        :return: runtime bytecode hash
        """
        return get_code_hash(self.code)

    @property
    def creation_bytecode_hash(self):
        """

        :return: Creation bytecode hash
        """
        return get_code_hash(self.creation_code)

    def as_dict(self):
        """

        :return:
        """
        return {
            "name": self.name,
            "code": self.code,
            "creation_code": self.creation_code,
            "disassembly": self.disassembly,
        }

    def get_easm(self):
        """

        :return:
        """
        return self.disassembly.get_easm()

    def get_creation_easm(self):
        """

        :return:
        """
        return self.creation_disassembly.get_easm()

    def matches_expression(self, expression):
        """

        :param expression:
        :return:
        """
        str_eval = ""
        easm_code = None

        tokens = re.split("\s+(and|or|not)\s+", expression, re.IGNORECASE)

        for token in tokens:

            if token in ("and", "or", "not"):
                str_eval += " " + token + " "
                continue

            m = re.match(r"^code#([a-zA-Z0-9\s,\[\]]+)#", token)

            if m:
                if easm_code is None:
                    easm_code = self.get_easm()

                code = m.group(1).replace(",", "\\n")
                str_eval += '"' + code + '" in easm_code'
                continue

            m = re.match(r"^func#([a-zA-Z0-9\s_,(\\)\[\]]+)#$", token)

            if m:

                sign_hash = "0x" + utils.sha3(m.group(1))[:4].hex()

                str_eval += '"' + sign_hash + '" in self.disassembly.func_hashes'

                continue

        return eval(str_eval.strip())
コード例 #5
0
ファイル: ethcontract.py プロジェクト: nbanmp/mythril
class ETHContract(persistent.Persistent):
    def __init__(self,
                 code,
                 creation_code="",
                 name="Unknown",
                 enable_online_lookup=False):

        # Workaround: We currently do not support compile-time linking.
        # Dynamic contract addresses of the format __[contract-name]_____________ are replaced with a generic address
        # Apply this for creation_code & code

        creation_code = re.sub(r"(_{2}.{38})", "aa" * 20, creation_code)
        code = re.sub(r"(_{2}.{38})", "aa" * 20, code)

        self.creation_code = creation_code
        self.name = name
        self.code = code
        self.disassembly = Disassembly(
            code, enable_online_lookup=enable_online_lookup)
        self.creation_disassembly = Disassembly(
            creation_code, enable_online_lookup=enable_online_lookup)

    def as_dict(self):

        return {
            "address": self.address,
            "name": self.name,
            "code": self.code,
            "creation_code": self.creation_code,
            "disassembly": self.disassembly,
        }

    def get_easm(self):

        return self.disassembly.get_easm()

    def matches_expression(self, expression):

        str_eval = ""
        easm_code = None

        tokens = re.split("\s+(and|or|not)\s+", expression, re.IGNORECASE)

        for token in tokens:

            if token in ("and", "or", "not"):
                str_eval += " " + token + " "
                continue

            m = re.match(r"^code#([a-zA-Z0-9\s,\[\]]+)#", token)

            if m:
                if easm_code is None:
                    easm_code = self.get_easm()

                code = m.group(1).replace(",", "\\n")
                str_eval += '"' + code + '" in easm_code'
                continue

            m = re.match(r"^func#([a-zA-Z0-9\s_,(\\)\[\]]+)#$", token)

            if m:

                sign_hash = "0x" + utils.sha3(m.group(1))[:4].hex()

                str_eval += '"' + sign_hash + '" in self.disassembly.func_hashes'

                continue

        return eval(str_eval.strip())
コード例 #6
0
        In this example, we'll only check one of the refernced contracts contains the initWallet() function
        If it does, we save the disassembly and callgraph for further analysis
        
        '''
 
        for xref in xrefs:
            code = homestead.eth_getCode(xref)

            disassembly = Disassembly(code)

            if contract.matches_expression("func#initWallet(address[],uint256,uint256)#"):
                print ("initWallet() in referenced library contract: " + xref)

                # Save list of contracts that forward calls to this library contract

                cwd = os.getcwd()

                with open("contracts_calling_" + xref + ".txt", "w") as f:
                    addresses = contract_storage.instance_lists[k].addresses

                    f.write("\n".join(addresses))

                easm = disassembly.get_easm()

                with open("library_" + xref + ".easm", "w") as f:
                    f.write(easm)

                generate_callgraph(disassembly, os.path.join(cwd, "library_" + xref))