예제 #1
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
예제 #2
0
    def detect_reentrancy(self, contract, ethNodeList, taintNodeList, callGraph):
        print('Start Contract {}'.format(contract.name))
        for function in contract.functions:
            if function.is_implemented:
                print('\tTo analyze:{}.{}'.format(function.contract.name, function.full_name))
                dm = DM(function)   # 声明dm防御对象
                reentrancyFlag = False

                # for node in function.nodes:
                #     self._node_taint(node)



                function_ethNodeList = []   # 存储本函数体内的eth
                functon_taintNodeList = []  # 存储本函数体内的taint
                for node in function.nodes:
                    if node in taintNodeList:
                        functon_taintNodeList.append(node)
                    if node in ethNodeList:
                        function_ethNodeList.append(node)
                #
                for function_taintNode in functon_taintNodeList:
                    '''
                    startToend = [start, ... ,end]
                    '''
                    cfgEntryNodeTotaint = []
                    cfgEntryNodeTotaint.append(function.entry_point)
                    cfgEntryNodeTotaint.extend(list(set(function.nodes) - set([function.entry_point, function_taintNode])))
                    cfgEntryNodeTotaint.append(function_taintNode)

                    adjMatrix = getadjMatrix(cfgEntryNodeTotaint)
                    mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint))
                    mydeepGraph.setadjMetrix(adjMatrix)
                    cfgAllPath = mydeepGraph.getPathofTwoNode(0, len(cfgEntryNodeTotaint)-1)
                    cfgAllPath_Node = allPaths_intToNode(cfgAllPath, cfgEntryNodeTotaint)

                    cfgCandidateAllPath_Node = []
                    for path in cfgAllPath_Node[:]:
                       if any(iNode in ethNodeList for iNode in path):
                           cfgCandidateAllPath_Node.append(path)

                    if cfgCandidateAllPath_Node:   # 证明cfg本身就找到Reentrancy了,准备humanlook, 注意reversed, DM


                        human_cfgCandidateAllPath_Node = []
                        for path in cfgCandidateAllPath_Node:
                            tempPath = []
                            for everyNode in path:
                                if everyNode.type == NodeType.ENTRYPOINT:
                                    everyNode.add_expression('entryPoint')
                                tempPath.append(str(everyNode.expression))
                            human_cfgCandidateAllPath_Node.append(tempPath)
                        advanceUpdateFlag = dm.advancedUpdateEth(function)
                        privateVisibility = dm.privateVisibility(function)
                        havePublicCaller = callerVisibilityHavePublic(function, callGraph, dm)
                        haveDefenModifier = dm.haveDefenseModifier(function)
                        haveDefenRequire = dm.requireMsgSender(function)
                        #ethAdvanceUpdateFlag = dm.advancedUpdateEth_2(function)

                        if privateVisibility is True or haveDefenModifier is True or haveDefenRequire is True:
                            # print('privateVisibility: ', privateVisibility)
                            # print('haveDefenModifier: ', haveDefenModifier)
                            # print('haveDefenRequire: ', haveDefenRequire)
                            # print('function.is_protected() ', function.is_protected())
                            # accessPermision = True
                            # havePublicCaller = True
                            if havePublicCaller is True:
                                reentrancyFlag = True
                                print('\t\tcontract: {} | function: {} | accessPermision: {} | publicCaller: {} | 锁: {} '.format(
                                    function.contract.name, function.full_name, accessPermision, havePublicCaller, advanceUpdateFlag))
                                for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node:
                                    print('\t\t\tpath: {}'.format(human_cfgCandidatePath_Node))
                        else:
                            accessPermision = False
                            reentrancyFlag = True
                            print(
                                '\t\tcontract: {} | function: {} | accessPermision: {} | 锁: {}'.format(
                                    function.contract.name, function.full_name, accessPermision, advanceUpdateFlag))
                            for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node:
                                print('\t\t\tpath: {}'.format(human_cfgCandidatePath_Node))
                if reentrancyFlag is True:
                    print('[cfg_Reentrancy in] contract: {} . function: {} | {}'.format(function.contract.name, function.full_name, function.source_mapping_str))
                    continue


                if reentrancyFlag is False:  # 证明cfg本身没找到Reentrancy
                    careTaintNode = set()
                    careEthNode = set()
                    careTaintFunction = set()
                    careEthFunction = set()
                    callGraphToTaintAllPath_Node = []
                    callGraphToEthAllPath_Node = []
                    print('\t\tcfg分析安全,所以开始ICFG的分析'.format(function.full_name))
                    currentFunctionNode = callGraph.function_Map_node.get(function)

                    '''
                    把钱更新的那些个ethFunction剔除掉
                    '''
                    for ethFunctionNode in callGraph.ethFunctionNodes[:]:
                        if dm.advancedUpdateEth(ethFunctionNode.function):# or dm.advancedUpdateEth_2(ethFunctionNode.function):
                            callGraph.ethFunctionNodes.remove(ethFunctionNode)

                    # for taintFunctionNode in callGraph.taintFunctionNodes[:]:
                    #     if dm.requireMsgSender(taintFunctionNode.function):
                    #         callGraph.taintFunctionNodes.remove(taintFunctionNode)

                    for taintFunctionNode in callGraph.taintFunctionNodes:
                        functionNode_to_taintFunctionNode = []
                        functionNode_to_taintFunctionNode.append(currentFunctionNode)
                        functionNode_to_taintFunctionNode.extend(list(set(callGraph.functionNodes) - set([currentFunctionNode, taintFunctionNode])))
                        functionNode_to_taintFunctionNode.append(taintFunctionNode)

                        adjMatrix = getadjMatrix(functionNode_to_taintFunctionNode)
                        mydeepGraph = MyDeepGraph(len(functionNode_to_taintFunctionNode))
                        mydeepGraph.setadjMetrix(adjMatrix)
                        callGraphToOneofTaintAllPath = mydeepGraph.getPathofTwoNode(0, len(functionNode_to_taintFunctionNode) - 1)
                        callGraphToOneofTaintAllPath_Node = allPaths_intToNode(callGraphToOneofTaintAllPath, functionNode_to_taintFunctionNode)
                        callGraphToTaintAllPath_Node.extend(callGraphToOneofTaintAllPath_Node)
                    for ethFunctionNode in callGraph.ethFunctionNodes:
                        functionNode_to_ethFunctionNode = []
                        functionNode_to_ethFunctionNode.append(currentFunctionNode)
                        functionNode_to_ethFunctionNode.extend(list(set(callGraph.functionNodes) - set([currentFunctionNode, ethFunctionNode])))
                        functionNode_to_ethFunctionNode.append(ethFunctionNode)
                        adjMatrix = getadjMatrix(functionNode_to_ethFunctionNode)
                        mydeepGraph = MyDeepGraph(len(functionNode_to_ethFunctionNode))
                        mydeepGraph.setadjMetrix(adjMatrix)
                        callGraphToOneOfEthAllPath = mydeepGraph.getPathofTwoNode(0, len(functionNode_to_ethFunctionNode) - 1)
                        callGraphToOneofEthAllPath_Node = allPaths_intToNode(callGraphToOneOfEthAllPath, functionNode_to_ethFunctionNode)
                        callGraphToEthAllPath_Node.extend(callGraphToOneofEthAllPath_Node)

                    for path in callGraphToTaintAllPath_Node:
                        careTaintFunction.add(path[1].function)
                    for path in callGraphToEthAllPath_Node:
                        careEthFunction.add(path[1].function)

                    for node in function.nodes:
                        for highLevelCall in node.high_level_calls:
                            contract, functionOrVariable = highLevelCall
                            if isinstance(functionOrVariable, Function):
                                if functionOrVariable in careEthFunction:
                                    careEthNode.add(node)
                                if functionOrVariable in careTaintFunction:
                                    careTaintNode.add(node)
                        for internalCall in node.internal_calls:
                            if isinstance(internalCall, Function):
                                if internalCall in careEthFunction:
                                    careEthNode.add(node)
                                if internalCall in careTaintFunction:
                                    careTaintNode.add(node)
                    careTaintNode = careTaintNode | set(functon_taintNodeList)
                    careEthNode = careEthNode | set(function_ethNodeList)

                    for taintNode in careTaintNode:
                        cfgEntryNodeTotaint = []
                        cfgEntryNodeTotaint.append(function.entry_point)
                        cfgEntryNodeTotaint.extend(list(set(function.nodes) - set([function.entry_point, taintNode])))
                        cfgEntryNodeTotaint.append(taintNode)

                        adjMatrix = getadjMatrix(cfgEntryNodeTotaint)
                        mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint))
                        mydeepGraph.setadjMetrix(adjMatrix)
                        cfgAllPath = mydeepGraph.getPathofTwoNode(0, len(cfgEntryNodeTotaint) - 1)

                        cfgAllPath_Node = allPaths_intToNode(cfgAllPath, cfgEntryNodeTotaint)
                        corePath = []
                        for path in cfgAllPath_Node:
                            if any(cfgNode in careEthNode for cfgNode in path[0:len(path)-1]):
                                corePath.append(path)
                        if corePath:
                            ###################################################

                            ########################################
                            for path in corePath[:]:
                                for callee in path[-1].callee:
                                    calleefunctionNode = callGraph.function_Map_node.get(callee)
                                    for callGraphToTaintPath in callGraphToTaintAllPath_Node:
                                        if calleefunctionNode == callGraphToTaintPath[1]:
                                            afterCalleeList = [functionNode.function.full_name for functionNode in callGraphToTaintPath[1:]]
                                            afterCalleeList.insert(0, 'taint')
                                            path.append(afterCalleeList)

                            for tempP in corePath[:]:
                                for tempNode in tempP:
                                    if tempNode in list(careEthNode):
                                        for callee in tempNode.callee:
                                            calleefunctionNode = callGraph.function_Map_node.get(callee)
                                            for callGraphToEthPath in callGraphToEthAllPath_Node:
                                                if calleefunctionNode == callGraphToEthPath[1]:
                                                    afterCalleeList = [functionNode.function.full_name for functionNode in callGraphToEthPath[1:]]
                                                    afterCalleeList.insert(0, 'eth')
                                                    tempP.append(afterCalleeList)
                            ##########################################
                            human_corePath = []
                            for path in corePath:
                                ##############################################
                                tempPath = []
                                needindex = len(path)
                                for i in range(len(path)):
                                    if isinstance(path[i], list):
                                        needindex = i
                                        break
                                #########################
                                for cfgNode in path[0:needindex]:
                                    tempPath.append(str(cfgNode.expression))
                                tempPath.append(path[needindex:])
                                human_corePath.append(tempPath)
                            advanceUpdateFlag = False  # dm.advancedUpdateEth(function)
                            privateVisibility = dm.privateVisibility(function)
                            haveDefenModifier = dm.haveDefenseModifier(function)
                            havePublicCaller = callerVisibilityHavePublic(function, callGraph, dm)
                            haveDefenRequire = dm.requireMsgSender(function)

                            if privateVisibility is True or haveDefenModifier is True or haveDefenRequire is True:
                                accessPermision = True
                                if havePublicCaller is True:
                                    reentrancyFlag = True
                                    print(
                                        '\t\tcontract: {} | function: {} | accessPermision: {} | publicCaller: {} | 锁/钱提前更新:{}'.format(
                                            function.contract.name, function.full_name, accessPermision,
                                            havePublicCaller, advanceUpdateFlag))
                                    for humanPath in human_corePath:
                                        print('\t\t\tpath:{}'.format(humanPath))
                            else:
                                accessPermision = False
                                reentrancyFlag = True
                                print(
                                    '\t\tcontract: {} | function: {} | accessPermision: {} | 锁/钱提前更新:{}'.format(
                                        function.contract.name, function.full_name, accessPermision,
                                        advanceUpdateFlag))
                                for humanPath in human_corePath:
                                    print('\t\t\tpath:{}'.format(humanPath))
                if reentrancyFlag is True:
                    print('[Icfg_Reentrancy in] contract: {} . function: {} | {}'.format(function.contract.name, function.full_name, function.source_mapping_str))
                    continue
예제 #3
0
    def detect_reentrancy(self, contract, ethNodeList, taintNodeList, icfg,
                          callGraph, cfgEndNodeList):
        print('Start Contract {}'.format(contract.name))
        for function in contract.functions:
            if function.is_implemented:
                print('\tTo analyze:{}.{}'.format(function.contract.name,
                                                  function.full_name))
                dm = DM(function)  # 声明dm防御对象
                reentrancyFlag = False

                functon_taintNodeList = []  # 存储本函数体内的taint
                for node in function.nodes:
                    if node in taintNodeList:
                        functon_taintNodeList.append(node)

                for function_taintNode in functon_taintNodeList:
                    '''
                    startToend = [start, ... ,end]
                    '''
                    cfgEntryNodeTotaint = []
                    cfgEntryNodeTotaint.append(function.entry_point)
                    cfgEntryNodeTotaint.extend(
                        list(
                            set(function.nodes) -
                            set([function.entry_point, function_taintNode])))
                    cfgEntryNodeTotaint.append(function_taintNode)

                    # cfgAllPath = getCfgAllPath(cfgEntryNodeTotaint)
                    adjMatrix = getadjMatrix(cfgEntryNodeTotaint)
                    mydeepGraph = MyDeepGraph(len(cfgEntryNodeTotaint))
                    mydeepGraph.setadjMetrix(adjMatrix)
                    cfgAllPath = mydeepGraph.getPathofTwoNode(
                        0,
                        len(cfgEntryNodeTotaint) - 1)
                    cfgAllPath_Node = allPaths_intToNode(
                        cfgAllPath, cfgEntryNodeTotaint)

                    cfgCandidateAllPath_Node = []
                    for path in cfgAllPath_Node[:]:
                        if any(iNode in ethNodeList for iNode in path):
                            cfgCandidateAllPath_Node.append(path)

                    if cfgCandidateAllPath_Node:  # 证明cfg本身就找到Reentrancy了,准备humanlook, 注意reversed, DM

                        human_cfgCandidateAllPath_Node = []
                        for path in cfgCandidateAllPath_Node:
                            tempPath = []
                            for everyNode in path:
                                if everyNode.type == NodeType.ENTRYPOINT:
                                    everyNode.add_expression('entryPoint')
                                tempPath.append(str(everyNode.expression))
                            human_cfgCandidateAllPath_Node.append(tempPath)
                        advanceUpdateFlag = False  # dm.advancedUpdateEth(function)
                        privateVisibility = dm.privateVisibility(function)
                        havePublicCaller = callerVisibilityHavePublic(
                            function, callGraph)
                        if privateVisibility is True:
                            if havePublicCaller is True:
                                reentrancyFlag = True
                                print(
                                    '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | 锁/钱提前更新:{}'
                                    .format(function.contract.name,
                                            function.full_name,
                                            privateVisibility,
                                            havePublicCaller,
                                            advanceUpdateFlag))
                                for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node:
                                    print('\t\t\tpath: {}'.format(
                                        human_cfgCandidatePath_Node))
                        else:
                            reentrancyFlag = True
                            print(
                                '\t\tcontract: {} | function: {} | private: {} | 锁/钱提前更新:{}'
                                .format(function.contract.name,
                                        function.full_name, privateVisibility,
                                        advanceUpdateFlag))
                            for human_cfgCandidatePath_Node in human_cfgCandidateAllPath_Node:
                                print('\t\t\tpath: {}'.format(
                                    human_cfgCandidatePath_Node))
                if reentrancyFlag is True:
                    print(
                        '[cfg_Reentrancy in] contract: {} . function: {} | {}'.
                        format(function.contract.name, function.full_name,
                               function.source_mapping_str))
                    continue

                if reentrancyFlag is False:  # 证明cfg本身没找到Reentrancy
                    '''
                    bug修复为了把当前的function的endnode的回调用处的那条路径删除,同时也要删除本函数entryNode的icfgFather
                    '''
                    print('\t\tcfg分析安全,所以开始ICFG的分析'.format(function.full_name))
                    # = function.entry_point.icfgFathers
                    # function.entry_point.set_icfgFather([])
                    '''
                    endnodeMapBackSons = {}
                    # hh = [str(endnode.expression) for endnode in function.ENDnodes]
                    # print('结束点:'.format(hh))
                    for endnode in function.ENDnodes:
                        endnodeMapBackSons[endnode] = []
                        for son in endnode.backIcfgSons:
                            endnodeMapBackSons[endnode].append(son)

                    for endnode in function.ENDnodes:
                        endnode.set_backIcfgSons([])
                    '''
                    # tt = [str(taintNode.expression) for taintNode in taintNodeList]
                    # print('系统中所有的taint:{}, 总共有 {} 个taintNode'.format(tt, len(taintNodeList)))
                    # for endnode in function.ENDnodes:
                    #     print('回到哪里了: {}'.format(endnodeMapBackSons[endnode]))
                    # for endnode in function.ENDnodes:
                    #     print('注意应该是0:{}'.format(len(endnode.backIcfgSons)))
                    for taintNode in taintNodeList:
                        icfgEntryNodeTotaint = []
                        icfgEntryNodeTotaint.append(function.entry_point)
                        icfgEntryNodeTotaint.extend(
                            list(
                                set(icfg.allNodes) -
                                set([function.entry_point, taintNode])))
                        icfgEntryNodeTotaint.append(taintNode)

                        adjMatrix = getICFGadjMatrix(icfgEntryNodeTotaint)

                        mydeepGraph = MyDeepGraph(len(icfgEntryNodeTotaint))
                        mydeepGraph.setadjMetrix(adjMatrix)
                        #mydeepGraph.printMatrix()
                        icfgAllPath = mydeepGraph.getPathofTwoNode(
                            0,
                            len(icfgEntryNodeTotaint) - 1)

                        icfgAllPath_Node = allPaths_intToNode(
                            icfgAllPath, icfgEntryNodeTotaint)

                        #icfgAllPath = getIcfgAllPath(icfgEntryNodeTotaint)
                        # print('函数{}的入口点到taint点{}的路径有{}条:'.format(function.full_name, taintNode.expression, len(icfgAllPath)))
                        #icfgAllPath_Node = allPaths_intToNode(icfgAllPath, icfgEntryNodeTotaint)
                        # print('应该为1:{}'.format(len(icfgAllPath_Node)))
                        # qq = [[str(ww.expression) for ww in yy] for yy in icfgAllPath_Node]
                        # print('路径:{}'.format(qq))
                        icfgCandidateAllPath_Node = []

                        for path in icfgAllPath_Node:
                            if any(iNode in ethNodeList for iNode in path):
                                icfgCandidateAllPath_Node.append(path)

                        # if icfgCandidateAllPaht_Node:
                        #     # 检查icfg路径合法性
                        #     cfgEndNodeList_exp = list(set(cfgEndNodeList) - set(function.ENDnodes))
                        #     for path in icfgCandidateAllPaht_Node:
                        #         new = path[-1]
                        #         for node in path:
                        #             if node in cfgEndNodeList_exp:
                        #                 for entryP in node.icfgSons:
                        #                     for preEndNode in entryP.function.ENDnodes:
                        #                         if preEndNode in path:
                        #                             if (path.index(preEndNode) + 1) <= len(path)-1:
                        #                                 possibleErrNodeIndex = path.index(preEndNode) + 1
                        #                                 possibleErrNode = path[possibleErrNodeIndex]
                        #                                 if possibleErrNode != node:
                        #                                     # path.append('非法路径')
                        #                                     pass
                        #
                        #
                        #             if node in function.ENDnodes:
                        #                 if path[-1] != node:
                        #                     # 非法路径
                        #                     pass
                        if icfgCandidateAllPath_Node:  # 证明icfg本身找到Reentrancy了,准备humanlook, DM

                            # print('证明icfg本身找到Reentrancy了,准备humanlook, DM')
                            '''
                            转变成普通人能看懂的形式,注意reversed
                            '''
                            human_icfgCandidateAllPath_Node = []
                            for path in icfgCandidateAllPath_Node:
                                tempPath = []
                                for everyNode in path:
                                    if everyNode.type == NodeType.ENTRYPOINT:
                                        everyNode.add_expression('entryPoint')
                                    tempPath.append(str(everyNode.expression))
                                human_icfgCandidateAllPath_Node.append(
                                    tempPath)
                            etherNodesInPath = []
                            # for path in icfgCandidateAllPaht_Node:
                            #     for itemNode in path:
                            #         if itemNode in ethNodeList:
                            #             etherNodesInPath.append(itemNode)
                            etherNodesInPath = [
                                itemNode for path in icfgCandidateAllPath_Node
                                for itemNode in path if itemNode in ethNodeList
                            ]
                            # print('长度:{}'.format(len(etherNodesInPath)))
                            # kkk = [str(etherNodeInPath.expression) for etherNodeInPath in etherNodesInPath]
                            # print('在路径中的转账节点:{}'.format(kkk))
                            realETHfunctionList = [
                                eNode.function for eNode in etherNodesInPath
                            ]
                            '''
                            if all(dm.advancedUpdateEth(function) for function in realETHfunctionList):
                                advanceUpdateFlag = True
                            else:
                                advanceUpdateFlag = False
                            '''
                            advanceUpdateFlag = False
                            #advanceUpdateFlag = dm.advancedUpdateEth(function)
                            privateVisibility = dm.privateVisibility(function)
                            havePublicCaller = callerVisibilityHavePublic(
                                function, callGraph)

                            if privateVisibility is True:
                                if havePublicCaller is True:
                                    reentrancyFlag = True
                                    print(
                                        '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | 锁/钱提前更新:{}'
                                        .format(function.contract.name,
                                                function.full_name,
                                                privateVisibility,
                                                havePublicCaller,
                                                advanceUpdateFlag))
                                    for human_icfgCandidatePath_Node in human_icfgCandidateAllPath_Node:
                                        print('\t\t\tpath: {}'.format(
                                            human_icfgCandidatePath_Node))
                            else:
                                reentrancyFlag = True
                                print(
                                    '\t\tcontract: {} | function: {} | private: {} | 锁/钱提前更新:{}'
                                    .format(function.contract.name,
                                            function.full_name,
                                            privateVisibility,
                                            advanceUpdateFlag))
                                for human_icfgCandidatePath_Node in human_icfgCandidateAllPath_Node:
                                    print('\t\t\tpath: {}'.format(
                                        human_icfgCandidatePath_Node))
                    '''
                    为了把当前的function的endnode的回调用处的那条路径再补上, 和entryNode的icfgFather叶去掉
                    '''
                    # if endnodeMapBackSons:
                    #     for endnode in function.ENDnodes:
                    #         endnode.set_backIcfgSons = endnodeMapBackSons[endnode]
                    #function.entry_point.set_icfgFather = icfgFathersNeedToDuan
                if reentrancyFlag is True:
                    print(
                        '[icfg_Reentrancy in] contract: {} . function: {} | {}'
                        .format(function.contract.name, function.name,
                                function.source_mapping_str))
예제 #4
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
예제 #5
0
    def _have_reentrancy(self,
                         function,
                         eth_node_list,
                         taint_node_list,
                         private_visibility,
                         have_public_caller,
                         icfg=None):
        reentrancy_flag = False
        for taint_node in taint_node_list:
            '''
            start_to_end = [start, ... ,end]
            '''
            entry_node_to_taint = []
            entry_node_to_taint.append(function.entry_point)
            if icfg is None:
                entry_node_to_taint.extend(
                    list(
                        set(function.nodes) -
                        set([function.entry_point, taint_node])))
            else:
                entry_node_to_taint.extend(
                    list(
                        set(icfg.allNodes) -
                        set([function.entry_point, taint_node])))
            entry_node_to_taint.append(taint_node)
            if icfg is None:
                adj_matrix = getadjMatrix(entry_node_to_taint)
            else:
                adj_matrix = getICFGadjMatrix(entry_node_to_taint)
            my_deep_graph = MyDeepGraph(len(entry_node_to_taint))
            my_deep_graph.setadjMetrix(adj_matrix)
            all_path = my_deep_graph.getPathofTwoNode(
                0,
                len(entry_node_to_taint) - 1)
            all_path_node = allPaths_intToNode(all_path, entry_node_to_taint)

            candidate_all_path_node = []
            for path in all_path_node:
                if any(inode in eth_node_list for inode in path):
                    candidate_all_path_node.append(path)
            if candidate_all_path_node:  # 证明找到Reentrancy了,准备human look, 注意reversed, DM
                '''
                转变成普通人能看懂的形式,注意reversed
                '''
                human_candidate_all_path_node = self.get_human_candidate_all_path_node(
                    candidate_all_path_node)
                advance_update_flag = False  # dm.advancedUpdateEth(function)
                txt1 = '\t\tcontract: {} | function: {} | private: {} | publicCaller: {} | Execution Locks and Eth ' \
                       'money balance modification: {} '
                txt2 = '\t\tcontract: {} | function: {} | private: {} | Execution Locks and Eth money balance ' \
                       'modification: {} '
                txt3 = '\t\t\tpath: {}'
                if private_visibility is True:
                    if have_public_caller is True:
                        reentrancy_flag = True
                        print(
                            txt1.format(function.contract.name,
                                        function.full_name, private_visibility,
                                        have_public_caller,
                                        advance_update_flag))
                        for human_candidate_path_node in human_candidate_all_path_node:
                            print(txt3.format(human_candidate_path_node))
                else:
                    reentrancy_flag = True
                    print(
                        txt2.format(function.contract.name, function.full_name,
                                    private_visibility, advance_update_flag))
                    for human_candidate_path_node in human_candidate_all_path_node:
                        print(txt3.format(human_candidate_path_node))
        if reentrancy_flag is True:
            if icfg is None:
                txt = '[cfg_Reentrancy in] contract: {} . function: {} | {}'
            else:
                txt = '[icfg_Reentrancy in] contract: {} . function: {} | {}'
            print(
                txt.format(function.contract.name, function.full_name,
                           function.source_mapping_str))
        return reentrancy_flag
예제 #6
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