Ejemplo n.º 1
0
def _detect_token_reentrant(contract: Contract) -> Dict[Function, List[Node]]:
    ret: Dict[Function, List[Node]] = defaultdict(list)
    for function in contract.functions_entry_points:
        if function.full_name in [
            "transfer(address,uint256)",
            "transferFrom(address,address,uint256)",
        ]:
            for ir in function.all_slithir_operations():
                if isinstance(ir, (LowLevelCall, HighLevelCall)):
                    if not function.parameters:
                        continue
                    if any(
                        (
                            is_dependent(ir.destination, parameter, function)
                            for parameter in function.parameters
                        )
                    ):
                        ret[function].append(ir.node)
                    if is_dependent(
                        ir.destination, SolidityVariableComposed("msg.sender"), function
                    ):
                        ret[function].append(ir.node)
                    if is_dependent(
                        ir.destination, SolidityVariableComposed("tx.origin"), function
                    ):
                        ret[function].append(ir.node)
    return ret
Ejemplo n.º 2
0
def _call_a_parameter(slither: SlitherCore) -> Dict[str, List[Dict]]:
    """
    Detect the functions with external calls
    :param slither:
    :return:
    """
    # contract -> [ (function, idx, interface_called) ]
    ret: Dict[str, List[Dict]] = defaultdict(list)
    for contract in slither.contracts:  # pylint: disable=too-many-nested-blocks
        for function in contract.functions_entry_points:
            for ir in function.all_slithir_operations():
                if isinstance(ir, HighLevelCall):
                    for idx, parameter in enumerate(function.parameters):
                        if is_dependent(ir.destination, parameter, function):
                            ret[contract.name].append(
                                {
                                    "function": _get_name(function),
                                    "parameter_idx": idx,
                                    "signature": _get_name(ir.function),
                                }
                            )
                if isinstance(ir, LowLevelCall):
                    for idx, parameter in enumerate(function.parameters):
                        if is_dependent(ir.destination, parameter, function):
                            ret[contract.name].append(
                                {
                                    "function": _get_name(function),
                                    "parameter_idx": idx,
                                    "signature": None,
                                }
                            )
    return ret
Ejemplo n.º 3
0
    def arbitrary_send(self, func):
        """
        """
        if func.is_protected():
            return []

        ret = []
        for node in func.nodes:
            for ir in node.irs:
                if isinstance(ir, SolidityCall):
                    if ir.function == SolidityFunction('ecrecover(bytes32,uint8,bytes32,bytes32)'):
                        return False
                if isinstance(ir, Index):
                    if ir.variable_right == SolidityVariableComposed('msg.sender'):
                        return False
                    if is_dependent(ir.variable_right, SolidityVariableComposed('msg.sender'), func.contract):
                        return False
                if isinstance(ir, (HighLevelCall, LowLevelCall, Transfer, Send)):
                    if isinstance(ir, (HighLevelCall)):
                        if isinstance(ir.function, Function):
                            if ir.function.full_name == 'transferFrom(address,address,uint256)':
                                return False
                    if ir.call_value is None:
                        continue
                    if ir.call_value == SolidityVariableComposed('msg.value'):
                        continue
                    if is_dependent(ir.call_value, SolidityVariableComposed('msg.value'), func.contract):
                        continue

                    if is_tainted(ir.destination, func.contract, self.slither):
                        ret.append(node)


        return ret
Ejemplo n.º 4
0
 def _arbitrary_from(nodes: List[Node], results: List[Node]):
     """Finds instances of (safe)transferFrom that do not use msg.sender or address(this) as from parameter."""
     for node in nodes:
         for ir in node.irs:
             if (isinstance(ir, HighLevelCall)
                     and isinstance(ir.function, Function)
                     and ir.function.solidity_signature
                     == "transferFrom(address,address,uint256)"
                     and not (is_dependent(
                         ir.arguments[0],
                         SolidityVariableComposed("msg.sender"),
                         node.function.contract,
                     ) or is_dependent(
                         ir.arguments[0],
                         SolidityVariable("this"),
                         node.function.contract,
                     ))):
                 results.append(ir.node)
             elif (isinstance(ir, LibraryCall)
                   and ir.function.solidity_signature
                   == "safeTransferFrom(address,address,address,uint256)"
                   and not (is_dependent(
                       ir.arguments[1],
                       SolidityVariableComposed("msg.sender"),
                       node.function.contract,
                   ) or is_dependent(
                       ir.arguments[1],
                       SolidityVariable("this"),
                       node.function.contract,
                   ))):
                 results.append(ir.node)
Ejemplo n.º 5
0
    def timestamp(self, func):
        """
        """

        ret = set()
        for node in func.nodes:
            if node.contains_require_or_assert():
                for var in node.variables_read:
                    if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract):
                        ret.add(node)
            for ir in node.irs:
                if isinstance(ir, Binary) and BinaryType.return_bool(ir.type):
                    for var in ir.read:
                        if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract):
                            ret.add(node)
        return list(ret)
Ejemplo n.º 6
0
    def advancedUpdateEth_2(self, function):
        from slither.analyses.data_dependency.data_dependency import is_dependent
        allNodes = function.nodes
        for ethNode in function.ethNodes:
            entryPointToethNode = []
            entryPointToethNode.append(function.entry_point)
            pilotProcessNodes = list(
                set(allNodes) - set([function.entry_point, ethNode]))
            entryPointToethNode.extend(pilotProcessNodes)
            entryPointToethNode.append(ethNode)

            adjMatrix = getadjMatrix(entryPointToethNode)
            mydeepGraph = MyDeepGraph(len(entryPointToethNode))
            mydeepGraph.setadjMetrix(adjMatrix)
            allPaths = mydeepGraph.getPathofTwoNode(
                0,
                len(entryPointToethNode) - 1)
            allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode)

            for path in allPaths_Node:
                for ir in path[-1].irs:
                    if isinstance(
                            ir, (HighLevelCall, LowLevelCall, Transfer, Send)):
                        if ir.call_value:
                            for node in path[0:len(path) - 1]:
                                for stateVariableWritten in node.state_variables_written:
                                    if is_dependent(ir.call_value,
                                                    stateVariableWritten,
                                                    function.contract):
                                        return True
                                    # elif is_dependent(stateVariableWritten, ir.call_value, function.contract):
                                    #     return True
            return False
Ejemplo n.º 7
0
def _timestamp(func: Function) -> List[Node]:
    ret = set()
    for node in func.nodes:
        if node.contains_require_or_assert():
            for var in node.variables_read:
                if is_dependent(var, SolidityVariableComposed("block.timestamp"), func.contract):
                    ret.add(node)
                if is_dependent(var, SolidityVariable("now"), func.contract):
                    ret.add(node)
        for ir in node.irs:
            if isinstance(ir, Binary) and BinaryType.return_bool(ir.type):
                for var in ir.read:
                    if is_dependent(
                        var, SolidityVariableComposed("block.timestamp"), func.contract
                    ):
                        ret.add(node)
                    if is_dependent(var, SolidityVariable("now"), func.contract):
                        ret.add(node)
    return sorted(list(ret), key=lambda x: x.node_id)
 def inspect_index_ir(self, ir, index_usage: Dict[Variable, Dict[int, Set[StateVariableSolc]]]):
     params = self.slither_function.parameters + self.slither_function.solidity_variables_read
     for param in params:
         if is_dependent(ir.variable_right, param, self.parent_contract.slither_contract):
             level = 0
             temp = ir.variable_left
             while isinstance(temp, ReferenceVariable):
                 temp = temp.points_to
                 level += 1
             if isinstance(temp, StateVariableSolc):
                 index_usage[param][level].add(temp)
def arbitrary_send(func: Function):
    if func.is_protected():
        return []

    ret: List[Node] = []
    for node in func.nodes:
        for ir in node.irs:
            if isinstance(ir, SolidityCall):
                if ir.function == SolidityFunction("ecrecover(bytes32,uint8,bytes32,bytes32)"):
                    return False
            if isinstance(ir, Index):
                if ir.variable_right == SolidityVariableComposed("msg.sender"):
                    return False
                if is_dependent(
                    ir.variable_right,
                    SolidityVariableComposed("msg.sender"),
                    func.contract,
                ):
                    return False
            if isinstance(ir, (HighLevelCall, LowLevelCall, Transfer, Send)):
                if isinstance(ir, (HighLevelCall)):
                    if isinstance(ir.function, Function):
                        if ir.function.full_name == "transferFrom(address,address,uint256)":
                            return False
                if ir.call_value is None:
                    continue
                if ir.call_value == SolidityVariableComposed("msg.value"):
                    continue
                if is_dependent(
                    ir.call_value,
                    SolidityVariableComposed("msg.value"),
                    func.contract,
                ):
                    continue

                if is_tainted(ir.destination, func.contract):
                    ret.append(node)

    return ret
Ejemplo n.º 10
0
    def call_in_loop(f, node, in_loop, visited, ret, loopsum):
        if node in visited:
            return
        # shared visited
        visited.append(node)

        if node.type == NodeType.STARTLOOP:
            loopsum.append('hasloop')
            # print('>>>>>>>>>>>>>begin loop')
            in_loop = True
            # is_tainted_by_arg, is_tainted_by_statevar, is_tained_by_local, has_transaction, has_lib_call, has_nested_loop = MultipleCallsInLoop.collect_summary(node, f)
            # print('Loop Summary----', 'has_nested_loop:', has_nested_loop, 'has_lib_call:', has_lib_call, 'has_transaction:', has_transaction,
            #             'is_tained_by_local:', is_tained_by_local, 'is_tainted_by_arg:', is_tainted_by_arg, 'is_tainted_by_statevar:', is_tainted_by_statevar )

        elif node.type == NodeType.ENDLOOP:
            # print('<<<<<<<<<<<<<exit loop')
            in_loop = False

        if in_loop:
            has_nested_loop = any(
                (son.type == NodeType.STARTLOOP) for son in node.sons)
            if has_nested_loop:
                loopsum.append('nested_loop')
            for ir in node.irs:
                if isinstance(ir,
                              (LowLevelCall, HighLevelCall, Send, Transfer)):
                    if isinstance(ir, LibraryCall):
                        has_lib_call = True
                        loopsum.append('lib_call')
                    else:
                        has_transaction = True
                        loopsum.append('transaction')

                if isinstance(ir, Condition):
                    is_tainted_by_arg = is_tainted(ir.value, f)
                    is_tainted_by_statevar = any(
                        is_dependent(ir.value, t, f)
                        for t in f.contract.state_variables)
                    is_tained_by_local = not (is_tainted_by_arg
                                              or is_tainted_by_statevar)
                    # print(is_tainted_by_arg, is_tainted_by_statevar, is_tained_by_local, node, type(node))
                    if is_tainted_by_arg:
                        loopsum.append('tainted_by_arg')
                    if is_tainted_by_statevar:
                        loopsum.append('tainted_by_statevar')
                    if is_tained_by_local:
                        loopsum.append('tained_by_local')

        for son in node.sons:
            MultipleCallsInLoop.call_in_loop(f, son, in_loop, visited, ret,
                                             loopsum)
Ejemplo n.º 11
0
from slither import Slither
from slither.analyses.data_dependency.data_dependency import is_dependent, is_tainted, pprint_dependency
from slither.core.declarations.solidity_variables import SolidityVariableComposed

slither = Slither('data_dependency.sol')

contract = slither.get_contract_from_name('Simple')

destination = contract.get_state_variable_from_name('destination')
source = contract.get_state_variable_from_name('source')

print('{} is dependent of {}: {}'.format(
    source, destination, is_dependent(source, destination, contract)))
assert not is_dependent(source, destination, contract)
print('{} is dependent of {}: {}'.format(
    destination, source, is_dependent(destination, source, contract)))
assert is_dependent(destination, source, contract)
print('{} is tainted {}'.format(source, is_tainted(source, contract, slither)))
assert not is_tainted(source, contract, slither)
print('{} is tainted {}'.format(destination,
                                is_tainted(destination, contract, slither)))
assert is_tainted(destination, contract, slither)

contract = slither.get_contract_from_name('Reference')

destination = contract.get_state_variable_from_name('destination')
source = contract.get_state_variable_from_name('source')

print('Reference contract')
print('{} is dependent of {}: {}'.format(
    source, destination, is_dependent(source, destination, contract)))
Ejemplo n.º 12
0
    def advancedUpdateEth(self, function):
        from slither.analyses.data_dependency.data_dependency import is_dependent

        allNodes = function.nodes
        for ethNode in function.ethNodes:
            entryPointToethNode = []
            entryPointToethNode.append(function.entry_point)
            pilotProcessNodes = list(
                set(allNodes) - set([function.entry_point, ethNode]))
            entryPointToethNode.extend(pilotProcessNodes)
            entryPointToethNode.append(ethNode)

            adjMatrix = getadjMatrix(entryPointToethNode)
            mydeepGraph = MyDeepGraph(len(entryPointToethNode))
            mydeepGraph.setadjMetrix(adjMatrix)
            allPaths = mydeepGraph.getPathofTwoNode(
                0,
                len(entryPointToethNode) - 1)
            allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode)

            for path in allPaths_Node[:]:

                careifNodeStack = []
                care_if_StateVariablesRead = set()
                care_RequireOrAssert_StateVariableRead = set()
                state_variables_written = set()
                for node in path:  # [start, end]    # 直接转帐函数cfg上的路径节点
                    if node.contains_require_or_assert():
                        care_RequireOrAssert_StateVariableRead |= set(
                            node.state_variables_read)
                    state_variables_written |= set(
                        node.state_variables_written)
                    if node.type == NodeType.IF:
                        for son in node.sons:
                            if son.type == NodeType.THROW or son.type == NodeType.RETURN:
                                careifNodeStack.append(node)
                    if node.type == NodeType.IF:
                        careifNodeStack.append(node)
                    if node.type == NodeType.ENDIF:
                        if careifNodeStack:
                            careifNodeStack.pop()
                if careifNodeStack:  # eth被包裹在if中
                    for careifNode in careifNodeStack:
                        care_if_StateVariablesRead |= set(
                            careifNode.state_variables_read)
                    for stateVariableWritten in state_variables_written:
                        for careStateVariableRead in care_if_StateVariablesRead | care_RequireOrAssert_StateVariableRead:
                            result = is_dependent(stateVariableWritten,
                                                  careStateVariableRead,
                                                  function.contract)
                            if result == True:
                                return True
                                # allPaths_Node.remove(path)

                else:  # 如果 转账语句不在if block中
                    for stateVariableWritten in state_variables_written:
                        for careStateVariableRead in care_RequireOrAssert_StateVariableRead:
                            result = is_dependent(stateVariableWritten,
                                                  careStateVariableRead,
                                                  function.contract)
                            if result == True:
                                return True
                                #allPaths_Node.remove(path)
                                #return False
            # if allPaths_Node:
            #     return False
        return False
from slither.core.declarations.solidity_variables import SolidityVariableComposed

if len(sys.argv) != 2:
    print("Usage: python data_dependency.py file.sol")
    sys.exit(-1)

slither = Slither(sys.argv[1])

contracts = slither.get_contract_from_name("Simple")
assert len(contracts) == 1
contract = contracts[0]
destination = contract.get_state_variable_from_name("destination")
source = contract.get_state_variable_from_name("source")

print(f"{source} is dependent of {destination}: {is_dependent(source, destination, contract)}")
assert not is_dependent(source, destination, contract)
print(f"{destination} is dependent of {source}: {is_dependent(destination, source, contract)}")
assert is_dependent(destination, source, contract)
print(f"{source} is tainted {is_tainted(source, contract)}")
assert not is_tainted(source, contract)
print(f"{destination} is tainted {is_tainted(destination, contract)}")
assert is_tainted(destination, contract)

contracts = slither.get_contract_from_name("Reference")
assert len(contracts) == 1
contract = contracts[0]
destination = contract.get_state_variable_from_name("destination")
assert destination
source = contract.get_state_variable_from_name("source")
assert source
Ejemplo n.º 14
0
    def advancedUpdateEth(self, function):  # PPT,检查程序执行锁
        from slither.analyses.data_dependency.data_dependency import is_dependent

        allNodes = function.nodes
        path_between_sender_and_if = []
        for ethNode in function.ethNodes:
            entryPointToethNode = []
            entryPointToethNode.append(function.entry_point)
            pilotProcessNodes = list(
                set(allNodes) - set([function.entry_point, ethNode]))
            entryPointToethNode.extend(pilotProcessNodes)
            entryPointToethNode.append(ethNode)

            adjMatrix = getadjMatrix(entryPointToethNode)
            mydeepGraph = MyDeepGraph(len(entryPointToethNode))
            mydeepGraph.setadjMetrix(adjMatrix)
            allPaths = mydeepGraph.getPathofTwoNode(
                0,
                len(entryPointToethNode) - 1)
            allPaths_Node = allPaths_intToNode(allPaths, entryPointToethNode)

            for path in allPaths_Node[:]:

                careifNodeStack = []
                care_if_StateVariablesRead = set()
                care_RequireOrAssert_StateVariableRead = set()
                state_variables_written = set()
                for node in path:  # [start, end]    # 直接转帐函数cfg上的路径节点
                    if node.contains_require_or_assert():
                        care_RequireOrAssert_StateVariableRead |= set(
                            node.state_variables_read)
                    state_variables_written |= set(
                        node.state_variables_written)
                    if node.type == NodeType.IF:
                        for son in node.sons:
                            if son.type == NodeType.THROW or son.type == NodeType.RETURN:
                                careifNodeStack.append(node)
                    if node.type == NodeType.IF:
                        careifNodeStack.append(node)
                        path_between_sender_and_if.append(node)
                    if node.type == NodeType.ENDIF:
                        if careifNodeStack:
                            careifNodeStack.pop()
                            path_between_sender_and_if = []
                    else:
                        path_between_sender_and_if.append(node)
                if careifNodeStack:  # 被包裹在if语句中的Node
                    for careifNode in careifNodeStack:
                        care_if_StateVariablesRead |= set(
                            careifNode.state_variables_read)

                    for stateVariableWritten in state_variables_written:
                        if len(care_if_StateVariablesRead
                               | care_RequireOrAssert_StateVariableRead) > 1:
                            return True
                        if len(care_if_StateVariablesRead
                               | care_RequireOrAssert_StateVariableRead) == 0:
                            return True
                        careStateVariableRead = list(
                            care_if_StateVariablesRead
                            | care_RequireOrAssert_StateVariableRead)[0]
                        for suspicious_node in path_between_sender_and_if:
                            ir_list = suspicious_node.irs_ssa
                            for ir in ir_list:
                                if isinstance(ir, Assignment):
                                    if hasattr(ir.lvalue, 'pure_name'):
                                        if ir.lvalue.pure_name == careStateVariableRead.name:
                                            r_v = ir.rvalue
                                    else:
                                        if ir.lvalue.name == careStateVariableRead.name:
                                            r_v = ir.rvalue
                                else:
                                    r_v = None
                                    continue
                        var_list_length = len(
                            care_if_StateVariablesRead
                            | care_RequireOrAssert_StateVariableRead)
                        for careifNode in careifNodeStack:
                            symbol_result = solve_expression(
                                careifNode.irs_ssa, r_v)
                            if symbol_result == False:
                                return True
                            else:
                                result = is_dependent(stateVariableWritten,
                                                      careStateVariableRead,
                                                      function.contract)
                                if result == True:
                                    return True  # TODO: 为什么这个位置是True
                                # allPaths_Node.remove(path)

                else:  # 如果 转账语句不在if block中
                    for stateVariableWritten in state_variables_written:
                        for careStateVariableRead in care_RequireOrAssert_StateVariableRead:
                            result = is_dependent(stateVariableWritten,
                                                  careStateVariableRead,
                                                  function.contract)
                            if result == True:
                                return True
                                #allPaths_Node.remove(path)
                                #return False
            # if allPaths_Node:
            #     return False
        return False