Projects STRLCPY DonPAPI Commits 7ae213e0
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    DonPAPI.py
    skipped 27 lines
    28 28  import concurrent.futures
    29 29  from lib.toolbox import split_targets,bcolors
    30 30  from database import database, reporting
    31  - 
     31 +from datetime import date
    32 32   
    33 33   
    34 34  global assets
    skipped 138 lines
    173 173   
    174 174   targets = split_targets(options.target_ip)
    175 175   logging.info("Loaded {i} targets".format(i=len(targets)))
    176  - if not options.report :
     176 + if len(targets) > 0 :
    177 177   try:
    178 178   with concurrent.futures.ThreadPoolExecutor(max_workers=int(options.t)) as executor:
    179 179   executor.map(seatbelt_thread, [(target, options, logging) for target in targets])
    skipped 3 lines
    183 183   traceback.print_exc()
    184 184   logging.error(str(e))
    185 185   #print("ENDING MAIN")
    186  - my_report = reporting(sqlite3.connect(options.db_path), logging, options, targets)
    187  - my_report.generate_report()
    188  - my_report.export_credz()
    189  - my_report.export_sam()
    190  - my_report.export_cookies()
    191  - if options.GetHashes:
    192  - my_report.export_MKF_hashes()
    193  - my_report.export_dcc2_hashes()
     186 + 
    194 187   
    195  - #attendre la fin de toutes les threads ?
    196 188   if options.report :
    197 189   try:
    198 190   my_report = reporting(sqlite3.connect(options.db_path), logging,options,targets)
    199  - my_report.generate_report()
     191 + # Splited reports
     192 + my_report.generate_report(report_file='%s_Client_view.html' % date.today().strftime("%d-%m-%Y"),
     193 + report_content=['credz', 'hash_reuse'], credz_content=['taskscheduler', 'LSA'])
     194 + my_report.generate_report(report_file='%s_Most_important_credz.html' % date.today().strftime("%d-%m-%Y"),
     195 + report_content=['credz'],
     196 + credz_content=['wifi', 'taskscheduler', 'credential-blob', 'browser', 'sysadmin',
     197 + 'LSA'])
     198 + my_report.generate_report(report_file='%s_cookies.html' % date.today().strftime("%d-%m-%Y"),
     199 + report_content=['cookies'], credz_content=[''])
     200 + # Main report
     201 + my_report.generate_report(report_file='%s_Full_Report.html' % date.today().strftime("%d-%m-%Y"))
     202 + logging.info("[+] Exporting loots to raw files : credz, sam, cookies")
     203 + my_report.export_credz()
     204 + my_report.export_sam()
     205 + my_report.export_cookies()
    200 206   if options.GetHashes:
    201 207   my_report.export_MKF_hashes()
    202 208   my_report.export_dcc2_hashes()
    skipped 81 lines
  • ■ ■ ■ ■ ■ ■
    database.py
    skipped 11 lines
    12 12   self.targets = targets
    13 13   self.report_file = os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y"))
    14 14   
    15  - def add_to_resultpage(self, datas):
     15 + def add_to_resultpage(self, datas,report_file=""):
    16 16   try:
     17 + if report_file=="":
     18 + report_file=self.report_file
    17 19   datas = datas.encode('ascii', 'ignore')
    18  - f = open(self.report_file, 'ab')
     20 + f = open(report_file, 'ab')
    19 21   f.write(datas)
    20 22   f.close()
    21 23   return True
    skipped 2 lines
    24 26   self.logging.debug(ex)
    25 27   return False
    26 28   
    27  - def generate_report(self,type='', user='', target=''):
     29 + def generate_report(self,type='', user='', target='',report_content=['credz','cookies','files','connected_user','hash_reuse','audited_scope','masterkeys'],credz_content=['wifi', 'taskscheduler', 'credential-blob', 'browser', 'sysadmin','SAM', 'LSA', 'DCC2'],report_file=""):
    28 30   
    29 31   try:
    30 32   my_path = os.path.dirname(os.path.realpath(__file__))
    skipped 8 lines
    39 41   self.logging.debug(f" Exception {bcolors.WARNING} in running Report {bcolors.ENDC}")
    40 42   self.logging.debug(ex)
    41 43   
    42  - self.logging.info("[+] Generating report")
     44 + self.logging.info(f"[+] Generating report : {report_file}")
    43 45   if self.conn == None :
    44 46   self.logging.debug(f"[+] db ERROR - {self.options.output_directory}")
    45 47   return -1
    46 48   
    47 49   try:
    48  - if os.path.exists(os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y"))):
    49  - if os.path.exists(os.path.join(self.options.output_directory,'%s_result_old.html' % date.today().strftime("%d-%m-%Y"))):
    50  - os.remove(os.path.join(self.options.output_directory,'%s_result_old.html' % date.today().strftime("%d-%m-%Y")))
    51  - os.rename(os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y")), os.path.join(self.options.output_directory,'%s_result_old.html' % date.today().strftime("%d-%m-%Y")))
    52  - os.remove(os.path.join(os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y"))))
    53  - self.report_file = os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y"))
     50 + if report_file=="":
     51 + self.report_file = os.path.join(self.options.output_directory,'%s_result.html' % date.today().strftime("%d-%m-%Y"))
     52 + else:
     53 + self.report_file=os.path.join(self.options.output_directory,report_file)
     54 + if os.path.exists(self.report_file):
     55 + if os.path.exists(self.report_file+"_old"):
     56 + os.remove(self.report_file+"_old")
     57 + os.rename(self.report_file, self.report_file+"_old")
     58 + os.remove(self.report_file)
     59 + 
    54 60   if not os.path.exists(os.path.join(self.options.output_directory,'res')):
    55 61   os.mkdir(os.path.join(self.options.output_directory,'res'))
    56 62   except Exception as ex:
    skipped 6 lines
    63 69   myfile,myfilename=myfiles
    64 70   if os.path.exists(myfile) and not os.path.exists(os.path.join(os.path.join(self.options.output_directory,'res'), myfilename)):
    65 71   shutil.copy2(myfile, os.path.join(os.path.join(self.options.output_directory,'res'), myfilename))
    66  - else:
    67  - self.logging.debug(f"{os.path.exists(myfile)} - {os.path.exists(os.path.join(os.path.join(self.options.output_directory,'res'), myfilename))}")
    68  - 
    69 72   except Exception as ex:
    70 73   self.logging.debug(f" Exception {bcolors.WARNING} in RES copy {bcolors.ENDC}")
    71 74   self.logging.debug(ex)
    skipped 76 lines
    148 151   """
    149 152   self.add_to_resultpage(data)
    150 153   
    151  - results = self.get_credz()
     154 + if 'credz' in report_content :
     155 + results = self.get_credz()
     156 + #popolute credz report filtering :
     157 + if 'browser' in credz_content:
     158 + credz_content.append('browser-internet_explorer')
     159 + credz_content.append('browser-firefox')
     160 + credz_content.append('browser-chrome')
     161 + if 'sysadmin' in credz_content:
     162 + credz_content.append('VNC')
     163 + credz_content.append('MRemoteNG')
     164 + #credz_content.append('VNC')
    152 165   
    153  - data = """<table class="statistics"><TR>
    154  - <Th><a class="firstletter">U</a><a>sername</A></Th>
    155  - <Th><a class="firstletter">P</a><a>assword</A></Th>
    156  - <Th><a class="firstletter">T</a><a>arget</A></Th>
    157  - <Th><a class="firstletter">T</a><a>ype</A></Th>
    158  - <Th><a class="firstletter">P</a><a>illaged_from_computerid</A></Th>
    159  - <Th><a class="firstletter">P</a><a>illaged_from_userid</A></Th></TR>\n"""
     166 + data = """<table class="statistics"><TR>
     167 + <Th><a class="firstletter">U</a><a>sername</A></Th>
     168 + <Th><a class="firstletter">P</a><a>assword</A></Th>
     169 + <Th><a class="firstletter">T</a><a>arget</A></Th>
     170 + <Th><a class="firstletter">T</a><a>ype</A></Th>
     171 + <Th><a class="firstletter">P</a><a>illaged_from_computerid</A></Th>
     172 + <Th><a class="firstletter">P</a><a>illaged_from_userid</A></Th></TR>\n"""
    160 173   
    161  - #<a href="#" id="toggle" onClick="toggle_it('tr1');toggle_it('tr2')">
    162  - current_type=''
    163  - for index,cred in enumerate(results):
    164  - cred_id, file_path, username, password, target, type, pillaged_from_computerid, pillaged_from_userid = cred
    165  - if type != current_type:
    166  - current_type=type
    167  - current_type_count=self.get_credz_count(current_type,'AND username NOT IN ("NL$KM_history") AND target NOT IN ("WindowsLive:target=virtualapp/didlogical","Adobe App Info","Adobe App Prefetched Info","Adobe User Info","Adobe User OS Info","MicrosoftOffice16_Data:ADAL","LegacyGeneric:target=msteams_adalsso/adal_contex")')[0][0]
    168  - data += f"""<TR id={current_type}><TD colspan="6" class="toggle_menu" onClick="toggle_it('{current_type}')"><A>{current_type} ({current_type_count})</A></TD></TR>"""
     174 + #<a href="#" id="toggle" onClick="toggle_it('tr1');toggle_it('tr2')">
     175 + current_type=''
     176 + for index,cred in enumerate(results):
     177 + cred_id, file_path, username, password, target, type, pillaged_from_computerid, pillaged_from_userid = cred
     178 + #filtering data to be included in the report
     179 + if type not in credz_content:
     180 + continue
     181 + if type != current_type:
     182 + current_type=type
     183 + current_type_count=self.get_credz_count(current_type,'AND username NOT IN ("NL$KM_history") AND target NOT IN ("WindowsLive:target=virtualapp/didlogical","Adobe App Info","Adobe App Prefetched Info","Adobe User Info","Adobe User OS Info","MicrosoftOffice16_Data:ADAL","LegacyGeneric:target=msteams_adalsso/adal_contex")')[0][0]
     184 + data += f"""<TR id={current_type}><TD colspan="6" class="toggle_menu" onClick="toggle_it('{current_type}')"><A>{current_type} ({current_type_count})</A></TD></TR>"""
    169 185   
    170 186   
    171  - #Skip infos of
    172  - # WindowsLive:target=virtualapp/didlogical
    173  - untreated_targets =["WindowsLive:target=virtualapp/didlogical","Adobe App Info","Adobe App Prefetched Info","Adobe User Info","Adobe User OS Info","MicrosoftOffice16_Data:ADAL","LegacyGeneric:target=msteams_adalsso/adal_contex"]
    174  - untreated_users = ["NL$KM_history"]
     187 + #Skip infos of
     188 + # WindowsLive:target=virtualapp/didlogical
     189 + untreated_targets =["WindowsLive:target=virtualapp/didlogical","Adobe App Info","Adobe App Prefetched Info","Adobe User Info","Adobe User OS Info","MicrosoftOffice16_Data:ADAL","LegacyGeneric:target=msteams_adalsso/adal_contex"]
     190 + untreated_users = ["NL$KM_history"]
    175 191   
    176  - blacklist_bypass=False
    177  - for untreated in untreated_targets:
    178  - if untreated in target:
    179  - blacklist_bypass=True
    180  - for untreated in untreated_users:
    181  - if untreated in username:
    182  - blacklist_bypass=True
    183  - if blacklist_bypass:
    184  - continue
     192 + blacklist_bypass=False
     193 + for untreated in untreated_targets:
     194 + if untreated in target:
     195 + blacklist_bypass=True
     196 + for untreated in untreated_users:
     197 + if untreated in username:
     198 + blacklist_bypass=True
     199 + if blacklist_bypass:
     200 + continue
    185 201   
    186  - #Get computer infos
    187  - res=self.get_computer_infos(pillaged_from_computerid)
    188  - for index_, res2 in enumerate(res):
    189  - ip, hostname=res2
    190  - computer_info=f"{ip} | {hostname}"
    191  - #pillaged_from_userid
    192  - if pillaged_from_userid != None:
    193  - res=self.get_user_infos(pillaged_from_userid)
    194  - for index_, pillaged_username in enumerate(res):
    195  - pillaged_from_userid=pillaged_username[0]
    196  - else:
    197  - pillaged_from_userid=str(pillaged_from_userid)
     202 + #Get computer infos
     203 + res=self.get_computer_infos(pillaged_from_computerid)
     204 + for index_, res2 in enumerate(res):
     205 + ip, hostname=res2
     206 + computer_info=f"{ip} | {hostname}"
     207 + #pillaged_from_userid
     208 + if pillaged_from_userid != None:
     209 + res=self.get_user_infos(pillaged_from_userid)
     210 + for index_, pillaged_username in enumerate(res):
     211 + pillaged_from_userid=pillaged_username[0]
     212 + else:
     213 + pillaged_from_userid=str(pillaged_from_userid)
    198 214   
    199  - if index % 2 == 0:
    200  - data += f"""<TR class=tableau_resultat_row0 {current_type}=1>"""
    201  - else:
    202  - data += f"""<TR class=tableau_resultat_row1 {current_type}=1>"""
     215 + if index % 2 == 0:
     216 + data += f"""<TR class=tableau_resultat_row0 {current_type}=1>"""
     217 + else:
     218 + data += f"""<TR class=tableau_resultat_row1 {current_type}=1>"""
    203 219   
    204  - if 'admin' in username.lower() : #Pour mettre des results en valeur
    205  - special_style = '''class="cracked"'''
    206  - else:
    207  - special_style = ""
     220 + if 'admin' in username.lower() : #Pour mettre des results en valeur
     221 + special_style = '''class="cracked"'''
     222 + else:
     223 + special_style = ""
    208 224   
    209 225   
    210 226   
    211  - ###Print block
    212  - #Recup des username dans le target #/# a update dans myseatbelt.py pour faire une fonction dump_CREDENTIAL_XXXXX clean
    213  - if "LegacyGeneric:target=MicrosoftOffice1" in target:
    214  - username = f'''{target.split(':')[-1]}'''
    215  - #Les pass LSA sont souvent en Hexa
    216  - #if "LSA" in type:
    217  - try:
    218  - hex_passw=''
    219  - hex_passw=binascii.unhexlify(password).replace(b'>',b'')
    220  - except Exception as ex:
    221  - #print(ex)
    222  - pass
     227 + ###Print block
     228 + #Recup des username dans le target #/# a update dans myseatbelt.py pour faire une fonction dump_CREDENTIAL_XXXXX clean
     229 + if "LegacyGeneric:target=MicrosoftOffice1" in target:
     230 + username = f'''{target.split(':')[-1]}'''
     231 + #Les pass LSA sont souvent en Hexa
     232 + #if "LSA" in type:
     233 + try:
     234 + hex_passw=''
     235 + hex_passw=binascii.unhexlify(password).replace(b'>',b'')
     236 + except Exception as ex:
     237 + #print(ex)
     238 + pass
    223 239   
    224 240   
    225  - for info in [username]:
    226  - data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
    227  - for info in [password]:
    228  - data += f"""<TD {special_style} ><A title="{hex_passw}"> {str(info)[:48]} </A></TD>"""
     241 + for info in [username]:
     242 + data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
     243 + for info in [password]:
     244 + data += f"""<TD {special_style} ><A title="{hex_passw}"> {str(info)[:48]} </A></TD>"""
    229 245   
    230  - #check if info contains a URL
    231  - if 'http:' in target or 'https:' in target:
    232  - info2 = target[target.index('http'):]
    233  - special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
    234  - elif 'ftp:' in target:
    235  - info2 = target[target.index('ftp'):]
    236  - special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
    237  - elif "Domain:target=" in target:
    238  - info2=f'''rdp://full%20address=s:{target[target.index('Domain:target=')+len('Domain:target='):]}:3389&username=s:{username}&audiomode=i:2&disable%20themes=i:1'''
    239  - special_ref = f'''href="{info2}" title="{target}"'''
    240  - elif "LegacyGeneric:target=MicrosoftOffice1" in target:
    241  - target=f'''{target[target.index('LegacyGeneric:target=')+len('LegacyGeneric:target='):]}'''
    242  - special_ref = f'''href="https://login.microsoftonline.com/" target="_blank" title="OfficeLogin"'''
    243  - else:
    244  - special_ref = f'''title="{target}"'''
    245  - data += f"""<TD {special_style} ><A {special_ref}> {str(target)[:48]} </A></TD>"""
     246 + #check if info contains a URL
     247 + if 'http:' in target or 'https:' in target:
     248 + info2 = target[target.index('http'):]
     249 + special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
     250 + elif 'ftp:' in target:
     251 + info2 = target[target.index('ftp'):]
     252 + special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
     253 + elif "Domain:target=" in target:
     254 + info2=f'''rdp://full%20address=s:{target[target.index('Domain:target=')+len('Domain:target='):]}:3389&username=s:{username}&audiomode=i:2&disable%20themes=i:1'''
     255 + special_ref = f'''href="{info2}" title="{target}"'''
     256 + elif "LegacyGeneric:target=MicrosoftOffice1" in target:
     257 + target=f'''{target[target.index('LegacyGeneric:target=')+len('LegacyGeneric:target='):]}'''
     258 + special_ref = f'''href="https://login.microsoftonline.com/" target="_blank" title="OfficeLogin"'''
     259 + else:
     260 + special_ref = f'''title="{target}"'''
     261 + data += f"""<TD {special_style} ><A {special_ref}> {str(target)[:48]} </A></TD>"""
    246 262   
    247  - for info in [type, computer_info, pillaged_from_userid]:
    248  - data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
    249  - data+="""</TR>\n"""
     263 + for info in [type, computer_info, pillaged_from_userid]:
     264 + data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
     265 + data+="""</TR>\n"""
    250 266   
    251  - data += """</TABLE><BR>"""
    252  - self.add_to_resultpage(data)
    253  - ###
     267 + data += """</TABLE><BR>"""
     268 + self.add_to_resultpage(data)
     269 + ###
    254 270   
    255 271   
    256 272   ##### List cookies
    257  - results = self.get_cookies()
     273 + if 'cookies' in report_content:
     274 + results = self.get_cookies()
    258 275   
    259  - data = """<table class="statistics"><TR>
    260  - <Th><a class="firstletter">N</a><a>ame</A></Th>
    261  - <Th><a class="firstletter">V</a><a>alue</A></Th>
    262  - <Th><a class="firstletter">U</a><a>ntil</A></Th>
    263  - <Th><a class="firstletter">T</a><a>arget</A></Th>
    264  - <Th><a class="firstletter">T</a><a>ype</A></Th>
    265  - <Th><a class="firstletter">P</a><a>illaged_from_computerid</A></Th>
    266  - <Th><a class="firstletter">P</a><a>illaged_from_userid</A></Th></TR>\n"""
     276 + data = """<table class="statistics"><TR>
     277 + <Th><a class="firstletter">N</a><a>ame</A></Th>
     278 + <Th><a class="firstletter">V</a><a>alue</A></Th>
     279 + <Th><a class="firstletter">U</a><a>ntil</A></Th>
     280 + <Th><a class="firstletter">T</a><a>arget</A></Th>
     281 + <Th><a class="firstletter">T</a><a>ype</A></Th>
     282 + <Th><a class="firstletter">P</a><a>illaged_from_computerid</A></Th>
     283 + <Th><a class="firstletter">P</a><a>illaged_from_userid</A></Th></TR>\n"""
    267 284   
    268  - # <a href="#" id="toggle" onClick="toggle_it('tr1');toggle_it('tr2')">
    269  - current_type = 'cookies'
    270  - data += f"""<TR id=cookies><TD colspan="7" class="toggle_menu" onClick="toggle_it('cookies')"><A>Cookies ({len(results)})</A></TD></TR>"""
    271  - for index, cred in enumerate(results):
    272  - name,value,expires_utc,target,type,pillaged_from_computerid,pillaged_from_userid = cred
    273  - # Skip infos of
    274  - # Get computer infos
    275  - res = self.get_computer_infos(pillaged_from_computerid)
    276  - for index_, res2 in enumerate(res):
    277  - ip, hostname = res2
    278  - computer_info = f"{ip} | {hostname}"
    279  - # pillaged_from_userid
    280  - if pillaged_from_userid != None:
    281  - res = self.get_user_infos(pillaged_from_userid)
    282  - for index_, pillaged_username in enumerate(res):
    283  - pillaged_from_userid = pillaged_username[0]
    284  - else:
    285  - pillaged_from_userid = str(pillaged_from_userid)
     285 + # <a href="#" id="toggle" onClick="toggle_it('tr1');toggle_it('tr2')">
     286 + current_type = 'cookies'
     287 + data += f"""<TR id=cookies><TD colspan="7" class="toggle_menu" onClick="toggle_it('cookies')"><A>Cookies ({len(results)})</A></TD></TR>"""
     288 + for index, cred in enumerate(results):
     289 + name,value,expires_utc,target,type,pillaged_from_computerid,pillaged_from_userid = cred
     290 + # Skip infos of
     291 + # Get computer infos
     292 + res = self.get_computer_infos(pillaged_from_computerid)
     293 + for index_, res2 in enumerate(res):
     294 + ip, hostname = res2
     295 + computer_info = f"{ip} | {hostname}"
     296 + # pillaged_from_userid
     297 + if pillaged_from_userid != None:
     298 + res = self.get_user_infos(pillaged_from_userid)
     299 + for index_, pillaged_username in enumerate(res):
     300 + pillaged_from_userid = pillaged_username[0]
     301 + else:
     302 + pillaged_from_userid = str(pillaged_from_userid)
    286 303   
    287  - if index % 2 == 0:
    288  - data += f"""<TR class=tableau_resultat_row0 {current_type}=1>"""
    289  - else:
    290  - data += f"""<TR class=tableau_resultat_row1 {current_type}=1>"""
     304 + if index % 2 == 0:
     305 + data += f"""<TR class=tableau_resultat_row0 {current_type}=1>"""
     306 + else:
     307 + data += f"""<TR class=tableau_resultat_row1 {current_type}=1>"""
    291 308   
    292  - special_style = ""
     309 + special_style = ""
    293 310   
    294  - ###Print block
    295  - for info in [name,value]:
    296  - data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
    297  - for info in [expires_utc]: #Formule a change si on intègre des cookies venant d'autre chose que chrome
    298  - try:
    299  - if type == "browser-chrome" :
    300  - data += f"""<TD {special_style} ><A title="{info}"> {(datetime(1601, 1, 1) + timedelta(microseconds=info)).strftime('%b %d %Y %H:%M:%S')} </A></TD>"""
    301  - else:
    302  - data += f"""<TD {special_style} ><A title="{info}"> {(datetime.fromtimestamp(info)).strftime('%b %d %Y %H:%M:%S')} </A></TD>"""
    303  - except:
    304  - data += f"""<TD {special_style} ><A title="{info}"> {info} </A></TD>"""
     311 + ###Print block
     312 + for info in [name,value]:
     313 + data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
     314 + for info in [expires_utc]: #Formule a change si on intègre des cookies venant d'autre chose que chrome
     315 + try:
     316 + if type == "browser-chrome" :
     317 + data += f"""<TD {special_style} ><A title="{info}"> {(datetime(1601, 1, 1) + timedelta(microseconds=info)).strftime('%b %d %Y %H:%M:%S')} </A></TD>"""
     318 + else:
     319 + data += f"""<TD {special_style} ><A title="{info}"> {(datetime.fromtimestamp(info)).strftime('%b %d %Y %H:%M:%S')} </A></TD>"""
     320 + except:
     321 + data += f"""<TD {special_style} ><A title="{info}"> {info} </A></TD>"""
    305 322   
    306  - # check if info contains a URL
    307  - if 'http:' in target or 'https:' in target:
    308  - info2 = target[target.index('http'):]
    309  - special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
    310  - elif 'ftp:' in target:
    311  - info2 = target[target.index('ftp'):]
    312  - special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
    313  - elif "Domain:target=" in target:
    314  - info2 = f'''rdp://full%20address=s:{target[target.index('Domain:target=') + len('Domain:target='):]}:3389&username=s:{username}&audiomode=i:2&disable%20themes=i:1'''
    315  - special_ref = f'''href="{info2}" title="{target}"'''
    316  - elif "LegacyGeneric:target=MicrosoftOffice1" in target:
    317  - target = f'''{target[target.index('LegacyGeneric:target=') + len('LegacyGeneric:target='):]}'''
    318  - special_ref = f'''href="https://login.microsoftonline.com/" target="_blank" title="OfficeLogin"'''
    319  - else:
    320  - special_ref = f'''title="{target}"'''
    321  - data += f"""<TD {special_style} ><A {special_ref}> {str(target)[:48]} </A></TD>"""
     323 + # check if info contains a URL
     324 + if 'http:' in target or 'https:' in target:
     325 + info2 = target[target.index('http'):]
     326 + special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
     327 + elif 'ftp:' in target:
     328 + info2 = target[target.index('ftp'):]
     329 + special_ref = f'''href="{info2}" target="_blank" title="{target}"'''
     330 + elif "Domain:target=" in target:
     331 + info2 = f'''rdp://full%20address=s:{target[target.index('Domain:target=') + len('Domain:target='):]}:3389&username=s:{username}&audiomode=i:2&disable%20themes=i:1'''
     332 + special_ref = f'''href="{info2}" title="{target}"'''
     333 + elif "LegacyGeneric:target=MicrosoftOffice1" in target:
     334 + target = f'''{target[target.index('LegacyGeneric:target=') + len('LegacyGeneric:target='):]}'''
     335 + special_ref = f'''href="https://login.microsoftonline.com/" target="_blank" title="OfficeLogin"'''
     336 + else:
     337 + special_ref = f'''title="{target}"'''
     338 + data += f"""<TD {special_style} ><A {special_ref}> {str(target)[:48]} </A></TD>"""
    322 339   
    323  - for info in [type, computer_info, pillaged_from_userid]:
    324  - data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
    325  - data += """</TR>\n"""
     340 + for info in [type, computer_info, pillaged_from_userid]:
     341 + data += f"""<TD {special_style} ><A title="{info}"> {str(info)[:48]} </A></TD>"""
     342 + data += """</TR>\n"""
    326 343   
    327  - data += """</TABLE><BR>"""
    328  - self.add_to_resultpage(data)
     344 + data += """</TABLE><BR>"""
     345 + self.add_to_resultpage(data)
     346 + 
    329 347   ##### List gathered files
    330  - results = self.get_file()
     348 + if 'files' in report_content:
     349 + results = self.get_file()
    331 350   
    332  - data = """<table class="statistics" id="Files"><TR><Th><a class="firstletter">F</a><a>ilename</A></Th>
    333  - <Th><a class="firstletter">T</a><a>ype</A></Th>
    334  - <Th><a class="firstletter">U</a><a>ser</A></Th>
    335  - <Th><a class="firstletter">I</a><a>p</A></Th></TR>\n"""
    336  - for index, myfile in enumerate(results):
    337  - try:
    338  - file_path, filename, extension, pillaged_from_computerid,pillaged_from_userid = myfile
    339  - res = self.get_computer_infos(pillaged_from_computerid)
    340  - for index, res2 in enumerate(res):
    341  - ip, hostname = res2
    342  - computer_info = f"{ip} | {hostname}"
    343  - res = self.get_user_infos(pillaged_from_userid)
    344  - for index, res2 in enumerate(res):
    345  - username = res2[0]
    346  - special_ref = f'''href="file://{file_path}" target="_blank" title="{filename}"'''
    347  - data += f"""<TR><TD><A {special_ref}> {filename} </A></TD><TD> {extension} </TD><TD> {username} </TD><TD> {computer_info} </TD></TR>\n"""
    348  - except Exception as ex:
    349  - self.logging.debug(f" Exception {bcolors.WARNING} in getting File for {file_path} {bcolors.ENDC}")
    350  - self.logging.debug(ex)
    351  - return False
    352  - data += """</TABLE><BR>"""
    353  - self.add_to_resultpage(data)
     351 + data = """<table class="statistics" id="Files"><TR><Th><a class="firstletter">F</a><a>ilename</A></Th>
     352 + <Th><a class="firstletter">T</a><a>ype</A></Th>
     353 + <Th><a class="firstletter">U</a><a>ser</A></Th>
     354 + <Th><a class="firstletter">I</a><a>p</A></Th></TR>\n"""
     355 + for index, myfile in enumerate(results):
     356 + try:
     357 + file_path, filename, extension, pillaged_from_computerid,pillaged_from_userid = myfile
     358 + res = self.get_computer_infos(pillaged_from_computerid)
     359 + for index, res2 in enumerate(res):
     360 + ip, hostname = res2
     361 + computer_info = f"{ip} | {hostname}"
     362 + res = self.get_user_infos(pillaged_from_userid)
     363 + for index, res2 in enumerate(res):
     364 + username = res2[0]
     365 + special_ref = f'''href="file://{file_path}" target="_blank" title="{filename}"'''
     366 + data += f"""<TR><TD><A {special_ref}> {filename} </A></TD><TD> {extension} </TD><TD> {username} </TD><TD> {computer_info} </TD></TR>\n"""
     367 + except Exception as ex:
     368 + self.logging.debug(f" Exception {bcolors.WARNING} in getting File for {file_path} {bcolors.ENDC}")
     369 + self.logging.debug(ex)
     370 + return False
     371 + data += """</TABLE><BR>"""
     372 + self.add_to_resultpage(data)
    354 373   
    355 374   ##### Identify user / IP relations
    356 375   # Confirm audited scope :
    357  - results = self.get_connected_user()
     376 + if 'connected_user' in report_content:
     377 + results = self.get_connected_user()
    358 378   
    359  - data = """<table class="statistics" id="Connected-users"><TR><Th><a class="firstletter">U</a><a>sername</A></Th>
    360  - <Th><a class="firstletter">I</a><a>P</A></Th></TR>\n"""
     379 + data = """<table class="statistics" id="Connected-users"><TR><Th><a class="firstletter">U</a><a>sername</A></Th>
     380 + <Th><a class="firstletter">I</a><a>P</A></Th></TR>\n"""
    361 381   
    362  - for index, cred in enumerate(results):
    363  - try:
    364  - ip, username = cred
    365  - data += """<TR><TD> %s </TD><TD> %s </TD></TR>\n""" % (username,ip)
    366  - except Exception as ex:
    367  - self.logging.debug(f" Exception {bcolors.WARNING} in Identify user / IP relations for {cred} {bcolors.ENDC}")
    368  - self.logging.debug(ex)
    369  - return False
    370  - data += """</TABLE><BR>"""
    371  - self.add_to_resultpage(data)
     382 + for index, cred in enumerate(results):
     383 + try:
     384 + ip, username = cred
     385 + data += """<TR><TD> %s </TD><TD> %s </TD></TR>\n""" % (username,ip)
     386 + except Exception as ex:
     387 + self.logging.debug(f" Exception {bcolors.WARNING} in Identify user / IP relations for {cred} {bcolors.ENDC}")
     388 + self.logging.debug(ex)
     389 + return False
     390 + data += """</TABLE><BR>"""
     391 + self.add_to_resultpage(data)
    372 392   
    373 393   
    374 394   ##### Identify Local hash reuse
    375  - results = self.get_credz_sam()
    376  - data = """<table class="statistics" id="Local_account_reuse"><TR><Th><a class="firstletter">L</a><a>ocal account reuse : </Th></TR>\n"""
    377  - for index, cred in enumerate(results):
    378  - username, password, type, pillaged_from_computerid = cred
    379  - res = self.get_computer_infos(pillaged_from_computerid)
    380  - for index, res2 in enumerate(res):
    381  - ip, hostname = res2
    382  - computer_info = f"{ip} | {hostname}"
    383  - data += """<TR><TD> %s </TD><TD> %s </TD><TD> %s </TD><TD> %s </TD></TR>\n""" % (username, password, type, computer_info)
    384  - data += """</TABLE><BR>"""
    385  - self.add_to_resultpage(data)
     395 + if 'hash_reuse' in report_content:
     396 + results = self.get_credz_sam()
     397 + data = """<table class="statistics" id="Local_account_reuse"><TR><Th><a class="firstletter">L</a><a>ocal account reuse : </Th></TR>\n"""
     398 + for index, cred in enumerate(results):
     399 + username, password, type, pillaged_from_computerid = cred
     400 + res = self.get_computer_infos(pillaged_from_computerid)
     401 + for index, res2 in enumerate(res):
     402 + ip, hostname = res2
     403 + computer_info = f"{ip} | {hostname}"
     404 + data += """<TR><TD> %s </TD><TD> %s </TD><TD> %s </TD><TD> %s </TD></TR>\n""" % (username, password, type, computer_info)
     405 + data += """</TABLE><BR>"""
     406 + self.add_to_resultpage(data)
    386 407   
    387 408   
    388 409   # Confirm audited scope :
    389  - results = self.get_computers()
    390  - data = """<table class="statistics" id="Scope_Audited"><TR><Th><a class="firstletter">S</a><a>cope Audited : </Th></TR>\n"""
    391  - data += """<TR><Th><a class="firstletter">I</a><a>p</A></Th>
    392  - <Th><a class="firstletter">H</a><a>ostname</A></Th>
    393  - <Th><a class="firstletter">D</a><a>omain</A></Th>
    394  - <Th><a class="firstletter">O</a><a>S</A></Th>
    395  - <Th><a class="firstletter">S</a><a>mb signing enabled</A></Th>
    396  - <Th><a class="firstletter">S</a><a>mb v1</A></Th>
    397  - <Th><a class="firstletter">I</a><a>s Admin</A></Th>
    398  - <Th><a class="firstletter">C</a><a>onnectivity</A></Th>
    399  - </TR>\n"""
     410 + if 'audited_scope' in report_content:
     411 + results = self.get_computers()
     412 + data = """<table class="statistics" id="Scope_Audited"><TR><Th><a class="firstletter">S</a><a>cope Audited : </Th></TR>\n"""
     413 + data += """<TR><Th><a class="firstletter">I</a><a>p</A></Th>
     414 + <Th><a class="firstletter">H</a><a>ostname</A></Th>
     415 + <Th><a class="firstletter">D</a><a>omain</A></Th>
     416 + <Th><a class="firstletter">O</a><a>S</A></Th>
     417 + <Th><a class="firstletter">S</a><a>mb signing enabled</A></Th>
     418 + <Th><a class="firstletter">S</a><a>mb v1</A></Th>
     419 + <Th><a class="firstletter">I</a><a>s Admin</A></Th>
     420 + <Th><a class="firstletter">C</a><a>onnectivity</A></Th>
     421 + </TR>\n"""
    400 422   
    401  - for index, cred in enumerate(results):
    402  - ip, hostname, domain, my_os, smb_signing_enabled,smbv1_enabled,is_admin,connectivity = cred
    403  - data+="<TR>"
    404  - for info in [ip, hostname, domain, my_os]:
    405  - data += f"""<TD> {info} </TD>"""
    406  - if smb_signing_enabled:
    407  - data+="<TD> Ok </TD>"
    408  - else:
    409  - data += """<TD><a class="firstletter"> NOT required </A></TD>"""
    410  - if smbv1_enabled:
    411  - data+="<TD> Yes </TD>"
    412  - else:
    413  - data += "<TD> No </TD>"
    414  - if is_admin:
    415  - data+="""<TD> Admin </A></TD>"""
    416  - else:
    417  - data += """<TD><a class="firstletter"> No </A></TD>"""
    418  - for info in [connectivity]:
    419  - data += f"""<TD> {info} </TD>"""
    420  - data+="</TR>\n"
    421  - data += """</TABLE><BR>\n"""
    422  - self.add_to_resultpage(data)
     423 + for index, cred in enumerate(results):
     424 + ip, hostname, domain, my_os, smb_signing_enabled,smbv1_enabled,is_admin,connectivity = cred
     425 + data+="<TR>"
     426 + for info in [ip, hostname, domain, my_os]:
     427 + data += f"""<TD> {info} </TD>"""
     428 + if smb_signing_enabled:
     429 + data+="<TD> Ok </TD>"
     430 + else:
     431 + data += """<TD><a class="firstletter"> NOT required </A></TD>"""
     432 + if smbv1_enabled:
     433 + data+="<TD> Yes </TD>"
     434 + else:
     435 + data += "<TD> No </TD>"
     436 + if is_admin:
     437 + data+="""<TD> Admin </A></TD>"""
     438 + else:
     439 + data += """<TD><a class="firstletter"> No </A></TD>"""
     440 + for info in [connectivity]:
     441 + data += f"""<TD> {info} </TD>"""
     442 + data+="</TR>\n"
     443 + data += """</TABLE><BR>\n"""
     444 + self.add_to_resultpage(data)
    423 445   
    424 446   #Etat des masterkeyz
    425  - if self.options.debug :
     447 + if self.options.debug and 'masterkeys' in report_content :
    426 448   results=self.get_masterkeys()
    427 449   data = """<table class="statistics" id="Scope_Audited"><TR><Th><a class="firstletter">M</a><a>asterkeys : </Th></TR>\n"""
    428 450   data += """<TR><Th><a class="firstletter">G</a><a>uid</A></Th>
    skipped 1304 lines
Please wait...
Page is in error, reload to recover