Copy AMITT repository, clean up and rebrand

Took a copy of the current AMITT github repository - we'll be updating this and merging the SPICE branch back in
Rebranded to DISARM
Moved generated pages to their own folder, to make looking at the repository less confusing
This commit is contained in:
Sara-Jayne Terp 2022-01-29 11:34:46 -05:00
commit 22abaf93d8
448 changed files with 58066 additions and 0 deletions

View file

@ -0,0 +1,282 @@
''' Manage AMITT counters
Create a page for each of the AMITT counter objects.
Don't worry about creating notes etc for these - they'll be in the generating spreadsheet
Reads 1 excel file: ../AMITT_MASTER_DATA/AMITT_Counters_MASTER.xlsx with sheets
* AMITT_objects: tactics, responses, actors, techniques
* Countermeasures
*
Creates markdown files
* ../counter_tactic_counts.md
* ../counter_tactics/{}counters.md
* ../counter_metatag_counts.md
* ../counter_metatag/{1}counters.md
* ../counter_resource_counts.md
* ../counter_resource/{1}counters.md
*
* {}/{}counters.md
*
'''
import pandas as pd
import numpy as np
import os
from sklearn.feature_extraction.text import CountVectorizer
class Counter:
def __init__(self, infile = '../AMITT_MASTER_DATA/AMITT_Counters_MASTER.xlsx'):
# Create counters cross-tables
crossidtechs = self.splitcol(self.dfcounters[['ID', 'Techniques']],
'Techniques', 'Techs', '\n')
crossidtechs = crossidtechs[crossidtechs['Techs'].notnull()]
crossidtechs['TID'] = crossidtechs['Techs'].str.split(' ').str[0]
crossidtechs.drop('Techs', axis=1, inplace=True)
self.idtechnique = crossidtechs
crossidres = self.splitcol(self.dfcounters[['ID', 'Resources needed']],
'Resources needed', 'Res', ',')
crossidres = crossidres[crossidres['Res'].notnull()]
self.idresource = crossidres
def analyse_counter_text(self, col='Title'):
# Analyse text in counter descriptions
alltext = (' ').join(self.dfcounters[col].to_list()).lower()
count_vect = CountVectorizer(stop_words='english')
word_counts = count_vect.fit_transform([alltext])
dfw = pd.DataFrame(word_counts.A, columns=count_vect.get_feature_names()).transpose()
dfw.columns = ['count']
dfw = dfw.sort_values(by='count', ascending=False)
return(dfw)
def splitcol(self, df, col, newcol, divider=','):
# Thanks https://stackoverflow.com/questions/17116814/pandas-how-do-i-split-text-in-a-column-into-multiple-rows?noredirect=1
return (df.join(df[col]
.str.split(divider, expand=True).stack()
.reset_index(drop=True,level=1)
.rename(newcol)).drop(col, axis=1))
# Print list of counters for each square of the COA matrix
# Write HTML version of framework diagram to markdown file
def write_counters_tactics_markdown(self, outfile = '../counter_tactic_counts.md'):
coacounts = pd.pivot_table(self.dfcounters[['Tactic', 'Response',
'ID']], index='Response', columns='Tactic', aggfunc=len, fill_value=0)
html = '''# AMITT Courses of Action matrix:
<table border="1">
<tr>
<td> </td>
'''
#Table heading = Tactic names
for col in coacounts.columns.get_level_values(1):
tid = self.create_tactic_file(col)
html += '<td><a href="counter_tactics/{0}counters.md">{1}</a></td>\n'.format(
tid, col)
html += '</tr><tr>\n'
# number of counters per response type
for response, counts in coacounts.iterrows():
html += '<td>{}</td>\n'.format(response)
for val in counts.values:
html += '<td>{}</td>\n'.format(val)
html += '</tr>\n<tr>\n'
# Total per tactic
html += '<td>TOTALS</td>\n'
for val in coacounts.sum().values:
html += '<td>{}</td>\n'.format(val)
html += '</tr>\n</table>\n'
with open(outfile, 'w') as f:
f.write(html)
print('updated {}'.format(outfile))
return
def create_tactic_file(self, tname):
if not os.path.exists('../counter_tactics'):
os.makedirs('../counter_tactics')
tid = tname[:tname.find(' ')]
html = '''# Tactic {} counters\n\n'''.format(tname)
html += '## by action\n\n'
for resp, counters in self.dfcounters[self.dfcounters['Tactic'] == tname].groupby('Response'):
html += '\n### {}\n'.format(resp)
for c in counters.iterrows():
html += '* {}: {} (needs {})\n'.format(c[1]['ID'], c[1]['Title'],
c[1]['Resources needed'])
html += '\n## by technique\n\n'
tactecs = self.techniques[self.techniques['phase'] == tid]['Id'].to_list()
for tech in [tid] + tactecs:
if tech == tid:
html += '\n### {}\n'.format(tech)
else:
techname = self.techniques[self.techniques['Id']==tech]['longname']
html += '\n### {}\n'.format(techname)
taccounts = self.idtechnique[self.idtechnique['TID'] == tech]
# html += '\n{}\n'.format(taccounts)
for c in self.dfcounters[self.dfcounters['ID'].isin(taccounts['ID'])].iterrows():
html += '* {}: {} (needs {})\n'.format(c[1]['ID'], c[1]['Title'],
c[1]['Resources needed'])
datafile = '../counter_tactics/{}counters.md'.format(tid)
print('Writing {}'.format(datafile))
with open(datafile, 'w') as f:
f.write(html)
f.close()
return(tid)
def create_object_file(self, index, rowtype, datadir):
oid = index
html = '''# {} counters: {}\n\n'''.format(rowtype, index)
html += '## by action\n\n'
for resp, clist in self.dfcounters[self.dfcounters[rowtype] == index].groupby('Response'):
html += '\n### {}\n'.format(resp)
for c in clist.iterrows():
html += '* {}: {} (needs {})\n'.format(c[1]['ID'], c[1]['Title'],
c[1]['Resources needed'])
datafile = '{}/{}counters.md'.format(datadir, oid)
print('Writing {}'.format(datafile))
with open(datafile, 'w') as f:
f.write(html)
f.close()
return(oid)
def write_counters_metacounts_markdown(self, outfile = '../counter_metatag_counts.md'):
coltype = 'Response'
rowtype = 'metatechnique'
rowname = 'metatag'
mtcounts = pd.pivot_table(self.dfcounters[[coltype, rowtype,'ID']],
index=rowtype, columns=coltype, aggfunc=len,
fill_value=0)
mtcounts['TOTALS'] = mtcounts.sum(axis=1)
html = '''# AMITT {} courses of action
<table border="1">
<tr>
<td> </td>
'''.format(rowtype)
# Table heading row
for col in mtcounts.columns.get_level_values(1)[:-1]:
html += '<td>{}</td>\n'.format(col)
html += '<td>TOTALS</td></tr><tr>\n'
# Data rows
datadir = '../counters_{}'.format(rowname)
if not os.path.exists(datadir):
os.makedirs(datadir)
for index, counts in mtcounts.iterrows():
tid = self.create_object_file(index, rowtype, datadir)
html += '<td><a href="counter_{0}/{1}counters.md">{2}</a></td>\n'.format(
rowname, tid, index)
for val in counts.values:
html += '<td>{}</td>\n'.format(val)
html += '</tr>\n<tr>\n'
# Column sums
html += '<td>TOTALS</td>\n'
for val in mtcounts.sum().values:
html += '<td>{}</td>\n'.format(val)
html += '</tr>\n</table>\n'
with open(outfile, 'w') as f:
f.write(html)
print('updated {}'.format(outfile))
return
def create_resource_file(self, index, rowtype, datadir):
oid = index
counterrows = self.idresource[self.idresource['Res'] == index]['ID'].to_list()
html = '''# {} counters: {}\n\n'''.format(rowtype, index)
html += '## by action\n\n'
omatrix = self.dfcounters[self.dfcounters['ID'].isin(counterrows)].groupby('Response')
for resp, clist in omatrix:
html += '\n### {}\n'.format(resp)
for c in clist.iterrows():
html += '* {}: {} (needs {})\n'.format(c[1]['ID'], c[1]['Title'],
c[1]['Resources needed'])
datafile = '{}/{}counters.md'.format(datadir, oid)
print('Writing {}'.format(datafile))
with open(datafile, 'w') as f:
f.write(html)
f.close()
return(oid, omatrix)
def write_counters_resource_markdown(self, outfile = '../counter_resource_counts.md'):
coltype = 'Response'
rowtype = 'resource'
rowname = 'resource'
html = '''# AMITT {} courses of action
<table border="1">
<tr>
<td> </td>
'''.format(rowtype)
# Table heading row
colvals = self.dfcounters[coltype].value_counts().sort_index().index
for col in colvals:
html += '<td>{}</td>\n'.format(col)
html += '<td>TOTALS</td></tr><tr>\n'
# Data rows
datadir = '../counter_{}'.format(rowname)
if not os.path.exists(datadir):
os.makedirs(datadir)
for index in self.idresource['Res'].value_counts().sort_index().index:
(oid, omatrix) = self.create_resource_file(index, rowtype, datadir) #self
row = pd.DataFrame(omatrix.apply(len), index=colvals).fillna(' ')
html += '<td><a href="counter_{0}/{1}counters.md">{2}</a></td>\n'.format(
rowname, oid, index)
if len(row.columns) > 0:
for val in row[0].to_list():
html += '<td>{}</td>\n'.format(val)
html += '<td>{}</td></tr>\n<tr>\n'.format('')
html += '</tr>\n</table>\n'
with open(outfile, 'w') as f:
f.write(html)
print('updated {}'.format(outfile))
return
def main():
counter = Counter()
counter.write_counters_tactics_markdown()
counter.write_counters_metacounts_markdown()
counter.write_counters_resource_markdown()
if __name__ == "__main__":
main()