예제 #1
0
파일: adtree.py 프로젝트: wwidel/adtrees
 def clonesPartitioned(self):
     """
     Return two lists
     [labels of necessary clones], [labels of optional clones]
     as defined in
     "On quantitative analysis of attack–defense trees with repeated labels".
     """
     basics_prop = self.basic_actions('a')
     basics_opp = self.basic_actions('d')
     # create basic assignment
     ba = BasicAssignment()
     for b in basics_opp:
         ba[b] = 2
     for b in basics_prop:
         ba[b] = 0
     clones = [label for label in basics_prop if self.isclone(label)]
     necessary = []
     optional = []
     # do the bottom up for each of the clones
     for label in clones:
         ba[label] = 1
         if minSkillLvl.evaluateBU(self, ba) == 1:
             necessary.append(label)
         else:
             optional.append(label)
         ba[label] = 0
     return necessary, optional
예제 #2
0
 def f():
     #global root
     from tkinter import filedialog
     file = filedialog.askopenfilename()
     if file == '':
         return
     if file[-4:] == '.xml':
         # ba should load successfully
         ba = BasicAssignment(path=file)
     else:
         # failed to load a tree
         from tkinter import messagebox
         messagebox.showinfo(
             'Error!',
             'Failed to load a basic assignment from specified file. Be sure to select an .xml file produced by ADTool.'
         )
         return
     # display loaded values in appropriate Entry widgets
     for i in range(self.ATTACKERS_ACTIONS_NUMBER):
         # 1. fetch the value
         val = ba[self.ATTACKERS_BAS[i]]
         # 2. update&display in appropriate Entry widget, the one in
         # (i+2, index) grid cell
         entry = get_widget_from_grid(self.root, i + 2, index)
         # clear the widget
         entry.delete(0, len(entry.get()))
         # modify value
         entry.insert(0, str(val))
예제 #3
0
 def find_pareto_selected(self):
     # reset the basic assignment
     #global BASIC_ASSIGNMENT
     self.BASIC_ASSIGNMENT = BasicAssignment()
     self.deactivate_optimal_attacks()
     self.activate_pareto()
     self.deactivate_countermeasures()
     self.lab32.config(text="Selected task requires")
     if self.PARETO_COSTS.get() == 1:
         x = " assignment of cost and"
     else:
         x = " assignments of cost and"
     self.lab33.config(text=self.PARETO_COSTS.get() + x)
     if self.PARETO_SKILLS.get() == 1:
         x = " assignment of skill/diff."
     else:
         x = " assignments of skill/diff."
     self.lab34.config(text=self.PARETO_SKILLS.get() + x)
     if self.PARETO_PROBS.get() == 1:
         x = " assignment of prob."
     else:
         x = " assignments of prob."
     self.lab35.config(text=self.PARETO_PROBS.get() + x)
     self.lab36.config(
         text=
         "for the attacker, and selection of actions executed by the defender."
     )
예제 #4
0
    def evaluateRBU(self, T, ba, neutralANDp, absorbingANDp):
        """
        Compute the value of the attribute modeled with the 'self' domain
        in the tree 'T', under the basic assignment 'ba', using
        the repeated bottom-up evaluation.

        Suitable for non-increasing attribute domains and trees containing repeated basic actions.

        The neutral and the absorbing element for the domain's operation 'andp' need to be provided.
        """
        if self.type != 1:
            print(
                'The repeated bottom-up evaluation can not be applied for this domain.'
            )
            return
        for label in T.basic_actions():
            if label not in ba:
                print('Cannot perform the attribute evaluation: the action "' +
                      label + '" has no value assigned.')
        # if not T.contains_clones():
        #    return self.evaluateBU(T, ba)
        proponent = T.root.type
        result = None
        necClones, optClones = T.clonesPartitioned()
        temp_ba = BasicAssignment()
        # copy the old values
        for label in ba:
            temp_ba[label] = ba[label]
        # modify the values for necessary clones
        for label in necClones:
            temp_ba[label] = neutralANDp
        # iterate over subsets of optional clones
        for C in powerset(optClones):
            optminusC = []
            for label in optClones:
                if label in C:
                    temp_ba[label] = absorbingANDp
                else:
                    temp_ba[label] = neutralANDp
                    optminusC.append(label)
            # do the bottom-up
            itresult = self.evaluateBU(T, temp_ba, proponent)
            # modify
            for label in optminusC:
                itresult = self.andp(itresult, ba[label])
            # modify
            if result == None:
                result = itresult
            else:
                result = self.orp(result, itresult)
        # take the orginal values of the necessary clones into account
        for label in necClones:
            result = self.andp(result, ba[label])
        return result
예제 #5
0
 def find_optimal_attacks_selected(self):
     # reset the basic assignment
     #global BASIC_ASSIGNMENT
     self.BASIC_ASSIGNMENT = BasicAssignment()
     self.activate_optimal_attacks()
     self.deactivate_pareto()
     self.deactivate_countermeasures()
     self.lab32.config(text="Selected task requires")
     self.lab33.config(text="1 assignment of " + self.ATTRIBUTE.get())
     self.lab34.config(text="")
     self.lab35.config(text="")
     self.lab36.config(
         text=
         "for the attacker, and selection of actions executed by the defender."
     )
예제 #6
0
파일: adtree.py 프로젝트: wwidel/adtrees
    def set_semantics(self):
        """
        Return the set semantics of an attack(-defense) tree T, as formulated in
        "On quantitative analysis of attack–defense trees with repeated labels"
        by Kordy et al.

        Returns a list of two-element lists
            [[set, set], [set, set], ..., [set, set]],
        with each element of each of the lists being a set of basic actions.
        """
        ba = BasicAssignment()
        for label in self.basic_actions('a'):
            ba[label] = [[set([label]), set()]]
        for label in self.basic_actions('d'):
            ba[label] = [[set(), set([label])]]
        return setSem.evaluateBU(self, ba)
예제 #7
0
 def find_countermeasures_selected(self):
     # reset the basic assignment
     #global BASIC_ASSIGNMENT
     self.BASIC_ASSIGNMENT = BasicAssignment()
     self.deactivate_optimal_attacks()
     self.deactivate_pareto()
     self.activate_countermeasures()
     self.lab32.config(text="Selected task requires")
     if self.OPT_PROBLEM.get() == 'coverage':
         x = "0 assignments of cost"
     else:
         x = "1 assignment cost"
     self.lab33.config(text="1 assignment of cost")
     self.lab34.config(text="for the defender")
     self.lab35.config(text="")
     self.lab36.config(text="and " + x + " for the attacker.")
예제 #8
0
 def import_assignment(self):
     #global root
     from tkinter import filedialog
     file = filedialog.askopenfilename()
     if file == '':
         # 'cancel' pressed
         return
     if file[-4:] == '.txt':
         # ba should load successfully
         ba = BasicAssignment(path=file)
     else:
         # failed to load an assignment
         from tkinter import messagebox
         messagebox.showinfo(
             'Error!',
             'Failed to load a basic assignment from specified file. Be sure to select a .txt file produced by OSEAD.'
         )
         return
     # display loaded values in appropriate Entry widgets
     # but not if the problem selected is the coverage problem
     current_task = self.TASK_SELECTED.get()
     if current_task in [1, 2] or self.OPT_PROBLEM != 'coverage':
         if current_task == 2:
             columns_to_fill_in = int(self.PARETO_COSTS.get()) + int(
                 self.PARETO_PROBS.get()) + int(self.PARETO_SKILLS.get())
         else:
             columns_to_fill_in = 1
         for i in range(self.ATTACKERS_ACTIONS_NUMBER):
             for j in range(columns_to_fill_in):
                 # 1. fetch the value
                 if current_task == 2:
                     # try: :)
                     val = ba[self.ATTACKERS_BAS[i].replace('\n',
                                                            ' ')][0][j]
                 else:
                     val = ba[self.ATTACKERS_BAS[i].replace('\n', ' ')]
                 # 2. update&display in appropriate Entry widget, the one in
                 # (i+2, index) grid cell
                 entry = get_widget_from_grid(self.root, i + 2, j + 1)
                 # clear the widget
                 entry.delete(0, len(entry.get()))
                 # modify value
                 entry.insert(0, str(val))
예제 #9
0
파일: adtree.py 프로젝트: wwidel/adtrees
 def root_always_achievable(self):
     ba = BasicAssignment()
     for b in self.basic_actions():
         ba[b] = 1
     return satisfiability.evaluateBU(self, ba) == 1
예제 #10
0
파일: adtree.py 프로젝트: wwidel/adtrees
    def defense_semantics(self):
        """
        Return the defense semantics of an attack-defense tree T, as defined in
        "How well can I secure my system?".

        Returns a list of two-element lists
            [[set, set], [set, set], ..., [set, set]],
        with each element of each of the lists being a set of basic actions.
        """
        attackers_actions = self.basic_actions('a')
        defenders_actions = self.basic_actions('d')
        # step 1: create attack strategies
        if self.contains_clones():
            # variant 1: for trees containing repeated basic actions
            # substep 1: create witnesses
            ba = BasicAssignment()
            for b in attackers_actions:
                ba[b] = []
            for b in defenders_actions:
                ba[b] = [[b]]
            witnesses = suffWit.evaluateBU(self, ba)
            # don't forget the empty defense strategy
            witnesses.append([])
            # substep 2: iterate over witnesses, get attack strategies
            # countering them
            AS = []
            for witness in witnesses:
                ba = BasicAssignment()
                for b in attackers_actions:
                    ba[b] = [[b]]
                for b in defenders_actions:
                    if b in witness:
                        ba[b] = []
                    else:
                        ba[b] = [[]]
                candidates = countStrats.evaluateBU(self, ba)
                # select the minimal ones
                for AS_countering_witness in minimal_lists(candidates):
                    if AS_countering_witness not in AS:
                        AS.append(AS_countering_witness)
        else:
            # variant 2: for trees containing no repeated basic actions (iFM)
            ba = BasicAssignment()
            for b in attackers_actions:
                ba[b] = [[b]]
            for b in defenders_actions:
                ba[b] = [[]]
            AS = attStrat.evaluateBU(self, ba)

        # At this point AS is the set of all attack strategies in the tree.
        # step 2: defense strategies countering attack strategies
        result = []
        # 2.1 swap actors
        proponent = 'd'
        # 2.2 create a basic assignment
        for b in self.basic_actions('d'):
            ba[b] = [[b]]
        # iterate
        for A in AS:
            # modify the basic assignment
            for b in attackers_actions:
                if b in A:
                    ba[b] = []
                else:
                    ba[b] = [[]]
            # do the bottom-up
            candidates = countStrats.evaluateBU(self, ba, proponent)
            # select the minimal ones
            for candidate in minimal_lists(candidates):
                result.append([set(A), set(candidate)])
        return result
예제 #11
0
    def __init__(self):
        self.window = Tk()  # the main window :(
        self.root = Toplevel(self.window)
        # self.root = Tk()  # the basic assignment window :(
        self.root.withdraw()
        self.col_width = 30
        self.TREE = ADTree()
        self.BASIC_ASSIGNMENT = BasicAssignment()
        self.TREE_LOADED = 0
        self.FILE_SELECTED = StringVar()
        self.FILE_SELECTED.set('no file selected')
        self.TREE_LOADED_MSG = "Path to currently loaded tree:"
        self.TASK_SELECTED = IntVar()
        self.TASK_SELECTED.set(0)
        self.ASSIGNMENTS_WINDOW_OPEN = False
        self.ASSIGNMENTS_WINDOW_OPENED_BEFORE = False
        self.ATTACKERS_BAS = []
        self.DEFENDERS_BAS = []
        self.ATTACKERS_ACTIONS_NUMBER = 0
        self.DEFENDERS_ACTIONS_NUMBER = 0
        self.DOMAIN = None
        self.DEF_CHECKBOXES_VARIABLES = []
        self.LAST_SELECTED_TASK = None
        self.PATH = StringVar()
        self.SET_SEM = []
        self.DEF_SEM = []
        self.SELECTED_DEFENCES = []
        self.RESULT = ""

        # optimal attacks variables
        self.NUMBER_ATTACKS = StringVar()
        self.NUMBER_ATTACKS.set("1")
        self.ATTRIBUTE = StringVar()
        self.ATTRIBUTE.set("cost")

        # pareto optimization variables
        self.PARETO_COSTS = StringVar()
        self.PARETO_COSTS.set("0")
        self.PARETO_SKILLS = StringVar()
        self.PARETO_SKILLS.set("0")
        self.PARETO_PROBS = StringVar()
        self.PARETO_PROBS.set("0")

        # ILP variables
        self.BUDGET = StringVar()
        self.BUDGET.set("0")
        self.OPT_PROBLEM = StringVar()
        self.OPT_PROBLEM.set("coverage")

        # assignment button
        self.ASSIGNMENT_ON = False
        self.assignment_button = None

        # oops
        self.window.title(
            "OSEAD: Optimal Strategies Extractor for Attack-Defense trees")
        self.window.protocol("WM_DELETE_WINDOW", self.on_closing_main_window)
        #window.resizable(0, 0)
        # width x height + x_offset + y_offset:
        width = 985
        height = 500
        self.window.geometry('{}x{}+20+20'.format(width, height))
        self.window.deiconify()
        # col_count, row_count = window.grid_size()
        #
        # for row in range(row_count):
        #     window.grid_rowconfigure(row, minsize=40)

        self.nbcols = 4
        self.col_width = 30  #

        # general stuff
        self.bg_colour = "#C5E3BF"  # "#A6D785"
        self.res_button = None

        self.radio_optimal = Radiobutton(
            self.window,
            text="Find optimal attacks",
            font=("helvetica", 10),
            relief=GROOVE,
            state=DISABLED,
            width=self.col_width - 4,
            variable=self.TASK_SELECTED,
            command=self.find_optimal_attacks_selected,
            value=1,
            padx=0,
            anchor='w')
        self.radio_optimal.grid(column=2, row=1, columnspan=2)
        self.radio_pareto = Radiobutton(self.window,
                                        text="Find Pareto optimal attacks",
                                        font=("helvetica", 10),
                                        relief=GROOVE,
                                        width=self.col_width - 4,
                                        state=DISABLED,
                                        command=self.find_pareto_selected,
                                        variable=self.TASK_SELECTED,
                                        value=2,
                                        padx=0,
                                        anchor='w')
        self.radio_pareto.grid(column=2, row=6, columnspan=2)
        self.radio_countermeasures = Radiobutton(
            self.window,
            text="Find optimal set of countermeasures",
            font=("helvetica", 10),
            relief=GROOVE,
            width=self.col_width - 4,
            state=DISABLED,
            command=self.find_countermeasures_selected,
            variable=self.TASK_SELECTED,
            value=3,
            padx=0,
            anchor='w')
        self.radio_countermeasures.grid(column=2, row=11, columnspan=2)
        # optimal attacks spinboxes
        self.spin_attacks_number = Spinbox(self.window,
                                           from_=1,
                                           to=20,
                                           width=10,
                                           wrap=True,
                                           textvariable=self.NUMBER_ATTACKS,
                                           state=DISABLED)
        self.spin_attacks_number.grid(column=3, row=2)

        self.spin_attribute = Spinbox(self.window,
                                      values=('cost', 'skill', 'difficulty',
                                              'probability'),
                                      width=10,
                                      wrap=True,
                                      textvariable=self.ATTRIBUTE,
                                      command=self.spinbox_attribute,
                                      state=DISABLED)
        self.spin_attribute.grid(column=3, row=3)
        # pareto spinboxes
        self.spin_pareto_costs = Spinbox(self.window,
                                         from_=0,
                                         to=20,
                                         width=10,
                                         wrap=True,
                                         command=self.spinbox_pareto_costs,
                                         textvariable=self.PARETO_COSTS,
                                         state=DISABLED)
        self.spin_pareto_costs.grid(column=3, row=7)
        self.spin_pareto_skills = Spinbox(self.window,
                                          from_=0,
                                          to=20,
                                          width=10,
                                          wrap=True,
                                          command=self.spinbox_pareto_skills,
                                          textvariable=self.PARETO_SKILLS,
                                          state=DISABLED)
        self.spin_pareto_skills.grid(column=3, row=8)
        self.spin_pareto_probs = Spinbox(self.window,
                                         from_=0,
                                         to=20,
                                         width=10,
                                         wrap=True,
                                         command=self.spinbox_pareto_probs,
                                         textvariable=self.PARETO_PROBS,
                                         state=DISABLED)
        self.spin_pareto_probs.grid(column=3, row=9)
        # countermeasures spinboxes
        self.entry_budget = Entry(self.window,
                                  width=10,
                                  state=DISABLED,
                                  exportselection=0,
                                  textvariable=self.BUDGET)
        self.entry_budget.grid(column=3, row=12)
        self.spin_counter = Spinbox(self.window,
                                    values=("coverage",
                                            "attacker's investment"),
                                    width=10,
                                    wrap=True,
                                    textvariable=self.OPT_PROBLEM,
                                    command=self.spinbox_ilp,
                                    state=DISABLED)
        self.spin_counter.grid(column=3, row=13)

        # required assignments
        self.lab32 = Label(self.window,
                           text="No task selected.",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w',
                           justify=LEFT)
        self.lab32.grid(column=4, row=1)
        self.lab33 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab33.grid(column=4, row=3)
        self.lab34 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab34.grid(column=4, row=4)
        self.lab35 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab35.grid(column=4, row=5)
        self.lab36 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w',
                           justify=LEFT,
                           wraplength=7 * 32)
        self.lab36.grid(column=4, row=6)
        self.run_button = Button(self.window,
                                 text="Run",
                                 state=DISABLED,
                                 command=self.run_button_clicked,
                                 width=10)
        self.run_button.grid(column=6, row=3, columnspan=2)
        self.lab45 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')  # , justify=LEFT)
        self.lab45.grid(column=6, row=5, columnspan=2)
        self.lab46 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')  # , justify=LEFT)
        self.lab46.grid(column=6, row=6, columnspan=2)
        self.lab47 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')  # , justify=LEFT)
        self.lab47.grid(column=6, row=7, columnspan=2)
        self.lab48 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')  # , justify=LEFT)
        self.lab48.grid(column=6, row=8, columnspan=2)
        self.lab49 = Label(self.window,
                           text="",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')  # , justify=LEFT)
        self.lab49.grid(column=6, row=9, columnspan=2)
        self.lab410 = Label(self.window,
                            text="",
                            font=("helvetica", 10),
                            relief=FLAT,
                            width=self.col_width,
                            anchor='w')  # , justify=LEFT)
        self.lab410.grid(column=6, row=11, columnspan=2)
        # lab37 = Label(window, text="",
        #               font=("helvetica", 10), relief=FLAT, width=(2 * col_width) // 3, anchor='w', justify=LEFT, wraplength=0)
        # lab37.grid(column=4, row=7, columnspan=2)

        self.lab1 = Label(self.window,
                          text="TREE SELECTION",
                          font=("verdana", 10),
                          relief=RIDGE,
                          width=self.col_width,
                          bg=self.bg_colour)
        self.lab1.grid(column=0, row=0, columnspan=2)

        self.lab12 = Label(self.window,
                           text="Select ADTool .xml output file:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')
        self.lab12.grid(column=0, row=2, columnspan=2)

        self.browse_button = Button(self.window,
                                    text="Browse",
                                    command=self.browse_clicked,
                                    anchor='e')
        self.browse_button.grid(column=0, row=3)

        self.lab13 = Label(self.window,
                           text=self.TREE_LOADED_MSG,
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=self.col_width,
                           anchor='w')
        self.lab13.grid(column=0, row=5, columnspan=2)

        self.lab14 = Label(self.window,
                           textvariable=self.FILE_SELECTED,
                           font=("helvetica", 10),
                           relief=FLAT,
                           anchor='w')
        self.lab14.grid(column=0, row=6)

        # 2.2 column 2 of 4
        self.lab2 = Label(self.window,
                          text="TASK SELECTION",
                          font=("verdana", 10),
                          relief=RIDGE,
                          width=self.col_width,
                          bg=self.bg_colour)  # "helvetica")
        self.lab2.grid(column=2, row=0, columnspan=2)

        # 2.2.1 find optimal attacks

        self.lab23 = Label(self.window,
                           text="Number of attacks:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab23.grid(column=2, row=2)

        self.lab24 = Label(self.window,
                           text="Attribute to be optimized:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab24.grid(column=2, row=3)  # , columnspan=2)

        # 2.2.2 find pareto optimal attacks

        self.lab26 = Label(self.window,
                           text="Number of costs:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab26.grid(column=2, row=7)

        self.lab26 = Label(self.window,
                           text="Number of skills/difficulties:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab26.grid(column=2, row=8)

        self.lab27 = Label(self.window,
                           text="Number of probabilities:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab27.grid(column=2, row=9)

        # 2.2.3 find optimal set of countermeasures

        self.lab28 = Label(self.window,
                           text="Defender's budget:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab28.grid(column=2, row=12)

        self.lab29 = Label(self.window,
                           text="Optimization problem:",
                           font=("helvetica", 10),
                           relief=FLAT,
                           width=(2 * self.col_width) // 3,
                           anchor='w')
        self.lab29.grid(column=2, row=13)

        # 2.3 column 3 of 4
        self.lab3 = Label(self.window,
                          text="BASIC ASSIGNMENT",
                          font=("verdana", 10),
                          relief=RIDGE,
                          width=self.col_width,
                          bg=self.bg_colour)  # "helvetica")
        self.lab3.grid(column=4, row=0, columnspan=2)

        # 2.4 column 4 of 4
        self.lab4 = Label(self.window,
                          text="RUN ANALYSIS",
                          font=("verdana", 10),
                          relief=RIDGE,
                          width=self.col_width,
                          bg=self.bg_colour)  # "helvetica")
        self.lab4.grid(column=6, row=0, columnspan=2)