mythril--arbitrary_jump.py(任意跳转)

arbitrary_jump.py(任意跳转)

该模块包含对于任意跳转的检测代码。

"""This module contains the detection code for Arbitrary jumps."""
import logging
from mythril.analysis.solver import get_transaction_sequence, UnsatError
from mythril.analysis.module.base import DetectionModule, Issue, EntryPoint
from mythril.analysis.swc_data import ARBITRARY_JUMP
from mythril.laser.ethereum.state.global_state import GlobalState

log = logging.getLogger(__name__)    #记录日志

# 搜索跳转到字节码中的任意位置
DESCRIPTION = """

Search for jumps to arbitrary locations in the bytecode
"""

# 继承自DetectionModule (DetectionModule位于mythril.analysis.module.base.py)
 """
    There are several class properties that expose information about the detection modules
    - name: The name of the detection module      # 检测模块的名称
    - swc_id: The SWC ID associated with the weakness that the module detects  # 与模块检测到的弱点关联的 SWC ID
    - description: A description of the detection module, and what it detects  # 检测模块及其检测内容的说明
    - entry_point: Mythril can run callback style detection modules, or modules that search the statespace.
                [IMPORTANT] POST entry points severely slow down the analysis, try to always use callback style modules
    - pre_hooks: A list of instructions to hook the laser vm for (pre execution of the instruction)
    - post_hooks: A list of instructions to hook the laser vm for (post execution of the instruction)
    """
    
class ArbitraryJump(DetectionModule):
    """This module searches for JUMPs to a user-specified location."""  # 此模块搜索到用户指定位置的 JUMP

    name = "Caller can redirect execution to arbitrary bytecode locations"
    swc_id = ARBITRARY_JUMP    # “127”
    description = DESCRIPTION
    entry_point = EntryPoint.CALLBACK   #  CALLBACK = 2
    pre_hooks = ["JUMP", "JUMPI"]

    def reset_module(self):
        """
        Resets the module by clearing everything
        :return:
        """
        super().reset_module()    # 使用父模块的reset_module()方法

    def _execute(self, state: GlobalState) -> None:
        """

        :param state:
        :return:
        """
        # 获取此全局状态的当前指令  instruction_list:反汇编 evm 字节码并返回指令列表。
        if state.get_current_instruction()["address"] in self.cache:
            return
        self.issues.extend(self._analyze_state(state))

    @staticmethod
    def _analyze_state(state):
        """

        :param state:
        :return:
        """

        jump_dest = state.mstate.stack[-1]   # 要跳转的地址
        if jump_dest.symbolic is False:      # 判断是不是符号化,是符号化的话就是不确定的,可以根据输入改变,会跳到不同的地址
            return []
        # Most probably the jump destination can have multiple locations in these circumstances
        try:
         """
		    约束条件有:
		    	UGE(max_calldata_size, transaction.call_data.calldatasize)
		    	UGE(
                	symbol_factory.BitVecVal(1000000000000000000000, 256),
                	world_state.starting_balances[transaction.caller],
            	)
            	UGE(
                	symbol_factory.BitVecVal(100000000000000000000, 256),
                	world_state.starting_balances[account.address],
            	)
         """
         # transaction_sequence 如果不为空,说明有解,说明存在问题
            transaction_sequence = get_transaction_sequence(
                state, state.world_state.constraints
            )
        except UnsatError:
            return []
        issue = Issue(
            contract=state.environment.active_account.contract_name,   
            function_name=state.environment.active_function_name,
            address=state.get_current_instruction()["address"],        
            swc_id=ARBITRARY_JUMP,
            title="Jump to an arbitrary instruction",
            severity="High",
            bytecode=state.environment.code.bytecode,
            description_head="The caller can redirect execution to arbitrary bytecode locations.",
            description_tail="It is possible to redirect the control flow to arbitrary locations in the code. "
            "This may allow an attacker to bypass security controls or manipulate the business logic of the "
            "smart contract. Avoid using low-level-operations and assembly to prevent this issue.",
            gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used),
            transaction_sequence=transaction_sequence,
        )
        return [issue]


detector = ArbitraryJump()
posted @ 2021-12-28 19:36  不加糖不加奶  阅读(84)  评论(0)    收藏  举报