├── GUI ├── __init__.py ├── caseanalysis.py ├── convui.sh ├── createcase.py ├── filetab.py ├── generate_forms.py ├── guicommon.py ├── oldforms │ └── exportall.ui ├── pathtab.py ├── plugintab.py ├── reportfuncs.py ├── searchtab.py ├── timelinetab.py └── uifiles │ ├── __init__.py │ ├── registrydecoder.ui │ └── registrydecoder_ui.py ├── README.md ├── __init__.py ├── acquirefiles ├── __init__.py ├── acquire_files.py └── image_classes.py ├── cleanwindows.py ├── common.py ├── datastructures ├── __init__.py ├── strings │ ├── __init__.py │ ├── stringdatabase │ │ ├── __init__.py │ │ ├── dbhandler.py │ │ ├── mysql.py │ │ └── sqlite3handler.py │ └── stringtable.py ├── tree │ ├── __init__.py │ └── paralleltree.py └── values │ ├── __init__.py │ └── valuestable.py ├── errorclasses.py ├── guicontroller.py ├── guimain.py ├── initial_processing ├── __init__.py ├── acquire_files.py ├── evidence_database.py ├── registry_sig.py └── tree_handler.py ├── opencase.py ├── pyinstaller.spec ├── pyinstaller ├── hook-regdecoder.py ├── hook-reporting.report_manager.py └── hook-templates.template_manager.py ├── registryparser ├── __init__.py ├── harness.py ├── regfile.py ├── regkey.py ├── regparser.py └── regvalue.py ├── report_manager.py ├── reporting ├── __init__.py └── report_formats │ ├── commasep.py │ ├── html.py │ ├── pdf.py │ ├── screen_display.py │ └── xls.py ├── start_processing.py ├── template_manager.py └── templates ├── __init__.py ├── template_files ├── BHO.py ├── ShellBagMRU.py ├── ShellBags.py ├── StreamMRU.py ├── acmru.py ├── appinitdlls.py ├── apppaths.py ├── computer_name.py ├── firewall_policy.py ├── ide_devs.py ├── ie_typed_urls.py ├── last_access_disabled.py ├── listusers.py ├── map_network_drive_letters.py ├── map_network_drive_mru.py ├── mmc_mru.py ├── mounted_devices.py ├── mrulist.py ├── muicache.py ├── muicache_update.py ├── profile_list.py ├── recent_docs.py ├── recent_docs_update.py ├── sbp2.py ├── services.py ├── system_run.py ├── system_run_update.py ├── timezone.py ├── typed_paths.py ├── usbstor.py ├── user_assist.py ├── user_run.py ├── user_software.py ├── windows_install_info.py ├── windows_logon_info.py ├── windows_uninstall.py ├── windows_version.py ├── winrar_archive_history.py ├── wireless_networks.py └── wordwheelquery.py └── util ├── __init__.py └── util.py /GUI/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["guimain","uifiles","createcase","common","filetab", "reportfuncs"] 26 | -------------------------------------------------------------------------------- /GUI/caseanalysis.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # draws the initial case handling GUI 26 | 27 | from PyQt4.QtCore import * 28 | from PyQt4.QtGui import * 29 | from PyQt4.QtNetwork import * 30 | 31 | import GUI.guicommon as common 32 | import opencase 33 | import filetab, plugintab 34 | 35 | class caseanalysis: 36 | 37 | def __init__(self, gui): 38 | self.gui = gui 39 | 40 | def start_analysis(self): 41 | self.case = opencase.opencase() 42 | filetab(self).draw() 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /GUI/convui.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mv GUI/uifiles/__init__.py GUI/uifiles/blah 4 | rm GUI/uifiles/*.py 5 | rm GUI/uifiles/*.pyc 6 | mv GUI/uifiles/blah GUI/uifiles/__init__.py 7 | 8 | FILES=GUI/uifiles/*.ui 9 | ext=".py" 10 | 11 | for UI in $FILES 12 | do 13 | pyname=$(echo $UI | sed -e 's/\./_/') 14 | pyname=$pyname$ext 15 | 16 | pyuic4 $UI -o $pyname 17 | 18 | done 19 | 20 | -------------------------------------------------------------------------------- /GUI/pathtab.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from errorclasses import * 26 | 27 | from PyQt4.QtCore import * 28 | from PyQt4.QtGui import * 29 | from PyQt4.QtNetwork import * 30 | 31 | import datetime 32 | 33 | class tmclass: 34 | 35 | def __init__(self, report_vals): 36 | 37 | self.plugin_set_header = 0 38 | self.timestamp = None 39 | self.report_data = report_vals 40 | 41 | class key_info: 42 | 43 | def __init__(self, node, vals): 44 | 45 | self.node = node 46 | self.vals = vals 47 | 48 | class path_params: 49 | 50 | def __init__(self, pathterms, pathsfile, includeVals, startDate, endDate): 51 | 52 | self.pathterms = pathterms 53 | self.pathsfile = pathsfile 54 | self.includeVals = includeVals 55 | self.startDate = startDate 56 | self.endDate = endDate 57 | 58 | class pathtab: 59 | 60 | def __init__(self, gui): 61 | self.name = "Path Tab" 62 | self.active_tabs = {} 63 | 64 | self.gui = gui 65 | 66 | def draw(self): 67 | self.pathinfo_hash = self.gcommon.fill_tree(self.gui, "pathAnalysisTreeWidget") 68 | 69 | def path_terms_file_browse(self): 70 | filename = QFileDialog.getOpenFileName(directory="/home/x/", filter="All (*)", parent=self.gui, caption="Add Paths (newline seperated))") 71 | 72 | self.gui.pathTermsLineEdit.setText(filename) 73 | 74 | # returns None if patterm isn't a path in the current file 75 | def get_path_hits(self, pathterm, includeVals): 76 | 77 | node = self.gcommon.get_tree_node(self, pathterm) 78 | 79 | if not node: 80 | return None 81 | 82 | if includeVals: 83 | # tuple of (name, data, raw data) 84 | vals = self.tapi.reg_get_values(node) 85 | else: 86 | vals = [] 87 | 88 | return [key_info(node, vals)] 89 | 90 | # get results for the given search term(s) and fileid 91 | def handle_run_path_lookup(self, sp, fileid): 92 | 93 | results = [] 94 | 95 | # run over all the searchterms in the same file 96 | for pathterm in sp.pathterms: 97 | hit = self.get_path_hits(pathterm, sp.includeVals) 98 | if hit: 99 | results = results + hit 100 | 101 | # if the user gave a search terms file 102 | if sp.pathsfile != "": 103 | sp.searchterm = "from %s" % sp.pathsfile 104 | # from the input box 105 | else: 106 | sp.searchterm = sp.pathterms[0] 107 | 108 | # remove results that break on the user date filtering 109 | if len(results) and (sp.startDate or sp.endDate): 110 | results = self.gcommon.filter_results(self, results, fileid, sp.startDate, sp.endDate) 111 | 112 | return results 113 | 114 | def do_run_path_lookup(self, fileid, sp): 115 | 116 | (filepath, evi_file, group_name) = self.gcommon.get_file_info(self.pathinfo_hash, fileid) 117 | 118 | self.gui.case_obj.current_fileid = fileid 119 | 120 | # results for fileid 121 | results = self.handle_run_path_lookup(sp, fileid) 122 | 123 | return self.gcommon.search_results(filepath, evi_file, group_name, results, fileid) 124 | 125 | def get_label_text(self, searchterm, filepath): 126 | 127 | return "Results for looking up path %s against %s" % (searchterm, filepath) 128 | 129 | def get_tab_text(self, searchterm): 130 | 131 | return "Path Results - %s" % searchterm 132 | 133 | def do_gen_tab(self, sp, sr, fileid): 134 | 135 | h = self.get_tab_text(sp.searchterm) 136 | l = self.get_label_text(sp.searchterm, sr.filepath) 137 | 138 | return self.gf.path_export_form(self, fileid, h, l) # sr.results 139 | 140 | # results is a list of key_info 141 | def get_report_vals(self, results, fileid): 142 | 143 | ret = [] 144 | 145 | for row in xrange(len(results)): 146 | 147 | r = results[row] 148 | 149 | lastwrite = r.node.timestamps[fileid] 150 | lastwrite = datetime.datetime.fromtimestamp(lastwrite).strftime('%Y/%m/%d %H:%M:%S') 151 | 152 | # add the path and its last write time 153 | ret.append([self.tapi.full_path_node_to_root(r.node), lastwrite]) 154 | 155 | # add any values 156 | for val_ent in r.vals: 157 | (name, val, rval) = val_ent 158 | ret.append(["", name, val]) 159 | 160 | return ret 161 | 162 | # genereates a search result tab and fills the GUI table 163 | def generate_tab(self, sp, sr, fileid): 164 | 165 | tab = self.do_gen_tab(sp, sr, fileid) 166 | 167 | report_vals = self.get_report_vals(sr.results, fileid) 168 | 169 | self.insert_results(tab, report_vals, sp.searchterm, fileid) 170 | 171 | return tab 172 | 173 | # performs the work for a path lookup 174 | # return of None means error 175 | # return of [] means no search matches 176 | def run_path_lookup(self, sp): 177 | 178 | gen_tab = 0 179 | 180 | all_results = self.gcommon.run_cb_on_tree(self, self.do_run_path_lookup, sp, "pathAnalysisTreeWidget") 181 | 182 | if all_results == None: 183 | return 184 | 185 | for results in all_results: 186 | 187 | # generate tab if they are there 188 | if len(results.results) > 0: 189 | tab = self.generate_tab(sp, results, results.fileid) 190 | gen_tab = 1 191 | 192 | # alert if no searches matched across all files ran 193 | if not gen_tab: 194 | self.gui.msgBox("The given path parameters returned no results.") 195 | 196 | def get_path_params(self): 197 | 198 | (pathterms, pathsfile) = self.gcommon.get_search_terms(self.gui, "path") 199 | 200 | if len(pathterms) == 0: 201 | self.gui.msgBox("No path(s) were entered. Unable to process") 202 | return None 203 | 204 | startDate = self.gui.pathStartDateLineEdit.text() 205 | endDate = self.gui.pathEndDateLlineEdit.text() 206 | 207 | includeVals = self.gui.pathValuesCheckBox.isChecked() 208 | 209 | return path_params(pathterms, pathsfile, includeVals, startDate, endDate) 210 | 211 | # called when 'search' is clicked 212 | def viewTree(self): 213 | 214 | sp = self.get_path_params() 215 | 216 | if not sp: 217 | return 218 | 219 | self.run_path_lookup(sp) 220 | 221 | # to catch anyone pulling the stale file id 222 | self.gui.case_obj.current_fileid = -42 223 | 224 | # puts rows into GUI table and keeps records for reporting and switching views 225 | def insert_results(self, tab, report_vals, searchterm, fileid): 226 | 227 | report = self.rm.display_reports[0] 228 | 229 | tab.tblWidget = tab.searchResTable 230 | 231 | tm = tmclass(report_vals) 232 | 233 | self.rm.report_tab_info(report, tm, tab, self.active_tabs, fileid, "Path", "Path Term", searchterm) 234 | 235 | def createReportClicked(self): 236 | self.rh.createReportClicked("Path Analysis Single") 237 | 238 | 239 | -------------------------------------------------------------------------------- /GUI/reportfuncs.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from errorclasses import * 26 | 27 | class report_handler: 28 | 29 | def __init__(self, gui, active_tabs, rm, gf): 30 | self.gui = gui 31 | self.active_tabs = active_tabs 32 | self.rm = rm 33 | self.gf = gf 34 | 35 | def get_plugin_export_format(self, cbox): 36 | 37 | name = unicode(cbox.currentText()) 38 | return self.rm.report_hash[name] 39 | 40 | def get_filename(self, lineedit): 41 | 42 | fname = lineedit.text() 43 | return str(fname) 44 | 45 | def export_report(self, finfoTab, dataTab, cinfo, append=0): 46 | 47 | # information about tab being processed 48 | 49 | try: 50 | tab_info = self.active_tabs[dataTab] 51 | except: 52 | # ugly hack b/c we add things last minute x) 53 | act_tabs = dict(self.gui.plugintab.rh.active_tabs.items() + self.gui.searchtab.rh.active_tabs.items() + self.gui.pathtab.rh.active_tabs.items()) 54 | tab_info = act_tabs[dataTab] 55 | 56 | report = self.get_plugin_export_format(finfoTab.cbox) 57 | repext = "." + report.extension 58 | 59 | filename = self.get_filename(finfoTab.reportname) 60 | 61 | if not filename or len(filename) == 0: 62 | self.gui.msgBox("Create Report button clicked but no report filename was given. Cannot Proceed.") 63 | return None 64 | 65 | # if the user didn't supply an extension, then append it (given from report module) 66 | if not filename.endswith(repext): 67 | filename = filename + repext 68 | 69 | report.report_single(report, filename, tab_info, cinfo) 70 | 71 | if append == 0: 72 | report.close_report() 73 | 74 | return report 75 | 76 | def saveAllPlugins(self, isChecked): 77 | 78 | self.saveAll(self.gui.plugintab.active_tabs, "Bulk Plugin Export") 79 | 80 | def saveAllSearches(self, isChecked): 81 | 82 | self.saveAll(self.gui.searchtab.active_tabs, "Bulk Search Export") 83 | 84 | def saveAllPaths(self, isChecked): 85 | 86 | self.saveAll(self.gui.pathtab.active_tabs, "Bulk Path Export") 87 | 88 | # saves all active tabs 89 | def savePluginsSearches(self, isChecked): 90 | 91 | #self.saveAll(dict(self.gui.searchtab.active_tabs.items() + self.gui.plugintab.active_tabs.items() + self.gui.pathtab.active_tabs.items()), "Bulk Search, Plugin, and Path Export") 92 | self.saveAll(None, "Bulk Search, Plugin, and Path Export") 93 | 94 | # called when the menu report plugin is clicked, loads form that allows for exporting 95 | def saveAll(self, active_tabs, header): 96 | 97 | # generate form 98 | tab = self.gf.export_all_form(self, header) 99 | 100 | tab.active_tabs = active_tabs 101 | 102 | # switch GUI view to it 103 | self.gui.analysisTabWidget.setCurrentWidget(tab) 104 | 105 | # called when Export All is clicked on a bulk export tab 106 | def exportAll(self): 107 | 108 | currentTab = self.gui.analysisTabWidget.currentWidget() 109 | 110 | if not hasattr(currentTab, "active_tabs"): 111 | self.gui.msgBox("Export All clicked when no tabs were active") 112 | return 113 | 114 | extabs = currentTab.active_tabs 115 | 116 | # bulk export 117 | if not extabs: 118 | extabs = dict(self.gui.searchtab.active_tabs.items() + self.gui.plugintab.active_tabs.items() + self.gui.pathtab.active_tabs.items()) 119 | 120 | if len(extabs) == 0: 121 | self.gui.msgBox("Export All clicked when no tabs were active") 122 | return 123 | 124 | # don't export diff tabs 125 | remove = [] 126 | for tab in extabs: 127 | if hasattr(tab, "diff_tab"): 128 | remove.append(tab) 129 | 130 | for t in remove: 131 | del extabs[t] 132 | 133 | report = self.get_plugin_export_format(currentTab.cbox) 134 | 135 | i = 0 136 | 137 | # for each active tab 138 | for tab in extabs: 139 | 140 | if hasattr(tab, "do_not_export"): 141 | continue 142 | 143 | cinfo = not i 144 | repinst = self.export_report(currentTab, tab, cinfo, 1) 145 | i = i + 1 146 | 147 | if i > 0 and repinst: 148 | repinst.close_report() 149 | 150 | self.gui.msgBox("Report Successfully Created") 151 | 152 | else: 153 | self.gui.msgBox("No Report Created. No Active Analysis Tabs were found.") 154 | 155 | # clicked from indiviual plugin output forms 156 | def createReportClicked(self, context): 157 | 158 | currentTab = self.gui.analysisTabWidget.currentWidget() 159 | 160 | #if currentTab in self.active_tabs: 161 | self.export_report(currentTab, currentTab, 1) 162 | 163 | self.gui.msgBox("Report Successfully Created") 164 | 165 | -------------------------------------------------------------------------------- /GUI/timelinetab.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from errorclasses import * 26 | 27 | from PyQt4.QtCore import * 28 | from PyQt4.QtGui import * 29 | from PyQt4.QtNetwork import * 30 | 31 | import datetime, codecs 32 | 33 | class timeline_params: 34 | 35 | def __init__(self, fd, outputfile, startDate, endDate): 36 | 37 | self.fd = fd 38 | self.outputfile = outputfile 39 | self.startDate = startDate 40 | self.endDate = endDate 41 | 42 | class timelinetab: 43 | 44 | def __init__(self, gui): 45 | self.name = "Path Tab" 46 | self.active_tabs = {} 47 | 48 | self.gui = gui 49 | 50 | def draw(self): 51 | self.info_hash = self.gcommon.fill_tree(self.gui, "timelineTreeWidget") 52 | 53 | def timeline_output_browse(self): 54 | filename = QFileDialog.getSaveFileName(directory="/home/x/", filter="All (*)", parent=self.gui, caption="Timeline Output File") 55 | 56 | self.gui.timelineLineEdit.setText(filename) 57 | 58 | def get_timeline_params(self): 59 | 60 | outputfile = self.gui.timelineLineEdit.text() 61 | 62 | if not outputfile: 63 | self.gui.msgBox("No output file was entereted!") 64 | return None 65 | 66 | outputfile = unicode(outputfile) 67 | 68 | if len(outputfile) == 0: 69 | self.gui.msgBox("No output file was entereted!") 70 | return None 71 | 72 | if self.gui.excelRadioButton.isChecked(): 73 | ext = ".tsv" 74 | else: 75 | ext = ".txt" 76 | 77 | if not outputfile.endswith(ext): 78 | outputfile = outputfile + ext 79 | 80 | try: 81 | fd = codecs.open(outputfile, "a+", encoding="UTF-8") 82 | except: 83 | self.gui.msgBox("Unable to open output file for writing!") 84 | return None 85 | 86 | startDate = self.gui.timelineStartDateLineEdit.text() 87 | endDate = self.gui.timelineEndDateLlineEdit_2.text() 88 | 89 | if startDate != "": 90 | s = self.gcommon.parse_date(self, startDate, "start") 91 | else: 92 | s = 1 93 | 94 | if endDate != "": 95 | e = self.gcommon.parse_date(self, endDate, "end") 96 | else: 97 | e = 1 98 | 99 | # input error 100 | if s == None or e == None: 101 | ret = None 102 | else: 103 | ret = timeline_params(fd, outputfile, startDate, endDate) 104 | 105 | return ret 106 | 107 | def run_timeline(self, fileid, sp): 108 | 109 | filepath = self.gcommon.get_file_info(self.info_hash, fileid)[0] 110 | 111 | # walk each node of the tree looking for entries that belong to this fileid 112 | nodehash = self.tapi.tree.nodehash 113 | 114 | numnodes = len(nodehash) 115 | 116 | for idx in xrange(0, numnodes+2): 117 | 118 | idx = "%d" % idx 119 | 120 | if idx in nodehash: 121 | node = nodehash[idx] 122 | else: 123 | continue 124 | 125 | # ensure fileid is correct 126 | if fileid in node.fileids: 127 | 128 | # filter by dates 129 | if sp.startDate or sp.endDate: 130 | res = self.gcommon.filter_results(self, [node], fileid, sp.startDate, sp.endDate) 131 | else: 132 | res = [1] 133 | 134 | if len(res) == 1: 135 | 136 | path = self.tapi.full_path_node_to_root(node) 137 | 138 | lastwrite = node.timestamps[fileid] 139 | 140 | if self.gui.excelRadioButton.isChecked(): 141 | lastwrite = datetime.datetime.fromtimestamp(lastwrite).strftime('%Y/%m/%d %H:%M:%S') 142 | sp.fd.write("%s\t%s\t%s\n" % (filepath, path, lastwrite)) 143 | 144 | else: 145 | # these three lines will write out autopsy format, regtime.pl 146 | filepath = filepath.replace("|", ",") 147 | sp.fd.write("0|%s:%s|0|0|0|0|0|0|%d|0|0\n" % (filepath, path, lastwrite)) 148 | 149 | # called when 'timeline' is clicked 150 | def viewTree(self): 151 | 152 | sp = self.get_timeline_params() 153 | 154 | if not sp or sp == None: 155 | return 156 | 157 | self.gcommon.run_cb_on_tree(self, self.run_timeline, sp, "timelineTreeWidget") 158 | 159 | sp.fd.close() 160 | 161 | self.gui.msgBox("Timeline Created") 162 | 163 | # to catch anyone pulling the stale file id 164 | self.gui.case_obj.current_fileid = -42 165 | 166 | 167 | -------------------------------------------------------------------------------- /GUI/uifiles/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["registrydecoder_ui"] 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Registry Decoder 2 | 3 | Registry Decoder provides a single tool in which to perform browsing, searching, analysis, and reporting of registry hive contents. All functionality is exposed through an intuitive GUI interface and accommodates even novice investigators. 4 | 5 | Registry Decoder also acts as a great resource for new research and experimenting within the registry. To see some ideas of open research areas in the registry analysis and how you can contribute to the project, please see our research page. 6 | 7 | ###### NOTE 8 | 9 | This project is no longer being maintained and is just being hosted here for posterity. 10 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["acquirers", "common", "GUI", "registryparser", "templates", "datastructures", "initial_processing", "reporting", "errorclasses", "template_manager". "opencase"] 26 | 27 | -------------------------------------------------------------------------------- /acquirefiles/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["acquire_files", "aq_common", "image_classes"] 26 | -------------------------------------------------------------------------------- /acquirefiles/image_classes.py: -------------------------------------------------------------------------------- 1 | # taken from samples/images.py of pytsk3 2 | 3 | """This module selects a suitable image info object based on the type.""" 4 | import bisect 5 | import ewf 6 | import pytsk3 7 | import sys 8 | 9 | 10 | class EWFImgInfo(pytsk3.Img_Info): 11 | """An image info class which uses ewf as a backing reader. 12 | 13 | All we really need to do to provide TSK with the ability to read image formats 14 | is override the methods below. 15 | """ 16 | 17 | def __init__(self, *paths_to_ewf_files): 18 | self.fd = ewf.ewffile(*paths_to_ewf_files) 19 | # Make sure to call the original base constructor. 20 | pytsk3.Img_Info.__init__(self, "") 21 | 22 | def get_size(self): 23 | """This should return the size of the image.""" 24 | return self.fd.size 25 | 26 | def read(self, off, length): 27 | """This method simply returns data from a particular offset.""" 28 | self.fd.seek(off) 29 | return self.fd.read(length) 30 | 31 | def close(self): 32 | """Dispose of the underlying file like object.""" 33 | self.fd.close() 34 | 35 | 36 | class SplitImage(pytsk3.Img_Info): 37 | """Virtualize access to split images. 38 | 39 | Note that unlike other tools (e.g. affuse) we do not assume that the images 40 | are the same size. 41 | """ 42 | 43 | def __init__(self, *files): 44 | self.fds = [] 45 | self.offsets = [0] 46 | offset = 0 47 | 48 | for fd in files: 49 | # Support either a filename or file like objects 50 | if not hasattr(fd, "read"): 51 | fd = open(fd, "rb") 52 | 53 | fd.seek(0,2) 54 | 55 | offset += fd.tell() 56 | self.offsets.append(offset) 57 | self.fds.append(fd) 58 | 59 | self.size = offset 60 | 61 | # Make sure to call the original base constructor. 62 | pytsk3.Img_Info.__init__(self, "") 63 | 64 | def get_size(self): 65 | return self.size 66 | 67 | def read(self, offset, length): 68 | """Read a buffer from the split image set. 69 | 70 | Handles the buffer straddling images. 71 | """ 72 | result = "" 73 | 74 | # The total available size in the file 75 | length = int(length) 76 | length = min(length, long(self.size) - offset) 77 | 78 | while length > 0: 79 | data = self._ReadPartial(offset, length) 80 | if not data: break 81 | 82 | length -= len(data) 83 | result += data 84 | offset += len(data) 85 | 86 | return result 87 | 88 | def _ReadPartial(self, offset, length): 89 | """Read as much as we can from the current image.""" 90 | # The part we need to read from. 91 | idx = bisect.bisect_right(self.offsets, offset + 1) - 1 92 | fd = self.fds[idx] 93 | 94 | # The offset this part is in the overall image 95 | img_offset = self.offsets[idx] 96 | fd.seek(offset - img_offset) 97 | 98 | # This can return less than length 99 | return fd.read(length) 100 | 101 | -------------------------------------------------------------------------------- /cleanwindows.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os 26 | import subprocess 27 | 28 | # Delete the files first. 29 | 30 | for dirpath, dirnames, filenames in os.walk(os.getcwd()): 31 | for each_file in filenames: 32 | if each_file.endswith('.pyc'): 33 | if os.path.exists(os.path.join(dirpath, each_file)): 34 | os.remove(os.path.join(dirpath, each_file)) 35 | -------------------------------------------------------------------------------- /common.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import sys, os, sqlite3, getopt 26 | 27 | from datetime import date, datetime 28 | 29 | import common 30 | 31 | import opencase 32 | 33 | import template_manager as tmmod 34 | 35 | def usage(): 36 | 37 | print "python opencase.py " 38 | print "See the instructions file for complete description" 39 | sys.exit(1) 40 | 41 | def parse_cmdline(gui, args): 42 | 43 | try: 44 | opts, args = getopt.getopt(sys.argv[1:], "d:", ["directory="]) 45 | except getopt.GetoptError, err: 46 | print "usage: python guimain.py" 47 | print "optional argument: (-d/--directory) to specify an extra plugin directory" 48 | sys.exit(1) 49 | 50 | directories = "" 51 | 52 | for o, a in opts: 53 | 54 | if o in ("-d", "--directory"): 55 | directories = a 56 | 57 | 58 | if directories: 59 | gui.plugin_dirs = directories.split(";") 60 | else: 61 | gui.plugin_dirs = [] 62 | 63 | def connect_db(directory, db_name): 64 | 65 | dbname = os.path.join(directory, db_name) 66 | conn = sqlite3.connect(dbname) 67 | cursor = conn.cursor() 68 | 69 | return (conn, cursor) 70 | 71 | def die(str): 72 | 73 | print "FATAL: %s" % str 74 | sys.exit(1) 75 | 76 | hive_types = ["SOFTWARE", "SYSTEM", "SECURITY", "NTUSER", "SAM", "USRCLASS"] 77 | 78 | def plugin_cmdline(): 79 | 80 | try: 81 | case_dir = sys.argv[1] 82 | plugin_name = sys.argv[2] 83 | fileid = int(sys.argv[3]) 84 | except: 85 | usage() 86 | 87 | try: 88 | extra = sys.argv[4] 89 | extra = extra.split(";") 90 | except: 91 | extra = [] 92 | 93 | # open the case and get the tree 94 | o = opencase.opencase(case_dir) 95 | o.current_fileid = fileid 96 | 97 | tm = tmmod.TemplateManager() 98 | tm.load_templates(o, extra) 99 | 100 | templates = tm.get_loaded_templates() 101 | 102 | ran = 0 103 | 104 | for t in templates: 105 | if t.pluginname == plugin_name: 106 | t.run_me() 107 | ran = 1 108 | break 109 | 110 | if ran: 111 | print "------output for %s------" % plugin_name 112 | 113 | for val_list in tm.report_data: 114 | for val in val_list: 115 | print val, 116 | print "" 117 | 118 | else: 119 | print "invalid plugin given" 120 | 121 | 122 | -------------------------------------------------------------------------------- /datastructures/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["tree","values","strings"] 26 | -------------------------------------------------------------------------------- /datastructures/strings/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["stringtable"] 26 | -------------------------------------------------------------------------------- /datastructures/strings/stringdatabase/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["dbhandler","sqlite3"] 26 | -------------------------------------------------------------------------------- /datastructures/strings/stringdatabase/dbhandler.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | 26 | import sqlite3handler 27 | 28 | class dbhandler: 29 | 30 | def __init__(self, dbtype, case_dir): 31 | 32 | self.databases = { "sqlite3" : sqlite3handler.sqlite3class } 33 | 34 | self.handle = self.set_dbhandle(dbtype, case_dir) 35 | 36 | def get_dbhandle(self): 37 | 38 | return self.handle 39 | 40 | def set_dbhandle(self, dbtype, case_dir): 41 | 42 | if dbtype in self.databases: 43 | ret = self.databases[dbtype](case_dir) 44 | else: 45 | print "Invalid database type sent to get_dbhandle %s" % dbtype 46 | 47 | return ret 48 | 49 | 50 | -------------------------------------------------------------------------------- /datastructures/strings/stringdatabase/mysql.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # mysql string table 26 | 27 | import MySQLdb, util 28 | 29 | class mysql: 30 | 31 | def __init__(self): 32 | util.die("Mysql database not implemented") 33 | 34 | 35 | -------------------------------------------------------------------------------- /datastructures/strings/stringdatabase/sqlite3handler.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import sqlite3, os 26 | 27 | class sqlite3class: 28 | 29 | def __init__(self, case_dir): 30 | 31 | self.connect_db(case_dir) 32 | self.create_database() 33 | 34 | def commit_db(self): 35 | self.conn.commit() 36 | 37 | def apply_pragmas(self): 38 | 39 | self.cursor.execute("PRAGMA default_cache_size=50000") 40 | self.cursor.execute("PRAGMA synchronous=OFF") 41 | self.cursor.execute("PRAGMA count_changes=OFF") 42 | self.cursor.execute("PRAGMA journal_mode=MEMORY") 43 | self.cursor.execute("PRAGMA temp_store=2") 44 | 45 | def connect_db(self, case_dir): 46 | 47 | self.filename = os.path.join(case_dir,"stringtable.db") 48 | self.conn = sqlite3.connect(self.filename) 49 | self.cursor = self.conn.cursor() 50 | 51 | self.apply_pragmas() 52 | 53 | # creates the database and writes it to disk 54 | def create_database(self): 55 | 56 | self.apply_pragmas() 57 | 58 | # they already exist if new evidence is being added 59 | try: 60 | self.cursor.execute("create table stringtable (string text unique collate nocase, id integer primary key asc)") 61 | self.cursor.execute("create index searchindex on stringtable (string collate nocase)") 62 | except: 63 | pass 64 | 65 | self.conn.commit() 66 | 67 | def insert_string(self, instr): 68 | 69 | self.cursor.execute("insert or replace into stringtable (string) values (?)",[instr]) 70 | 71 | sid = self.cursor.execute("SELECT last_insert_rowid()").fetchone()[0] 72 | 73 | return sid 74 | 75 | def fetch_one(self): 76 | 77 | ret = self.cursor.fetchone() 78 | 79 | if ret: 80 | ret = ret[0] 81 | else: 82 | ret = -1 83 | 84 | return ret 85 | 86 | def string_id(self, searchstr): 87 | 88 | self.cursor.execute("select id from stringtable where string=?",[searchstr]) 89 | 90 | res = self.cursor.fetchall() 91 | 92 | #if len(res) != 1: 93 | #print "got %d hits for %s" % (len(res), searchstr) 94 | 95 | if res and res[0]: 96 | ret = res[0][0] 97 | else: 98 | ret = -1 99 | 100 | return ret 101 | #return self.fetch_one() 102 | 103 | def search_ids(self, searchstr): 104 | 105 | # allow users to search with wildcards 106 | searchstr = searchstr.replace("*", "%") 107 | 108 | self.cursor.execute("select id from stringtable where string like ?",["%" + searchstr + "%"]) 109 | 110 | res = self.cursor.fetchall() 111 | 112 | # make a list of the actual strings 113 | if res: 114 | ret = [x[0] for x in res] 115 | else: 116 | ret = None 117 | 118 | #print "found %d strings that match %s" % (len(ret), searchstr) 119 | 120 | return ret 121 | 122 | def idxtostr(self, sid): 123 | 124 | self.cursor.execute("select string from stringtable where id=?",[sid]) 125 | 126 | ret = self.fetch_one() 127 | 128 | if ret == -1: 129 | ret = None 130 | 131 | return ret 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /datastructures/strings/stringtable.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import sys 26 | import datastructures.strings.stringdatabase.dbhandler as sdbm 27 | 28 | class stringtbl: 29 | 30 | def __init__(self, case_dir): 31 | self.idxlookup = {} 32 | self.strlookup = {} 33 | self.sdb = sdbm.dbhandler("sqlite3",case_dir).get_dbhandle() 34 | self.db_connect(case_dir) 35 | 36 | self.hits = 0 37 | self.misses = 0 38 | 39 | def db_connect(self, cd): 40 | self.sdb.connect_db(cd) 41 | 42 | # sqlite has to commit to the disk explicility 43 | # but it kills performance to do it after every insert 44 | def commit_db(self): 45 | self.sdb.commit_db() 46 | 47 | def add_string(self, instr): 48 | 49 | # inserts into database (if not already there) and returns string id 50 | sid = self.sdb.insert_string(instr) 51 | return sid 52 | 53 | def precache_values(self): 54 | 55 | self.sdb.cursor.execute("select string,id from stringtable order by id limit 128000") 56 | strings = self.sdb.cursor.fetchall() 57 | 58 | for (searchstr, sid) in strings: 59 | 60 | self.idxlookup[sid] = searchstr 61 | self.strlookup[searchstr] = sid 62 | 63 | # returns id for string, if it doesn't exist, returns -1 64 | def string_id(self, searchstr): 65 | 66 | if searchstr in self.strlookup: 67 | sid = self.strlookup[searchstr] 68 | else: 69 | sid = self.sdb.string_id(searchstr) 70 | 71 | #if searchstr in ("services", "Services"): 72 | # print "sid %d for %s" % (sid, searchstr) 73 | 74 | # cache value 75 | if sid != -1: 76 | self.idxlookup[sid] = searchstr 77 | self.strlookup[searchstr] = sid 78 | 79 | return sid 80 | 81 | 82 | # returns the correspodning string or None 83 | def idxtostr(self, sid): 84 | # we do *not* cache from add_string 85 | # so this only finds searched for strings 86 | if sid in self.idxlookup: 87 | ret = self.idxlookup[sid] 88 | else: 89 | ret = self.sdb.idxtostr(sid) 90 | 91 | return ret 92 | 93 | # 94 | def nodetostr(self, node): 95 | return self.idxtostr(node.sid) 96 | 97 | 98 | # if searchstr doesn't exists it adds it and returns id of searchstr 99 | def getadd_string(self, searchstr): 100 | 101 | sid = self.string_id(searchstr) 102 | 103 | if sid == -1: 104 | sid = self.add_string(searchstr) 105 | 106 | return sid 107 | 108 | def search_ids(self, searchstr): 109 | 110 | return self.sdb.search_ids(searchstr) 111 | 112 | 113 | -------------------------------------------------------------------------------- /datastructures/tree/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["paralleltree.py"] 26 | -------------------------------------------------------------------------------- /datastructures/values/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["valuestable"] 26 | -------------------------------------------------------------------------------- /datastructures/values/valuestable.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import common 26 | import sys, sqlite3, os, types, struct 27 | 28 | from datastructures.strings.stringtable import * 29 | 30 | class nodevalue: 31 | 32 | def __init__(self, nodeid, namesid, asciisid, rawsid, regtype): 33 | 34 | self.nodeid = nodeid 35 | self.namesid = namesid 36 | self.asciisid = asciisid 37 | self.rawsid = rawsid 38 | self.regtype = regtype 39 | 40 | def __eq__(self, other): 41 | 42 | return self.nodeid == other.nodeid and \ 43 | self.namesid == other.namesid and \ 44 | self.asciisid == other.asciisid and \ 45 | self.regtype == other.regtype 46 | 47 | 48 | class valuesholder: 49 | 50 | def __init__(self, obj): 51 | self.obj = obj 52 | self.stringtable = obj.stringtable 53 | self.db_connect(obj.case_directory) 54 | 55 | self.vid_cache = {} 56 | 57 | self.before_pickle() 58 | 59 | def before_pickle(self): 60 | self.vals_hash = {} 61 | 62 | def db_connect(self, case_dir): 63 | 64 | self.conn = sqlite3.connect(os.path.join(case_dir, "namedata.db")) 65 | self.cursor = self.conn.cursor() 66 | 67 | self.cursor.execute("PRAGMA default_cache_size=20000") 68 | self.cursor.execute("PRAGMA synchronous=OFF") 69 | self.cursor.execute("PRAGMA count_changes=OFF") 70 | self.cursor.execute("PRAGMA journal_mode=MEMORY") 71 | self.cursor.execute("PRAGMA temp_store=2") 72 | 73 | def get_ascii_type(self, asciidata): 74 | 75 | if not asciidata: 76 | return "" 77 | 78 | atype = type(asciidata) 79 | 80 | if atype == list: 81 | asciidata = ",".join([x for x in asciidata]) 82 | 83 | elif atype == bytearray: 84 | asciidata = asciidata.decode("utf-16", "replace") 85 | 86 | elif atype == str: 87 | asciidata = asciidata.decode("utf-8", "replace") 88 | 89 | elif atype == int: 90 | asciidata = "%d" % asciidata 91 | 92 | elif atype == long: 93 | asciidata = "%ld" % asciidata 94 | 95 | elif atype == unicode: 96 | pass 97 | 98 | else: 99 | print "Unknown type: %s | %s" % (atype,asciidata) 100 | 101 | return asciidata 102 | 103 | def record_name_data(self, val): 104 | 105 | if not val.name or val.name == "": 106 | name = "NONE" 107 | else: 108 | name = self.get_ascii_type(val.name) 109 | 110 | regtype = val.type_of_data 111 | 112 | asciidata = self.get_ascii_type(val.data) 113 | 114 | if val.data and regtype == 3: # REG_BINARY 115 | rawdata = "".join(["%.02x" % r for r in val.data]) 116 | else: 117 | rawdata = asciidata 118 | 119 | nid = self.stringtable.getadd_string(name) 120 | aid = self.stringtable.getadd_string(asciidata) 121 | rid = self.stringtable.getadd_string(rawdata) 122 | 123 | key = "%d|%d|%d|%s" % (nid, aid, rid, regtype) 124 | 125 | if not key in self.vals_hash: 126 | 127 | self.cursor.execute("insert into keyvalues (namesid, rawsid, asciisid, regtype) values (?,?,?,?) ", \ 128 | (nid, rid, aid, regtype)) 129 | 130 | vid = self.cursor.execute("SELECT last_insert_rowid()").fetchone()[0] 131 | 132 | self.vals_hash[key] = vid 133 | 134 | else: 135 | vid = self.vals_hash[key] 136 | 137 | return vid 138 | 139 | # set the vid for each node 140 | def create_values(self, node, fileid): 141 | 142 | valuelist = node.valuelist 143 | 144 | # list of values from reg parser - right pane 145 | for val in valuelist: 146 | vid = self.record_name_data(val) 147 | 148 | # associate the name/value pair with its node & fileid 149 | if not vid in node.values: 150 | node.values[vid] = {} 151 | 152 | if not fileid in node.values[vid]: 153 | node.values[vid][fileid] = 1 154 | 155 | if not vid in self.vid_cache: 156 | self.vid_cache[vid] = {} 157 | 158 | if not node in self.vid_cache[vid]: 159 | self.vid_cache[vid][node] = 1 160 | 161 | def or_statement(self, column, int_list): 162 | 163 | fstr = "" 164 | 165 | if int_list: 166 | fstr = "%s in (" % column 167 | fstr = fstr + ",".join(["%d" % sid for sid in int_list]) + ") " 168 | 169 | return fstr 170 | 171 | def check_fileids(self, node_fileids, good_fileids): 172 | 173 | # not a node for the root 174 | if good_fileids[0] == -1: 175 | goodids = None 176 | else: 177 | goodids = list(set(good_fileids) & set(node_fileids)) 178 | 179 | return goodids 180 | 181 | def values_for_node(self, node, fileids, extra_query=""): 182 | 183 | ret = [] 184 | 185 | if not node: 186 | return ret 187 | 188 | for vid in node.values: 189 | 190 | cur = [] 191 | 192 | # get the fileids for this particular value 193 | node_fileids = node.values[vid].keys() 194 | 195 | if not self.check_fileids(node_fileids, fileids): 196 | continue 197 | 198 | query = "select namesid,asciisid,rawsid,regtype from keyvalues where id=%d " % vid 199 | 200 | query = query + extra_query 201 | 202 | self.cursor.execute(query) 203 | 204 | for v in self.cursor.fetchall(): 205 | 206 | cur.append(nodevalue(node.nodeid, v[0], v[1], v[2], v[3])) 207 | 208 | ret = ret + cur 209 | 210 | return ret 211 | 212 | def key_name(self, node, name, fileids): 213 | 214 | sid = self.stringtable.string_id(name) 215 | 216 | if sid: 217 | ret = self.values_for_node(node, fileids, "and namesid=%d" % sid) 218 | else: 219 | ret = None 220 | 221 | return ret 222 | 223 | def key_name_value(self, node, name, value, fileids): 224 | 225 | nid = self.stringtable.string_id(name) 226 | vid = self.stringtable.string_id(value) 227 | 228 | if vid and nid: 229 | ret = self.values_for_node(node, fileids, "and namesid=%d and asciisid=%d" % (nid, vid)) 230 | else: 231 | ret = None 232 | 233 | return ret 234 | 235 | def do_nodevals_for_search(self, sidcolumn, searchfor, fileids, partial): 236 | 237 | ret = [] 238 | 239 | if partial: 240 | sids = self.stringtable.search_ids(searchfor) 241 | else: 242 | sids = self.stringtable.string_id(searchfor) 243 | if sids: 244 | sids = [sids] 245 | 246 | if sids and sids != -1: 247 | 248 | orp = self.or_statement(sidcolumn, sids) 249 | 250 | query = "select id from keyvalues where %s" % orp 251 | 252 | self.cursor.execute(query) 253 | 254 | # the value ids that matched the search 255 | vids = [x[0] for x in self.cursor.fetchall()] 256 | 257 | # remove where the same name/data matched multiple times 258 | vids = list(set(vids)) 259 | 260 | # get the value id for all matching nodes 261 | for vid in vids: 262 | 263 | if not vid in self.vid_cache: 264 | continue 265 | 266 | nodes = self.vid_cache[vid].keys() 267 | 268 | # get the values for each node 269 | for node in nodes: 270 | 271 | ret = ret + self.values_for_node(node, fileids, "and " + orp) 272 | 273 | return ret 274 | 275 | def nodevals_for_search(self, sidcolumn, searchfor, fileids, partial): 276 | 277 | ret = self.do_nodevals_for_search(sidcolumn, searchfor, fileids, partial) 278 | 279 | filtered = [] 280 | 281 | ''' 282 | This fixes the issue where 'names' would show up in search results multiple times 283 | We could define __hash__ and then do something like list(set()) but then we have to worry about collisions 284 | Since the lists are always going to be small, it doesn't seem worth the risk 285 | ''' 286 | for node in ret: 287 | 288 | if node not in filtered: 289 | filtered.append(node) 290 | 291 | return filtered 292 | 293 | def names_for_search_partial(self, searchfor, fileids): 294 | return self.nodevals_for_search("namesid", searchfor, fileids, 1) 295 | 296 | def names_for_search(self, searchfor, fileids): 297 | return self.nodevals_for_search("namesid", searchfor, fileids, 0) 298 | 299 | def data_for_search_partial(self, searchfor, fileids): 300 | return self.nodevals_for_search("asciisid", searchfor, fileids, 1) 301 | 302 | def data_for_search(self, searchfor, fileids): 303 | return self.nodevals_for_search("asciisid", searchfor, fileids, 0) 304 | 305 | def rawdata_for_search_partial(self, searchfor, fileids): 306 | return self.nodevals_for_search("rawsid", searchfor, fileids, 1) 307 | 308 | def rawdata_for_search(self, searchfor, fileids): 309 | return self.nodevals_for_search("rawsid", searchfor, fileids, 0) 310 | 311 | # returns the ascii string 312 | def get_value_string(self, val): 313 | return self.stringtable.idxtostr(val.asciisid) 314 | 315 | def get_raw_value_string(self, val): 316 | return self.stringtable.idxtostr(val.rawsid) 317 | 318 | def get_name_string(self, val): 319 | return self.stringtable.idxtostr(val.namesid) 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /errorclasses.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | class RDError(Exception): 26 | 27 | def __init__(self, value): 28 | self.value = value 29 | 30 | def __str__(self): 31 | return repr(self.value) 32 | 33 | class MsgBoxError(Exception): 34 | 35 | def __init__(self, value): 36 | self.value = value 37 | 38 | def __str__(self): 39 | return self.value 40 | 41 | class RequiredKeyError(Exception): 42 | 43 | def __init__(self, value): 44 | self.value = value 45 | 46 | def __str__(self): 47 | return self.value 48 | 49 | class RegFiKeyError(Exception): 50 | 51 | def __init__(self, value): 52 | self.value = value 53 | 54 | def __str__(self): 55 | return self.value 56 | 57 | class RegAcquireError(Exception): 58 | 59 | def __init__(self, value): 60 | self.value = value 61 | 62 | def __str__(self): 63 | return self.value 64 | 65 | class RegBadEvidenceError(Exception): 66 | 67 | def __init__(self, value): 68 | self.value = value 69 | 70 | def __str__(self): 71 | return self.value 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /guicontroller.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | #handles communication between gui and processing code 26 | 27 | import os, stat, hashlib 28 | 29 | # evidence types 30 | UNKNOWN = 0 31 | DD = 1 32 | RDB = 2 33 | SINGLEFILE = 3 34 | 35 | # DO NOT CHANGE THIS OR THE HASH TABLE 36 | # registry types 37 | SOFTWARE = 1 38 | SYSTEM = 2 39 | SECURITY = 3 40 | NTUSER = 4 41 | SAM = 5 42 | USRCLASS = 6 43 | 44 | registry_types = {SOFTWARE: "SOFTWARE", SYSTEM: "SYSTEM", SECURITY:"SECURITY", NTUSER:"NTUSER", SAM:"SAM", USRCLASS:"USRCLASS"} 45 | 46 | 47 | class guihandler: 48 | 49 | def __init__(self): 50 | pass 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /initial_processing/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["acquire_files","evidence_database","registry_sig","tree_handler"] 26 | -------------------------------------------------------------------------------- /initial_processing/acquire_files.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from errorclasses import * 26 | 27 | from guicontroller import * 28 | import registry_sig 29 | import acquirefiles.acquire_files as aqfile 30 | import shutil, sys, re, os 31 | 32 | import pytsk3 33 | import ewf 34 | import traceback 35 | 36 | class acquire_files: 37 | 38 | def __init__(self): 39 | self.singlefilecounter = 0 40 | self.reg_sig = registry_sig.registry_sig() 41 | self.ac = None 42 | 43 | def add_single_file(self, evidence_file, evidence_type, gui_ref): 44 | 45 | # write the info.txt information 46 | directory = os.path.join(gui_ref.directory, "registryfiles", "singlefiles") 47 | try: 48 | os.makedirs(directory) 49 | except: 50 | pass 51 | 52 | filename = os.path.join(directory,"info.txt") 53 | fd = open(filename,"a",0750) 54 | 55 | mtime = int(os.path.getmtime(filename)) 56 | 57 | fd.write("%s\t%d\t%d\n" % (evidence_file, mtime, self.singlefilecounter)) 58 | 59 | fd.close() 60 | 61 | # copy the evidence file into the case directory 62 | # copy2 copies mac time as well as the file 63 | filename = os.path.join(directory,"%d" % self.singlefilecounter) 64 | 65 | shutil.copy2(evidence_file,filename) 66 | 67 | self.singlefilecounter = self.singlefilecounter + 1 68 | 69 | def is_mbr(self, filepath): 70 | 71 | ret = False 72 | 73 | fd = open(filepath, "rb") 74 | 75 | fd.seek(446, 0) 76 | 77 | status = fd.read(1) 78 | 79 | if len(status) == 1 and ord(status) in [0x00, 0x80]: 80 | 81 | fd.seek(510, 0) 82 | 83 | sig = fd.read(2) 84 | 85 | if ord(sig[0]) == 0x55 and ord(sig[1]) == 0xAA: 86 | ret = True 87 | 88 | return ret 89 | 90 | def is_partition_image(self, evidence_file): 91 | 92 | isimage = 1 93 | 94 | try: 95 | img = pytsk3.Img_Info(evidence_file) 96 | pytsk3.FS_Info(img) 97 | except: 98 | isimage = 0 99 | #print "Not a disk image: ", sys.exc_info()[:2] 100 | 101 | return isimage 102 | 103 | # checks if given file is a partition image 104 | def is_disk_image(self, evidence_file): 105 | 106 | return self.is_mbr(evidence_file) or self.is_partition_image(evidence_file) 107 | 108 | # tries to determine the file type of 'evidence_file' based on 109 | # extension 110 | def determine_type_ext(self, evidence_file): 111 | 112 | extension = os.path.splitext(evidence_file)[-1].lower() 113 | 114 | if extension in (".img",".dd",".raw") or re.search('^(.e\d{1,})$', extension): 115 | etype = [DD] 116 | 117 | elif extension == ".db": 118 | etype = [RDB] 119 | 120 | elif self.is_disk_image(evidence_file): 121 | etype = [DD] 122 | 123 | else: 124 | etype = None 125 | 126 | return etype 127 | 128 | def determine_type_sig(self, evidence_file): 129 | 130 | fd = open(evidence_file,"rb") 131 | 132 | checkbuffer = fd.read(0x80) 133 | 134 | # check for a registry file 135 | ret = self.reg_sig.determine_type(checkbuffer) 136 | 137 | if not ret: 138 | ret = [UNKNOWN] 139 | 140 | return ret 141 | 142 | def continuebox(self, evidence_file, gui_ref): 143 | 144 | cont = gui_ref.gui.yesNoDialog("Unable to process %s" % evidence_file, "Would you like to skip this file?") 145 | 146 | if cont: 147 | return -1 148 | else: 149 | gui_ref.gui.msgBox("Unable to process evidence file %s. Exiting." % evidence_file) 150 | raise RegAcquireError(evidence_file) 151 | 152 | # this gathers the evidence from input files for second stange processing 153 | def acquire_from_file(self, evidence_file, gui_ref): 154 | 155 | evidence_type = self.determine_type_ext(evidence_file) 156 | 157 | if not evidence_type: 158 | evidence_type = self.determine_type_sig(evidence_file) 159 | 160 | if evidence_type[0] == UNKNOWN: 161 | 162 | evidence_type = self.continuebox(evidence_file, gui_ref) 163 | 164 | elif evidence_type[0] == DD: 165 | # pytsk3 166 | self.ac = aqfile.acquire_files(gui_ref.directory, gui_ref) 167 | 168 | # command line 169 | if not hasattr(gui_ref, "gui"): 170 | acq_current = gui_ref.acquire_current 171 | acq_backup = gui_ref.acquire_backups 172 | else: 173 | acq_current = gui_ref.gui.acquire_current 174 | acq_backup = gui_ref.gui.acquire_backups 175 | 176 | # this hits on a broken filesystem 177 | try: 178 | self.ac.acquire_files(evidence_file, acq_current, acq_backup) 179 | except Exception, e: 180 | print "BUG! when attempting to acquire files: %s" % str(e) 181 | traceback.print_exc(file=sys.stdout) 182 | evidence_type = self.continuebox(evidence_file, gui_ref) 183 | 184 | elif evidence_type[0] == SINGLEFILE: 185 | self.add_single_file(evidence_file, evidence_type[1], gui_ref) 186 | 187 | # keep a list of RDB files added 188 | elif evidence_type[0] == RDB: 189 | fd = open(os.path.join(gui_ref.directory, "registryfiles", "rdb-files.txt"), "a+") 190 | fd.write(evidence_file + "\n") 191 | fd.close() 192 | 193 | return evidence_type 194 | 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /initial_processing/registry_sig.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import sys 26 | 27 | from guicontroller import * 28 | 29 | class registry_sig: 30 | 31 | 32 | def __init__(self): 33 | pass 34 | 35 | def determine_type(self, checkbuffer): 36 | 37 | lookfor = ["s\x00o\x00f\x00t\x00w\x00a\x00r\x00e\x00", "s\x00y\x00s\x00t\x00e\x00m\x00", "s\x00e\x00c\x00u\x00r\x00i\x00t\x00y\x00"] 38 | lookfor = lookfor + ["n\x00t\x00u\x00s\x00e\x00r\x00.\x00d\x00a\x00t", "s\x00a\x00m\x00", "u\x00s\x00r\x00c\x00l\x00a\x00s\x00s\x00.\x00d\x00a\x00t\x00"] 39 | lookfor = lookfor + ["U\x00s\x00r\x00C\x00l\x00a\x00s\x00s\x00.\x00d\x00a\x00t\x00"] 40 | 41 | default = "D\x00E\x00F\x00A\x00U\x00L\x00T" 42 | 43 | idx = 1 44 | 45 | for check in lookfor: 46 | 47 | if check in checkbuffer or check.upper() in checkbuffer: 48 | 49 | # UsrClass to usrclass 50 | if idx == 7: 51 | idx = 6 52 | 53 | return [SINGLEFILE, idx] 54 | 55 | idx = idx + 1 56 | 57 | # default is really an ntuser file 58 | if default in checkbuffer or default.upper() in checkbuffer: 59 | return [SINGLEFILE, 6] 60 | 61 | return None 62 | 63 | def determine_type_file(self, filename): 64 | 65 | return self.determine_type(open(filename,"rb").read(0x80)) 66 | 67 | def main(): 68 | 69 | r = registry_sig() 70 | 71 | res = r.determine_type_file(sys.argv[1]) 72 | 73 | if res: 74 | print res #registry_types[res[1]] 75 | else: 76 | print "no" 77 | 78 | 79 | 80 | if __name__ == "__main__": 81 | main() 82 | 83 | -------------------------------------------------------------------------------- /initial_processing/tree_handler.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import cPickle, os, sys, traceback 26 | import registryparser.regparser as regparse 27 | from errorclasses import * 28 | 29 | class tree_handling: 30 | 31 | def __init__(self): 32 | self.reg_parser = regparse.regparser() 33 | 34 | def add_file_to_tree(self, gui, existingfilepath, fileid, case_obj, filepath): 35 | 36 | # get the keys from the registry 37 | keylist = self.reg_parser.parse_file(existingfilepath) 38 | 39 | # had to try/expect whole function b/c 40 | # exception occurs in 'for' due to being generator 41 | try: 42 | self.add_elements(keylist, gui, fileid, case_obj) 43 | 44 | # regfi throws generic Exception 45 | except Exception, e: 46 | print "--error: %s" % str(e) 47 | traceback.print_exc(file=sys.stdout) 48 | cont = gui.yesNoDialog("Unable to process %s" % filepath, "Would you like to skip this file?") 49 | 50 | if cont: 51 | return False 52 | else: 53 | raise RegFiKeyError(filepath) 54 | 55 | return True 56 | 57 | def add_elements(self, keylist, gui, fileid, case_obj): 58 | 59 | ktree = case_obj.tree 60 | 61 | i = 0 62 | 63 | for element in keylist: 64 | 65 | isroot = not i 66 | 67 | ktree.add_path(fileid, element, isroot) 68 | 69 | i = i + 1 70 | 71 | if i % 5000 == 0: 72 | if not hasattr(gui,"progressLabel"): 73 | return 74 | 75 | gui.progressLabel.setText("Processed %d registry keys" % i) 76 | 77 | gui.update() 78 | gui.app.processEvents() 79 | gui.update() 80 | gui.app.processEvents() 81 | 82 | if i % 10000 == 0: 83 | 84 | case_obj.stringtable.commit_db() 85 | case_obj.vtable.conn.commit() 86 | 87 | case_obj.vtable.conn.commit() 88 | case_obj.stringtable.commit_db() 89 | 90 | -------------------------------------------------------------------------------- /opencase.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import sys, os, struct, cPickle, sqlite3, getopt 26 | 27 | from datastructures.tree.paralleltree import * 28 | 29 | class objclass: 30 | pass 31 | 32 | class fileinfo: 33 | 34 | def __init__(self, evidence_file, file_alias, part_num, group_name, type_name, registry_file, rpname=""): 35 | 36 | self.evidence_file = evidence_file 37 | self.file_alias = file_alias 38 | self.part_num = part_num 39 | self.group_name = group_name 40 | self.type_name = type_name 41 | self.registry_file = registry_file 42 | self.rpname = rpname 43 | 44 | class opencase: 45 | 46 | def __init__(self, case_dir): 47 | self.directory = case_dir 48 | self.opencaseobj() 49 | 50 | def open_db(self, database): 51 | 52 | ret = objclass() 53 | 54 | dbname = os.path.join(self.directory, database) 55 | 56 | ret.conn = sqlite3.connect(dbname) 57 | ret.cursor = ret.conn.cursor() 58 | 59 | return ret 60 | 61 | def opencaseobj(self): 62 | filename = os.path.join(self.directory,"caseobj.pickle") 63 | fd = open(filename,"rb") 64 | obj = cPickle.load(fd) 65 | 66 | obj.stringtable.db_connect(self.directory) 67 | obj.vtable.db_connect(self.directory) 68 | 69 | self.evidencedb = self.open_db("evidence_database.db") 70 | self.nddb = self.open_db("namedata.db") 71 | self.stringdb = self.open_db("stringtable.db") 72 | self.treenodedb = self.open_db("treenodes.db") 73 | self.caseinfodb = self.open_db("caseinfo.db") 74 | 75 | self.case_obj = obj 76 | 77 | self.vtable = obj.vtable 78 | self.tree = obj.tree 79 | self.tree.db = self.treenodedb 80 | 81 | obj.stringtable.precache_values() 82 | 83 | self.stringtable = obj.stringtable 84 | self.vtable = obj.vtable 85 | self.case_directory = self.directory 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /pyinstaller.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | projpath = os.path.dirname(os.path.abspath(SPEC)) 3 | 4 | def get_plugins(list): 5 | 6 | for item in list: 7 | if item[0].startswith('templates.template_files') and not (item[0] == 'templates.template_files' and '__init__.py' in item[1]): 8 | yield item 9 | elif item[0].startswith('reporting.report_formats') and not (item[0] == 'reporting.report_formats' and '__init__.py' in item[1]): 10 | yield item 11 | 12 | exeext = ".exe" if 'win' in sys.platform else "" 13 | 14 | a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(CONFIGDIR,'support\\useUnicode.py'), os.path.join(projpath, 'guimain.py')], 15 | pathex = [HOMEPATH], 16 | hookspath = [os.path.join(projpath, 'pyinstaller')]) 17 | 18 | pyz = PYZ(a.pure - set(get_plugins(a.pure)), name = os.path.join(BUILDPATH, 'regdecoder.pkz')) 19 | 20 | plugins = Tree(os.path.join(projpath, 'reporting', 'report_formats'), 'reportingg') 21 | plugins = plugins + Tree(os.path.join(projpath, 'templates', 'template_files'), 'templatess') 22 | 23 | exe = EXE(pyz, 24 | a.scripts, 25 | a.binaries + [('libewf.dll', 'C:\\libewf.dll', 'BINARY')] + [('zlib1.dll', 'C:\\zlib1.dll', 'BINARY')], 26 | a.zipfiles, 27 | a.datas, 28 | plugins, 29 | name = os.path.join(projpath, 'dist', 'pyinstaller', 'regdecoder' + exeext), 30 | debug = 0, 31 | strip = False, 32 | upx = False, 33 | icon = "", 34 | console = 1) 35 | 36 | -------------------------------------------------------------------------------- /pyinstaller/hook-regdecoder.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os, sys 26 | 27 | 28 | def collect_modules(path): 29 | 30 | projpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 31 | 32 | modules = set([fullmod]) 33 | 34 | (one, two) = fullmod.split(".") 35 | 36 | for dirpath, _dirnames, filenames in os.walk(os.path.join(projpath, one, two)): 37 | dirpath = dirpath[len(os.path.join(projpath, one, two)):] 38 | if dirpath and dirpath[0] == os.path.sep: 39 | dirpath = dirpath[1:] 40 | for filename in filenames: 41 | path = os.path.join(dirpath, os.path.splitext(filename)[0]) 42 | if "/." in path: 43 | continue 44 | # why? 45 | if "__" in path: 46 | continue 47 | 48 | path = path.replace("-", "_") 49 | path = path.replace(os.path.sep, ".") 50 | 51 | modules.add(fullmod + "." + path) 52 | 53 | hiddenimports = list(modules) 54 | 55 | return hiddenimports 56 | 57 | 58 | hi = collect_modules("reporting.report_formats") 59 | 60 | hi = hi + collect_modules("templates.template_files") 61 | 62 | hiddenimports = list(hi) 63 | 64 | 65 | -------------------------------------------------------------------------------- /pyinstaller/hook-reporting.report_manager.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os 26 | import sys 27 | 28 | def collect_rd_modules(fullmod): 29 | 30 | projpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 31 | 32 | modules = set([fullmod]) 33 | 34 | (one, two) = fullmod.split(".") 35 | 36 | for dirpath, _dirnames, filenames in os.walk(os.path.join(projpath, one, two)): 37 | dirpath = dirpath[len(os.path.join(projpath, one, two)):] 38 | if dirpath and dirpath[0] == os.path.sep: 39 | dirpath = dirpath[1:] 40 | for filename in filenames: 41 | path = os.path.join(dirpath, os.path.splitext(filename)[0]) 42 | if "/." in path or "__" in path or ".svn" in path: 43 | continue 44 | 45 | path = path.replace("-", "_") 46 | path = path.replace(os.path.sep, ".") 47 | 48 | modules.add(fullmod + "." + path) 49 | 50 | hi = list(modules) 51 | 52 | return hi 53 | 54 | 55 | hi = collect_rd_modules("reporting.report_formats") 56 | 57 | hiddenimports = list(hi) 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /pyinstaller/hook-templates.template_manager.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os, sys 26 | 27 | 28 | def collect_rd_modules(fullmod): 29 | 30 | projpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 31 | 32 | modules = set([fullmod]) 33 | 34 | (one, two) = fullmod.split(".") 35 | 36 | for dirpath, _dirnames, filenames in os.walk(os.path.join(projpath, one, two)): 37 | dirpath = dirpath[len(os.path.join(projpath, one, two)):] 38 | if dirpath and dirpath[0] == os.path.sep: 39 | dirpath = dirpath[1:] 40 | for filename in filenames: 41 | path = os.path.join(dirpath, os.path.splitext(filename)[0]) 42 | if "/." in path or "__" in path or ".svn" in path: 43 | continue 44 | 45 | path = path.replace("-", "_") 46 | path = path.replace(os.path.sep, ".") 47 | 48 | modules.add(fullmod + "." + path) 49 | 50 | hi = list(modules) 51 | 52 | return hi 53 | 54 | hi = collect_rd_modules("templates.template_files") 55 | 56 | hiddenimports = list(hi) 57 | 58 | 59 | -------------------------------------------------------------------------------- /registryparser/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["regfile_common" , "regfile" , "reghivebin" , "regkey" , "reglinkage" , "regvalue" , "regparser"] 26 | -------------------------------------------------------------------------------- /registryparser/harness.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | 26 | # regfile test harness 27 | 28 | 29 | import os, sys 30 | import regfile 31 | import cPickle 32 | import getopt 33 | 34 | 35 | def print_keys(keylist): 36 | 37 | for element in keylist: 38 | print element.path + " TYPE " + str(type(element.path)) 39 | for e in element.value_list: 40 | print "\tname: %s\t\ttype: %s\tvalue: %s" % (e.name, e.type_of_data, e.value) 41 | 42 | return 43 | 44 | 45 | 46 | def usage(): 47 | print "python harness.py -i | -r" 48 | print "\t-i: input new registry file for parsing" 49 | print "\t-r reload previously parsed registry file" 50 | 51 | def main(): 52 | 53 | diskfile = "pickle.dat" 54 | 55 | if len(sys.argv) < 2: 56 | sys.stderr.write("Too few arguments.\n") 57 | usage() 58 | exit(1) 59 | 60 | try: 61 | opts, args = getopt.getopt(sys.argv[1:], "i:r", ["input", "restore"]) 62 | except getopt.GetoptError, err: 63 | sys.stderr.write(str(err)+"\n") 64 | usage() 65 | sys.exit(1) 66 | 67 | for o, a in opts: 68 | if o in ("-i", "--input"): 69 | mode = 'INPUT' 70 | bytes = open(a, 'rb').read() 71 | elif o in ("-r", "--reload"): 72 | mode = 'RELOAD' 73 | else: 74 | assert False, "unhandled option" 75 | 76 | if mode == 'INPUT': 77 | 78 | rf = regfile.RegFile(bytes) 79 | # get a generator for keys 80 | keylist = [] 81 | keygen = rf.get_keygen() 82 | # rf.parse_file(keylist) 83 | outfile = open(diskfile, "wb") 84 | 85 | # iterate through and add to list for pickling 86 | for element in keygen: 87 | keylist.append(element) 88 | 89 | sys.stderr.write("list built\n") 90 | cPickle.dump(keylist, outfile, 2) 91 | sys.stderr.write("list dumped\n") 92 | outfile.close() 93 | print_keys(keylist) 94 | 95 | elif mode == 'RELOAD': 96 | infile = open(diskfile, "rb") 97 | keylist = cPickle.load(infile) 98 | sys.stderr.write("list loaded\n") 99 | print_keys(keylist) 100 | 101 | else: 102 | sys.stderr.write("mode error: mode == %s\n" % (str(mode))) 103 | usage() 104 | exit(1) 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /registryparser/regfile.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | 26 | import regkey 27 | import regvalue 28 | import pyregfi 29 | 30 | 31 | class RegFile: 32 | 33 | ''' 34 | DOCME 35 | ''' 36 | 37 | def __init__(self, regfile): 38 | self.regfile = regfile 39 | 40 | def get_keygen(self): 41 | 42 | reghive = pyregfi.openHive(self.regfile) 43 | regiter = pyregfi.HiveIterator(reghive) 44 | 45 | for key in regiter: 46 | path_list = [] 47 | for val in regiter.current_path(): 48 | path_list.append(val) 49 | value_list = [] 50 | for val in key.values: 51 | 52 | data = val.fetch_data() 53 | 54 | if not data: 55 | data = val.fetch_raw_data() 56 | 57 | v = regvalue.Value(val.name, val.type, data) 58 | value_list.append(v) 59 | yield regkey.RegKeyNK(path_list, value_list, key.modified) 60 | 61 | 62 | # for now, give me a registry file and I will try to parse some stuff out 63 | def main(): 64 | 65 | if len(sys.argv) != 2: 66 | usage() 67 | sys.exit() 68 | 69 | regfile = RegFile(sys.argv[1]) 70 | 71 | generator = regfile.get_keygen() 72 | for key in generator: 73 | print key 74 | 75 | 76 | if __name__ == "__main__": 77 | main() 78 | 79 | -------------------------------------------------------------------------------- /registryparser/regkey.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | ''' 26 | regfile 1.0 27 | 2010 28 | Lodovico Marziale 29 | ''' 30 | 31 | 32 | # Base classs for some registry structures. BUG: probably shouldn't be here. 33 | class RegStructure: 34 | 35 | ''' 36 | Parent class of all internal registry structures. 37 | ''' 38 | 39 | def __init__(self): 40 | self.children = [] 41 | self.sig = "" 42 | 43 | def has_children(self): 44 | return (len(self.children) > 0) 45 | 46 | def get_children(self): 47 | return self.children 48 | 49 | def num_children(self): 50 | return len(self.children) 51 | 52 | def key_type(self): 53 | return self.sig 54 | 55 | 56 | 57 | class RegKeyNK(RegStructure): 58 | 59 | ''' 60 | The registry structure representing an actual registry key. 61 | ''' 62 | 63 | def __init__(self, path_list, value_list, timestamp): 64 | 65 | RegStructure.__init__(self) 66 | 67 | self.path = path_list 68 | self.value_list = value_list 69 | self.timestamp = timestamp 70 | 71 | 72 | 73 | if __name__ == "__main__": 74 | main() 75 | -------------------------------------------------------------------------------- /registryparser/regparser.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os, sys 26 | import regfile 27 | import cPickle 28 | 29 | 30 | class regparser: 31 | 32 | def __init__(self): 33 | pass 34 | 35 | def parse_file(self, registryfile): 36 | 37 | rf = regfile.RegFile(registryfile) 38 | 39 | keygen = rf.get_keygen() 40 | 41 | return keygen 42 | 43 | -------------------------------------------------------------------------------- /registryparser/regvalue.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | ''' 26 | regfile 1.0 27 | 2010 28 | Lodovico Marziale 29 | ''' 30 | 31 | 32 | class Value(): 33 | 34 | 35 | def __init__(self, name, type_of_data, data): 36 | 37 | self.name = name 38 | if not self.name: 39 | self.name = "NONE" 40 | self.type_of_data = type_of_data 41 | self.data = data 42 | 43 | 44 | def main(): 45 | pass 46 | 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /reporting/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["report_formats"] 26 | -------------------------------------------------------------------------------- /reporting/report_formats/commasep.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # creates HTML formatted output 26 | 27 | import codecs 28 | 29 | def get_instance(): 30 | 31 | return csvReport() 32 | 33 | class csvReport: 34 | 35 | def __init__(self): 36 | self.name = "CSV" 37 | self.extension = "csv" 38 | self.fileoutput = 1 39 | 40 | def set_file(self, filename): 41 | 42 | self.fd = codecs.open(filename, "a+", encoding="UTF-8") 43 | 44 | def set_table_size(self, rowmax, colmax): 45 | pass 46 | 47 | def start_output(self): 48 | pass 49 | 50 | def start_table(self): 51 | pass 52 | 53 | def start_column(self): 54 | pass 55 | 56 | def end_column(self): 57 | pass 58 | 59 | def write_number_column(self): 60 | pass 61 | 62 | def write_table_headers(self, header_list): 63 | pass 64 | 65 | def write_data_list(self, data_list, print_row, bold=-1): 66 | 67 | row = 1 68 | 69 | # don't write out case info & headers 70 | if print_row == 0: 71 | return 72 | 73 | for outer_list in data_list: 74 | 75 | if print_row: 76 | self.fd.write("%d," % row) 77 | 78 | vidx = 0 79 | 80 | # actual report items 81 | for val in outer_list: 82 | 83 | if not val or val == "": 84 | val = "" 85 | 86 | val = val.replace(",", "") 87 | 88 | self.fd.write("%s," % val) 89 | 90 | vidx = vidx + 1 91 | 92 | self.fd.write("\n") 93 | 94 | row = row + 1 95 | 96 | def end_table(self): 97 | pass 98 | 99 | def end_output(self): 100 | pass 101 | 102 | def close_report(self): 103 | self.fd.close() 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /reporting/report_formats/html.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # creates HTML formatted output 26 | 27 | import codecs 28 | 29 | def get_instance(): 30 | 31 | return htmlReport() 32 | 33 | class htmlReport: 34 | 35 | def __init__(self): 36 | self.name = "HTML" 37 | self.extension = "html" 38 | self.fileoutput = 1 39 | 40 | def set_file(self, filename): 41 | 42 | self.fd = codecs.open(filename, "a+", encoding="UTF-8") 43 | 44 | def set_table_size(self, rowmax, colmax): 45 | pass 46 | 47 | def start_output(self): 48 | self.fd.write("Registry Decoder Report") 49 | 50 | def start_table(self): 51 | self.fd.write("") 52 | 53 | def start_column(self): 54 | self.fd.write("") 55 | 56 | def end_column(self): 57 | self.fd.write("") 58 | 59 | def write_number_column(self): 60 | self.fd.write("") 61 | 62 | def write_table_headers(self, header_list): 63 | 64 | for header in header_list: 65 | self.fd.write("" % header) 66 | 67 | def write_data_list(self, data_list, print_row, bold=-1): 68 | 69 | row = 1 70 | 71 | for outer_list in data_list: 72 | 73 | self.fd.write("") 74 | 75 | if print_row: 76 | self.fd.write("" % row) 77 | 78 | vidx = 0 79 | 80 | # actual report items 81 | for val in outer_list: 82 | 83 | if not val or val == "": 84 | val = " " 85 | 86 | if vidx == bold: 87 | val = "" + val + "" 88 | 89 | self.fd.write("" % val) 90 | 91 | vidx = vidx + 1 92 | 93 | self.fd.write("") 94 | 95 | row = row + 1 96 | 97 | def end_table(self): 98 | self.fd.write("
Number%s
%d%s



") 99 | 100 | def end_output(self): 101 | self.fd.write("") 102 | 103 | def close_report(self): 104 | self.fd.close() 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /reporting/report_formats/pdf.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from reportlab.lib import colors 26 | from reportlab.lib.pagesizes import letter, inch 27 | from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph 28 | from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 29 | 30 | def get_instance(): 31 | 32 | return pdfReport() 33 | 34 | class pdfReport: 35 | 36 | def __init__(self): 37 | 38 | self.name = "PDF" 39 | self.extension = "pdf" 40 | self.fileoutput = 1 41 | 42 | self.tables = [] 43 | 44 | def set_file(self, filename): 45 | self.fd = SimpleDocTemplate(filename, pagesize=letter, title="Registry Decoder Report", author="Registry Decoder") 46 | 47 | def set_table_size(self, rowmax, colmax): 48 | self.rmax = rowmax 49 | self.cmax = colmax 50 | 51 | def start_output(self): 52 | pass 53 | 54 | def start_table(self): 55 | self.cur_col = -1 56 | self.report_data = {} 57 | 58 | def start_column(self): 59 | self.report_data[self.cur_col] = [] 60 | 61 | def end_column(self): 62 | self.cur_col = self.cur_col + 1 63 | 64 | def write_number_column(self): 65 | self.report_data[self.cur_col].append("Number") 66 | 67 | def write_table_headers(self, header_list): 68 | 69 | for header in header_list: 70 | self.report_data[self.cur_col].append("%s" % header) 71 | 72 | def write_data_list(self, data_list, print_row, bold=-1): 73 | 74 | row = 1 75 | 76 | self.end_column() 77 | 78 | style = getSampleStyleSheet()['Normal'] 79 | style.wordWrap = 'LTR' 80 | 81 | #if not self.cur_col in self.report_data: 82 | # self.report_data[self.cur_col] = [] 83 | 84 | for outer_list in data_list: 85 | 86 | self.start_column() 87 | 88 | if print_row: 89 | self.report_data[self.cur_col].append("%d" % row) 90 | 91 | vidx = 0 92 | 93 | # actual report items 94 | for val in outer_list: 95 | 96 | if not val: 97 | val = "" 98 | 99 | val = "".join(val[i:i+40] + "\n" for i in xrange(0,len(val),40)) 100 | 101 | #val = Paragraph(val, style) 102 | 103 | #if not val or val == "": 104 | # val = " " 105 | # 106 | #if vidx == bold: 107 | # val = "" + val + "" 108 | 109 | self.report_data[self.cur_col].append(val) 110 | 111 | vidx = vidx + 1 112 | 113 | self.end_column() 114 | 115 | row = row + 1 116 | 117 | def end_table(self): 118 | 119 | draw_data = [] 120 | 121 | for col in sorted(self.report_data.keys()): 122 | draw_data.append([]) 123 | 124 | for row in self.report_data[col]: 125 | draw_data[col].append(row) 126 | 127 | #print "drawing:\n%s\n\n" % str(draw_data) 128 | #print "%d | %d" % self.cmax 129 | 130 | t = Table(draw_data) 131 | t.hAlign = 'LEFT' 132 | t.setStyle(TableStyle([('BOX', (0,0), (-1,-1), 0.25, colors.black), ('GRID',(0,0),(-1,-1),0.5,colors.black)])) 133 | self.tables.append(t) 134 | 135 | def end_output(self): 136 | pass 137 | 138 | def close_report(self): 139 | self.fd.build(self.tables) 140 | self.fd = None 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /reporting/report_formats/screen_display.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from PyQt4.QtCore import * 26 | from PyQt4.QtGui import * 27 | from PyQt4.QtNetwork import * 28 | 29 | name = "Default Screen Display" 30 | fileoutput = 0 31 | 32 | def get_instance(): 33 | 34 | return screenDisplay() 35 | 36 | class screenDisplay: 37 | 38 | def __init__(self): 39 | self.name = name 40 | self.fileoutput = fileoutput 41 | 42 | 43 | def report_data(self, tableWidget, header_list, data_list, match_idxs, rowmax, colmax, color_idxs): 44 | 45 | tableWidget.setRowCount(rowmax) 46 | tableWidget.setColumnCount(colmax) 47 | tableWidget.setHorizontalHeaderLabels(header_list) 48 | 49 | row = 0 50 | 51 | if color_idxs == []: 52 | colors = [Qt.black, Qt.black, Qt.black] 53 | idxctr = -1 54 | else: 55 | colors = [Qt.red, Qt.black, Qt.blue] 56 | idxctr = color_idxs[0] 57 | 58 | color_idx = 0 59 | color = colors[color_idx] 60 | 61 | # first list 62 | for outer_list in data_list: 63 | 64 | if color_idxs != [] and idxctr == 0: 65 | if color_idx < 2: 66 | color_idx = color_idx + 1 67 | 68 | idxctr = color_idxs[color_idx] 69 | 70 | if idxctr == 0: 71 | if color_idx < 2: 72 | color_idx = color_idx + 1 73 | 74 | idxctr = color_idxs[color_idx] 75 | 76 | color = colors[color_idx] 77 | 78 | col = 0 79 | 80 | if match_idxs and match_idxs != []: 81 | idx = match_idxs[row] 82 | else: 83 | idx = -1 84 | 85 | # actual report items 86 | for val in outer_list: 87 | 88 | item = QTableWidgetItem(QString(val)) 89 | 90 | if col == idx: 91 | font = item.font() 92 | font.setBold(True) 93 | item.setFont(font) 94 | 95 | fg = item.foreground() 96 | fg.setColor(color) 97 | item.setForeground(fg) 98 | 99 | tableWidget.setItem(row, col, item) 100 | 101 | col = col + 1 102 | 103 | row = row + 1 104 | 105 | idxctr = idxctr - 1 106 | 107 | 108 | tableWidget.resizeColumnsToContents() 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /reporting/report_formats/xls.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | from xlwt import Workbook 26 | 27 | def get_instance(): 28 | 29 | return xlsReport() 30 | 31 | class xlsReport: 32 | 33 | def __init__(self): 34 | 35 | self.name = "XLS" 36 | self.extension = "xls" 37 | self.fileoutput = 1 38 | 39 | self.wb = None 40 | self.cur_sheet = 1 41 | 42 | # this is set to avoid information about term etc 43 | self.no_case_info = 1 44 | 45 | def set_file(self, filename): 46 | self.filename = filename 47 | 48 | if not self.wb: 49 | self.wb = Workbook() 50 | 51 | self.sheet = self.wb.add_sheet("Registry Decoder Report Sheet %d" % self.cur_sheet) 52 | self.cur_sheet = self.cur_sheet + 1 53 | 54 | def set_table_size(self, rowmax, colmax): 55 | self.rmax = rowmax 56 | self.cmax = colmax 57 | 58 | def start_output(self): 59 | pass 60 | 61 | def start_table(self): 62 | pass 63 | 64 | def start_column(self): 65 | pass 66 | 67 | def end_column(self): 68 | pass 69 | 70 | def write_number_column(self): 71 | pass 72 | 73 | # we don't support headers now (not sure whats the point??) 74 | def write_table_headers(self, header_list): 75 | pass 76 | 77 | def write_data_list(self, data_list, print_row, bold=-1): 78 | 79 | row = 0 80 | 81 | self.end_column() 82 | 83 | for outer_list in data_list: 84 | 85 | self.start_column() 86 | 87 | # we dont number the rows since excel does that for you... 88 | 89 | col = 0 90 | 91 | # actual report items 92 | for val in outer_list: 93 | 94 | if not val: 95 | val = "" 96 | 97 | self.sheet.write(row, col, unicode(val)) 98 | 99 | col = col + 1 100 | 101 | self.end_column() 102 | 103 | row = row + 1 104 | 105 | def end_table(self): 106 | pass 107 | 108 | def end_output(self): 109 | pass 110 | 111 | # save the file and then reset our variable 112 | def close_report(self): 113 | self.wb.save(self.filename) 114 | self.wb = None 115 | self.cur_sheet = 1 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /start_processing.py: -------------------------------------------------------------------------------- 1 | # Registry Decoder 2 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 3 | # 4 | # Contact email: registrydecoder@digitalforensicssolutions.com 5 | # 6 | # Authors: 7 | # Andrew Case - andrew@digitalforensicssolutions.com 8 | # Lodovico Marziale - vico@digitalforensicssolutions.com 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2 of the License, or (at 13 | # your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, but 16 | # WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | # General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program; if not, write to the Free Software 22 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | # 24 | #!/usr/bin/python 25 | 26 | import sys,os,cPickle,time,struct,sqlite3 27 | 28 | import initial_processing.acquire_files as acquire_reg_files 29 | import initial_processing.evidence_database as evidence_database 30 | 31 | from PyQt4.QtCore import * 32 | from PyQt4.QtGui import * 33 | 34 | from datastructures.values.valuestable import * 35 | from datastructures.tree.paralleltree import * 36 | from datastructures.strings.stringtable import * 37 | from guicontroller import * 38 | from errorclasses import * 39 | 40 | import common, opencase 41 | 42 | # whether to profile the run through command line 43 | profile = 0 44 | 45 | class objclass: 46 | pass 47 | 48 | class case_processing: 49 | 50 | def __init__(self): 51 | self.acquire_files = acquire_reg_files.acquire_files() 52 | self.evidence_db = evidence_database.evidence_database() 53 | 54 | def create_tree_databases(self, case_directory): 55 | 56 | databases = ["namedata", "treenodes"] 57 | i = 0 58 | 59 | for database in databases: 60 | dbname = os.path.join(case_directory, database + ".db") 61 | conn = sqlite3.connect(dbname) 62 | cursor = conn.cursor() 63 | 64 | cursor.execute("PRAGMA default_cache_size=20000") 65 | cursor.execute("PRAGMA synchronous=OFF") 66 | cursor.execute("PRAGMA count_changes=OFF") 67 | cursor.execute("PRAGMA journal_mode=MEMORY") 68 | cursor.execute("PRAGMA temp_store=2") 69 | 70 | if i == 0: 71 | try: 72 | cursor.execute("create table keyvalues (namesid int, fileid int, rawsid int , asciisid int, regtype text, id integer primary key asc)") 73 | cursor.execute("create index keyvalindex on keyvalues (nodeid,fileid)") 74 | except: 75 | pass 76 | elif i == 1: 77 | try: 78 | cursor.execute("create table treenodes (nodeid int unique, parentid int, stringid int, id integer primary key asc)") 79 | cursor.execute("create index treeindex on treenodes (nodeid, parentid, stringid)") 80 | except: 81 | pass 82 | i = i + 1 83 | 84 | conn.commit() 85 | 86 | def insert_tree_nodes(self, case_obj): 87 | 88 | pid_cache = {} 89 | 90 | conn = sqlite3.connect(os.path.join(case_obj.case_directory,"treenodes.db")) 91 | cursor = conn.cursor() 92 | 93 | for key in case_obj.tree.past_queries: 94 | 95 | (pid, sid) = [int(x) for x in key.split("|")] 96 | node = case_obj.tree.past_queries[key] 97 | nodeid = node.nodeid 98 | 99 | if not pid in pid_cache: 100 | pid_cache[pid] = [] 101 | 102 | pid_cache[pid].append(nodeid) 103 | 104 | try: 105 | cursor.execute("insert into treenodes (nodeid, parentid, stringid) values(?,?,?)", (nodeid, pid, sid)) 106 | except sqlite3.IntegrityError: 107 | pass 108 | 109 | conn.commit() 110 | 111 | case_obj.tree.pid_cache = pid_cache 112 | 113 | # refill past_queries from previous values 114 | def reinit_trees(self, obj): 115 | 116 | conn = sqlite3.connect(os.path.join(obj.case_directory, "treenodes.db")) 117 | cursor = conn.cursor() 118 | 119 | cursor.execute("select nodeid, parentid, stringid from treenodes") 120 | 121 | for (nid, pid, sid) in cursor.fetchall(): 122 | 123 | key = "%d|%d" % (pid, sid) 124 | obj.tree.past_queries[key] = obj.tree.idxtonode(nid) 125 | 126 | def reinit_vals(self, obj): 127 | 128 | conn = sqlite3.connect(os.path.join(obj.case_directory, "namedata.db")) 129 | cursor = conn.cursor() 130 | 131 | cursor.execute("select namesid, rawsid, asciisid, regtype, id from keyvalues") 132 | 133 | for (nid, rid, aid, regtype, vid) in cursor.fetchall(): 134 | 135 | key = "%d|%d|%d|%s" % (nid, aid, rid, regtype) 136 | 137 | obj.vtable.vals_hash[key] = vid 138 | 139 | def reinit_htables(self, obj): 140 | 141 | self.reinit_trees(obj) 142 | self.reinit_vals(obj) 143 | 144 | def create_tree(self, obj, case_directory): 145 | 146 | self.create_tree_databases(case_directory) 147 | 148 | return ptree(obj) 149 | 150 | def setup_case_obj(self, case_directory): 151 | 152 | case_obj = objclass() 153 | 154 | case_obj.case_directory = case_directory 155 | 156 | case_obj.stringtable = stringtbl(case_directory) 157 | case_obj.vtable = valuesholder(case_obj) 158 | case_obj.tree = self.create_tree(case_obj, case_directory) 159 | 160 | return case_obj 161 | 162 | def perform_processing(self, gui_ref): 163 | 164 | self.evidence_db.update_label(gui_ref, "Starting Processing") 165 | 166 | if gui_ref.gui.add_evidence: 167 | case_obj = opencase.opencase(gui_ref.directory) 168 | self.reinit_htables(case_obj) 169 | else: 170 | case_obj = self.setup_case_obj(gui_ref.directory) 171 | 172 | ehash = {} 173 | 174 | numfiles = len(gui_ref.evidence_list) 175 | 176 | i = 0 177 | skip_indexes = [] 178 | # grab each peice of evidence given and process it based on type 179 | for evidence_file in gui_ref.evidence_list: 180 | 181 | self.evidence_db.update_label(gui_ref, "Processing File %d of %d" % (i+1, numfiles)) 182 | 183 | # grab all the registry files from each file or the registry file itself 184 | etype = self.acquire_files.acquire_from_file(evidence_file, gui_ref) 185 | 186 | # user chose to skip the file 187 | if etype == -1: 188 | skip_indexes.append(i) 189 | 190 | # user chose not to skip file, need to force re-adding of evidence 191 | elif etype == -2: 192 | raise RegBadEvidenceError(evidence_file) 193 | 194 | else: 195 | etype = etype[0] 196 | ehash[evidence_file] = etype 197 | 198 | i = i + 1 199 | 200 | if self.acquire_files.ac: 201 | ac = self.acquire_files.ac 202 | ac.cursor.close() 203 | ac.cursor = None 204 | ac.conn = None 205 | 206 | # remove files that could not be processed 207 | gui_ref.evidence_list = [item for idx,item in enumerate(gui_ref.evidence_list) if idx not in skip_indexes] 208 | 209 | # check if any valid files were added 210 | if len(gui_ref.evidence_list) == 0: 211 | gui_ref.gui.msgBox("No valid files were added as evidence. Cannot Proceed.") 212 | raise RegBadEvidenceError("No valid files") 213 | 214 | # write out evidence information to evidence_database.db 215 | self.evidence_db.write_evidence_database(gui_ref, ehash, case_obj) 216 | 217 | self.evidence_db.update_label(gui_ref, "Saving Information") 218 | 219 | self.insert_tree_nodes(case_obj) 220 | 221 | # delete lists and such that aren't needed anymore 222 | case_obj.tree.before_pickle() 223 | 224 | self.evidence_db.update_label(gui_ref, "Final Processing") 225 | 226 | pickle_name = os.path.join(case_obj.case_directory,"caseobj.pickle") 227 | writefd = open(pickle_name,"wb") 228 | cPickle.dump(case_obj, writefd, 2) 229 | writefd.close() 230 | 231 | return True 232 | 233 | class blah: 234 | pass 235 | 236 | def print_stuff(self, obj): 237 | 238 | #print_vals(obj) 239 | 240 | #draw_graph(obj.ktree,obj) 241 | 242 | ret = obj.ktree.check_path_from_root(["Clients","Contacts","Address Book"],[-1]) 243 | 244 | def main(): 245 | 246 | import templates.util.util as tutilclass 247 | 248 | #image = sys.argv[1] 249 | 250 | g = blah() 251 | g.acquire_current = 1 252 | g.acquire_backups = 1 253 | g.directory = "/mnt/big/single/" 254 | #g.evidence_list = ["/media/ba42b2b8-ad4d-4ee2-b5de-0c8119467859/win7.dd"] 255 | #g.evidence_list = ["/mnt/big/XP.dd"] 256 | g.evidence_list = ["/home/x/SYSTEM"] 257 | 258 | case_processing().perform_processing(g) 259 | 260 | print "done!" 261 | 262 | if __name__ == "__main__": 263 | 264 | if profile: 265 | import cProfile 266 | cProfile.run('main()') 267 | else: 268 | main() 269 | 270 | 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /template_manager.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | import os, sys 26 | import templates 27 | import templates.util.util as tutil 28 | 29 | class TemplateManager: 30 | 31 | def __init__(self, template_directory="template_files"): 32 | 33 | self.template_directory = os.path.join("templates", template_directory) 34 | self.templates = [] 35 | sys.path.append(self.template_directory) 36 | 37 | self.timestamp = None 38 | 39 | self.reset_report() 40 | 41 | # return the template instance or None 42 | def find_template(self, template): 43 | 44 | ret = [t for t in self.templates if t.pluginname == template] 45 | 46 | if ret: 47 | ret = ret[0] 48 | 49 | return ret 50 | 51 | # Returns the list of all loaded templates. 52 | def get_loaded_templates(self): 53 | return self.templates 54 | 55 | # Returns the list of loaded templated which run on the specified hive 56 | # ("System", "Software" ...) 57 | def get_hive_templates(self, hive): 58 | return [t for t in self.templates if hive in t.hives] 59 | 60 | def reset_report(self): 61 | self.report_data = [] 62 | self.error_set = 0 63 | self.plugin_set_header = 0 64 | 65 | # build a list of list of header/data value for reporting modules 66 | def set_report_header(self, header, psetheader=1): 67 | 68 | if psetheader == 1: 69 | self.plugin_set_header = 1 70 | 71 | if isinstance(header, str) or isinstance(header, unicode): 72 | header = [header] 73 | 74 | self.report_data.append(header) 75 | 76 | # how templates report their output, a list of lists to the caller 77 | def report(self, data): 78 | 79 | self.set_report_header(data, 0) 80 | 81 | def report_error(self, data): 82 | 83 | self.error_set = 1 84 | 85 | # if there is a header keep it 86 | if self.plugin_set_header == 1: 87 | self.report_data = [self.report_data[0], [data]] 88 | 89 | # if not indicate error 90 | else: 91 | self.report_data = [["Plugin Error"], [data]] 92 | 93 | def set_timestamp(self, timestamp): 94 | self.timestamp = timestamp 95 | 96 | def attach_template_methods(self, mod, case_obj): 97 | 98 | tree = case_obj.tree 99 | tapi = tutil.templateutil(case_obj) 100 | 101 | # lets templates call report directly 102 | tapi.report = self.report 103 | 104 | # lets templates set the global timestamp 105 | tapi.set_timestamp = self.set_timestamp 106 | 107 | # attach methods from templaute utils 108 | for attr in tutil.templateutil.__dict__: 109 | if attr[0:2] != "__": 110 | method_addr = getattr(tapi, attr) 111 | setattr(mod, attr, method_addr) 112 | 113 | def attach_string_methods(self, mod, case_obj): 114 | 115 | setattr(mod, "get_key_string", case_obj.tree.stringtable.nodetostr) 116 | setattr(mod, "get_value_string", case_obj.vtable.get_value_string) 117 | setattr(mod, "get_name_string", case_obj.vtable.get_name_string) 118 | 119 | def attach_report_methods(self, mod, case_obj): 120 | 121 | setattr(mod, "report", self.report) 122 | setattr(mod, "report_error", self.report_error) 123 | setattr(mod, "reg_set_report_header", self.set_report_header) 124 | 125 | def attach_methods(self, mod, case_obj): 126 | 127 | self.attach_template_methods(mod, case_obj) 128 | self.attach_string_methods(mod, case_obj) 129 | self.attach_report_methods(mod, case_obj) 130 | 131 | # Walk the template directory and parse each file into a Template. 132 | def load_templates(self, case_obj, extra_dirs): 133 | 134 | self.templates = [] 135 | 136 | if '_MEIPASS2' in os.environ: 137 | self.template_directory = os.path.join(os.environ['_MEIPASS2'], "templatess") 138 | sys.path.append(self.template_directory) 139 | 140 | self.import_templates(case_obj, self.template_directory) 141 | 142 | for directory in extra_dirs: 143 | 144 | sys.path.append(directory) 145 | self.import_templates(case_obj, directory) 146 | 147 | def import_templates(self, case_obj, directory): 148 | 149 | required_attrs = ["pluginname", "description", "run_me"] 150 | 151 | for root, dirs, files in os.walk(directory): 152 | for fd in files: 153 | 154 | if fd.endswith(".py") or fd.endswith(".PY"): 155 | # these are python api templates which we need to load 156 | # modules must define everything in required_attrs 157 | 158 | # get module name from filename 159 | modname = fd.rsplit(".")[0] 160 | 161 | mod = __import__(modname) 162 | 163 | valid = 1 164 | # verify it meets requirements 165 | for attr in required_attrs: 166 | if not hasattr(mod, attr): 167 | valid = 0 168 | 169 | if valid: 170 | 171 | # allows plugins to work on multiple hive types 172 | if hasattr(mod, "hive"): 173 | setattr(mod, "hives", [mod.hive]) 174 | delattr(mod, "hive") 175 | 176 | self.attach_methods(mod, case_obj) 177 | self.templates.append(mod) 178 | 179 | # see opencase.py -> main() 180 | # on how to use/run/load templates 181 | 182 | 183 | -------------------------------------------------------------------------------- /templates/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["util"] 26 | -------------------------------------------------------------------------------- /templates/template_files/BHO.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # Kevin Moore - CERT - kevinm@cert.org 28 | 29 | import struct 30 | 31 | pluginname = "Browser Helper Objects" 32 | description = "" 33 | hive = "SOFTWARE" 34 | documentation = "" 35 | 36 | def run_me(): 37 | 38 | class BHO: 39 | 40 | # Class detailing information about Browser Helper Object values 41 | 42 | def __init__(self): 43 | 44 | self.ID = "" # Class ID value in form {00000000-0000-0000-0000-000000000000} 45 | self.path = "" # Full Path to Browser Helper Object key value 46 | self.value = "" # Will be path of BHO payload (exe, dll, activex, etc) 47 | self.subvalue = "" # Will be name of BHO 48 | self.written = "" # Last Written Date of BHO Registry key 49 | 50 | def set_data(self, classID, reg_path, last_written): 51 | 52 | # Sets BHO class data 53 | 54 | self.ID = classID 55 | self.path = reg_path 56 | self.written = last_written 57 | return self 58 | 59 | # ENDCLASS - BHO 60 | 61 | def parse_bho(regkey): 62 | 63 | # Identifies and populates Browser Helper Object data, returns BHO Class object 64 | 65 | bho = BHO() 66 | subval = '' 67 | 68 | key_name = reg_get_key_name(regkey) 69 | key_path = "\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects" 70 | key_path += "\%s" % key_name # ClassID 71 | 72 | skey = reg_get_required_key(key_path) 73 | bho.set_data(key_name, key_path, get_last_write_time(skey)) 74 | 75 | return bho 76 | 77 | # ENDFUNCTION - parse_bho 78 | 79 | def parse_bho_class_ids(bhos): 80 | 81 | # Parses Data in \Classes\CLSID section of Software Hive for more detailed BHO information 82 | key_path = '\Classes\CLSID' 83 | class_key = reg_get_required_key(key_path) 84 | subkeys = reg_get_subkeys(class_key) 85 | 86 | keynames = {} 87 | 88 | for key in subkeys: 89 | 90 | keynames[reg_get_key_name(key)] = key 91 | 92 | for bho in bhos: 93 | 94 | key_path = '\Classes\CLSID' 95 | 96 | # Parses each key value under \Classes\CLSID to see if it matches the ClassID of a BHO identified 97 | if bho.ID in keynames: 98 | 99 | key_path += '\%s' % bho.ID 100 | regkey = reg_get_required_key(key_path) 101 | 102 | valstr = get_value_for_node_name(regkey, "NONE") 103 | 104 | if valstr: 105 | bho.subvalue = valstr 106 | 107 | new_subkeys = reg_get_subkeys(regkey) 108 | 109 | for sub in new_subkeys: 110 | 111 | # Parsing Subkeys under ClassID 112 | name = reg_get_key_name(sub) 113 | 114 | if name.find('InprocServer32') == 0: # Subvalue in InprocServer32 contains fullpath to BHO payload 115 | 116 | key_path += '\%s' % name 117 | regkey = reg_get_required_key(key_path) 118 | 119 | valstr = get_value_for_node_name(regkey, "NONE") 120 | 121 | if valstr: 122 | 123 | bho.value = valstr 124 | break 125 | 126 | #ENDFUNCTION - parse_bho_class_ids 127 | 128 | def print_report(bhos): 129 | 130 | # This function prints output of Browser Helper Objects Identified 131 | 132 | reg_set_report_header(('BHO Name', 'BHO Path', 'Last Written', 'Class ID', 'Registry Path')) 133 | 134 | for b in bhos: 135 | 136 | reg_report((b.subvalue, b.value, b.written, b.ID, b.path)) # Report Format: Friendly Name, Full Path to BHO file, Parent Last Written, Class ID of BHO and Reg Full Path 137 | 138 | # ENDFUNCTION print_report 139 | 140 | # ********************* # 141 | # Main processing Steps 142 | if path_exists(root_key() + "\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects"): # Determines if path exists in some software hives it does not 143 | 144 | bho_entries = [] 145 | regkey = reg_get_required_key("\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects") 146 | subkeys = reg_get_subkeys(regkey) 147 | 148 | for key in subkeys: 149 | 150 | new_bho = parse_bho(key) # Identifies Browser Helper Objects in standard registry location returns BHO class object 151 | bho_entries.append(new_bho) 152 | 153 | parse_bho_class_ids(bho_entries) # Identifies detailed Browser Helper Object info from ClassID in \Classes\CLSID section of Software Registry Hive 154 | 155 | print_report(bho_entries) # Prints report 156 | 157 | else: 158 | reg_report(('Path to Browser Helper Objects Not Found in Registry Hive')) 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /templates/template_files/acmru.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Last Access Disabled 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | 30 | pluginname = "ACMRU" 31 | description = "Displays user MRU files." 32 | hive = "NTUSER" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Software\Microsoft\Search Assistant\ACMru") 38 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 39 | 40 | for subkey in reg_get_subkeys(regkey): 41 | 42 | reg_report("") 43 | reg_report((reg_get_key_name(subkey), reg_get_lastwrite(subkey))) 44 | reg_report_values_name_data(subkey) 45 | 46 | 47 | -------------------------------------------------------------------------------- /templates/template_files/appinitdlls.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | 30 | pluginname = "App Init DLLs" 31 | description = "Displays DLLs which are loaded by each application that runs." 32 | hive = "SOFTWARE" 33 | documentation = "http://support.microsoft.com/kb/197571" 34 | 35 | 36 | def run_me(): 37 | 38 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion\Windows") 39 | 40 | for val in reg_get_values(regkey): 41 | if reg_get_value_name(val) == "AppInit_DLLs": 42 | report((reg_get_value_name(val), reg_get_value_data(val))) 43 | 44 | -------------------------------------------------------------------------------- /templates/template_files/apppaths.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Application Paths 26 | 27 | pluginname = "Application Paths" 28 | description = "Displays the exe files for each application listed in the Software\AppPaths" 29 | hive = "SOFTWARE" 30 | documentation = "" 31 | 32 | import sys 33 | 34 | def run_me(): 35 | 36 | reg_set_report_header(("Executable", "Path")) 37 | regkey = reg_get_required_key("\Microsoft\Windows\CurrentVersion\App Paths") 38 | 39 | subkeys = reg_get_subkeys(regkey) 40 | for key in subkeys: 41 | if reg_get_key_name(key).endswith(".exe"): 42 | path = "" 43 | for val in reg_get_values(key): 44 | 45 | if reg_get_value_name(val) == "NONE": 46 | path = reg_get_value_data(val) 47 | reg_report((reg_get_key_name(key), path)) 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /templates/template_files/computer_name.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Computer Name 26 | 27 | 28 | pluginname = "Computer Name" 29 | description = "" 30 | hive = "SYSTEM" 31 | 32 | 33 | def run_me(): 34 | 35 | ccs = reg_get_currentcontrolset() 36 | regkey = reg_get_required_key("\ControlSet00" + ccs + "\Control\ComputerName\ComputerName") 37 | reg_report_values_name_data(regkey) 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /templates/template_files/firewall_policy.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Windows Firewall Policy Settings 26 | # 27 | # Kevin Moore - CERT - kevinm@cert.org 28 | 29 | 30 | 31 | pluginname = "Windows Firewall Policy Settings" 32 | description = "Displays Windows Firewall Policy settings including authorized applications and ports" 33 | hive = "SYSTEM" 34 | 35 | 36 | def run_me(): 37 | 38 | from datetime import time 39 | import struct 40 | 41 | ccs = reg_get_currentcontrolset() # Identifies system's current control set for timezone settings retrieval 42 | reg_report(('Current ControlSet', '00' + ccs)) 43 | reg_report(("")) 44 | 45 | regkey = reg_get_required_key("\ControlSet00" + ccs + "\Services\SharedAccess\Parameters") # Retrieves key based on CurrentControlSe 46 | 47 | # Registry Keys containing information related to firewall policy settings 48 | keys = ( 49 | "\ControlSet00" + ccs + "\Services\SharedAccess", 50 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters", 51 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy", 52 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules", 53 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Configurable\System", 54 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile", 55 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile\AuthorizedApplications\List", 56 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Static\System", 57 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile", 58 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List", 59 | "\ControlSet00" + ccs + "\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\GloballyOpenPorts\List") 60 | 61 | # Retrieve values from keys above 62 | for k in keys: 63 | reg_key = reg_get_key(k) 64 | if reg_key: 65 | reg_report((k)) 66 | reg_report_values_name_data(reg_key) 67 | reg_report(("")) -------------------------------------------------------------------------------- /templates/template_files/ide_devs.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "IDE Devices" 30 | description = "Lists information on installed IDE devices." 31 | hive = "SYSTEM" 32 | documentation = "" 33 | 34 | def run_me(): 35 | 36 | regkey = reg_get_required_key("\ControlSet00"+get_current_control_set()+"\Enum\IDE") 37 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 38 | 39 | for rkey in reg_get_subkeys(regkey): 40 | for key in reg_get_subkeys(rkey): 41 | for val in reg_get_values(key): 42 | name = reg_get_value_name(val) 43 | if name == "FriendlyName": 44 | fname = reg_get_value_data(val) 45 | reg_report((reg_get_lastwrite(key), fname)) 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /templates/template_files/ie_typed_urls.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # IE Typed URLs 26 | 27 | 28 | pluginname = "IE Typed URLs" 29 | description = "Displays URLs types in Internet Explorer." 30 | hive = "NTUSER" 31 | documentation = "" 32 | 33 | 34 | def run_me(): 35 | 36 | reg_set_report_header(("Number","URL")) 37 | regkey = reg_get_required_key("\Software\Microsoft\Internet Explorer\TypedURLs") 38 | reg_report_values_name_data(regkey) 39 | 40 | 41 | -------------------------------------------------------------------------------- /templates/template_files/last_access_disabled.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Last Access Disabled 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Last Access Disabled" 30 | description = "Displays whether last access time filesystem timestamps are disabled." 31 | hive = "SYSTEM" 32 | 33 | 34 | def run_me(): 35 | 36 | regkey = reg_get_required_key("\ControlSet00"+get_current_control_set()+"\Control\FileSystem") 37 | found = False 38 | for val in reg_get_values(regkey): 39 | if reg_get_value_name(val) == "NtfsDisableLastAccessUpdate": 40 | found = True 41 | reg_report((reg_get_value_name(val), reg_get_value_data(val))) 42 | if not found: 43 | reg_report("NtfsDisableLastAccessUpdate not found.") 44 | 45 | -------------------------------------------------------------------------------- /templates/template_files/listusers.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "List Users" 30 | description = "Lists user accounts on the system." 31 | hive = "SAM" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\SAM\Domains\Account\Users\Names") 38 | 39 | for skey in reg_get_subkeys(regkey): 40 | reg_report(reg_get_key_name(skey)) 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/template_files/map_network_drive_letters.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # Kevin Moore - km@while1forensics.com 27 | # Version 0.1 28 | # 29 | 30 | pluginname = "Mapped Network Drive Letters" 31 | description = "Lists user's mapped network drives according to volume letter" 32 | hive = "NTUSER" 33 | documentation = "" 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Network") 38 | subkeys = reg_get_subkeys(regkey) 39 | 40 | for key in subkeys: 41 | reg_report(('Drive Letter', reg_get_key_name(key))) 42 | reg_report(('Last Written Date', reg_get_lastwrite(key))) 43 | reg_report_values_name_data(key) 44 | reg_report(('')) 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/template_files/map_network_drive_mru.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "Map Network Drive MRU" 30 | description = "Lists recentloy mapped network drives." 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | def run_me(): 35 | 36 | regkey = reg_get_required_key("\Software\Microsoft\Windows\CurrentVersion\Explorer\Map Network Drive MRU") 37 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 38 | reg_report_values_name_data(regkey) 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/template_files/mmc_mru.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "MMC MRU" 30 | description = "Lists recently used components of the Microsoft Management Console." 31 | hive = "" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Software\Microsoft\Microsoft Management Console\Recent File List") 38 | reg_report_values_name_data(regkey) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /templates/template_files/mounted_devices.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Mounted Devices 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Mounted Devices" 30 | description = "Displays info on previously mounted devices." 31 | hive = "SYSTEM" 32 | 33 | 34 | def run_me(): 35 | 36 | reg_set_report_header(("Device Name","Signature")) 37 | regkey = reg_get_required_key("\MountedDevices") 38 | reg_report_values_name_data(regkey) 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /templates/template_files/mrulist.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "User MRUs" 30 | description = "" 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | mru_keys = ( 38 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU", 39 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSaveMRU", 40 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU", 41 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedMRU", 42 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU", 43 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRULegacy", 44 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\CIDSizeMRU", 45 | "\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\FirstFolder" ) 46 | 47 | ignore = ("MRUListEx") 48 | 49 | for mru_key in mru_keys: 50 | regkey = reg_get_key(mru_key) 51 | if regkey: 52 | reg_report((mru_key)) 53 | for val in reg_get_values(regkey): 54 | if reg_get_value_name(val) not in ignore: 55 | reg_report((reg_get_value_name(val), reg_get_value_data(val))) 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /templates/template_files/muicache.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "MUI Cache" 30 | description = "Displays executables from user MUICache key" 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Software\Microsoft\Windows\ShellNoRoam\MUICache") 38 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 39 | 40 | for val in reg_get_values(regkey): 41 | if reg_get_value_name(val) is not "LangID": 42 | reg_report((reg_get_value_name(val), reg_get_value_data(val))) 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /templates/template_files/muicache_update.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # Updated 03/09/12 27 | # Kevin Moore - km@while1forensics.com 28 | # 29 | 30 | pluginname = "MUI Cache" 31 | description = "Displays executables from user MUICache key" 32 | hives = ['NTUSER', 'USRCLASS'] 33 | documentation = "" 34 | 35 | 36 | def run_me(): 37 | 38 | def process_key(regkey): 39 | 40 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 41 | 42 | for val in reg_get_values(regkey): 43 | if reg_get_value_name(val) is not "LangID": 44 | reg_report((reg_get_value_name(val), reg_get_value_data(val))) 45 | 46 | if path_exists(root_key() + '\Local Settings\Software\Microsoft\Windows\shell\MUICache'): # USRCLASS 47 | 48 | regkey = reg_get_required_key('\Local Settings\Software\Microsoft\Windows\shell\MUICache') 49 | process_key(regkey) 50 | 51 | elif path_exists(root_key() + '\Software\Microsoft\Windows\ShellNoRoam\MUICache'): # NTUSER 52 | 53 | regkey = reg_get_required_key("\Software\Microsoft\Windows\ShellNoRoam\MUICache") 54 | process_key(regkey) 55 | 56 | else: 57 | reg_report(('MUICache not found in registry file')) 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /templates/template_files/profile_list.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "Profile List" 30 | description = "Displays contents of ProfileList key" 31 | hive = "SOFTWARE" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion\ProfileList") 38 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 39 | 40 | for key in reg_get_subkeys(regkey): 41 | 42 | reg_report(reg_get_key_name(key)) 43 | for val in reg_get_values(key): 44 | name = reg_get_value_name(val) 45 | data = reg_get_value_data(val) 46 | if name == "ProfileImagePath": 47 | reg_report((name, data)) 48 | if name == "Sid": 49 | reg_report((name, data)) 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /templates/template_files/recent_docs.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Recent Docs 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Recent Docs" 30 | description = "Displays files and folders recently accessed by this user." 31 | hive = "NTUSER" 32 | 33 | 34 | def run_me(): 35 | 36 | regkey = reg_get_required_key("\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs") 37 | values = reg_get_values(regkey) 38 | 39 | for val in values: 40 | name = reg_get_value_name(val) 41 | data = reg_get_value_data(val) 42 | if name == "MRUListEx" and data: 43 | if len(data) == 1: 44 | data = ord(data) 45 | 46 | reg_report((name, data)) 47 | 48 | -------------------------------------------------------------------------------- /templates/template_files/recent_docs_update.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Recent Docs 26 | # ver 1.0 27 | # 07/18/2011 28 | # 29 | # Updated by Kevin Moore - km@while1forensics.com 30 | # 7/12/12 31 | 32 | pluginname = "Recent Docs Ordered" 33 | description = "Displays files and folders recently accessed by this user " \ 34 | "and ordered by their associated MRUListEx value" 35 | hive = "NTUSER" 36 | 37 | def run_me(): 38 | 39 | import struct 40 | 41 | def chunks(l, n): 42 | list = [] 43 | for i in range(0, len(l), n): 44 | list.append(str(l[i:i+n])) 45 | return list 46 | 47 | def determine_mru_order(reg_value_data): 48 | mru_order = [] 49 | ptr = 0 50 | # Each MRUListEx entry is 4 bytes (uint) and \xFF\xFF\xFF\xFF 51 | # signifies the end of the entries data 52 | while reg_value_data[ptr:ptr+4] != '\xFF\xFF\xFF\xFF': 53 | mru, = struct.unpack('I', reg_value_data[ptr:ptr+4]) 54 | mru_order.append(mru) 55 | ptr += 4 56 | return mru_order 57 | 58 | def get_recent_doc_values(key): 59 | entry_values = {} 60 | recent_doc_entries = reg_get_values(key) 61 | order = None 62 | for value in recent_doc_entries: 63 | name = reg_get_value_name(value) 64 | # MRUListEx provides an ordered list of when RecentDocs 65 | # entries were accessed 66 | if name.lower() in ['viewstream']: 67 | continue # Research needs to be conducted to determine if any data of 68 | # value can be gained from this key 69 | if name.lower() in ['mrulistex']: 70 | value_data = reg_get_raw_value_data(value) 71 | order = determine_mru_order(value_data) 72 | split_mrulist = chunks(order, 20) 73 | # Prints a list of the MRUListEx ordered list for reference) 74 | reg_report(('MRUListEx Order: ', '\n'.join(split_mrulist))) 75 | else: 76 | value_data = reg_get_value_data(value) 77 | entry_values[name] = value_data 78 | if order is None: 79 | for k, v in entry_values.iteritems(): 80 | reg_report((v, str(k))) 81 | else: 82 | for item in order: 83 | try: 84 | item = str(item) 85 | reg_report((entry_values[item],str(item))) 86 | except: 87 | reg_report(('***ERROR: Unidentified MRUList Entry', str(item))) 88 | 89 | key_path = "\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs" 90 | key = reg_get_required_key(key_path) 91 | report((key_path, reg_get_lastwrite(key))) 92 | get_recent_doc_values(key) # Get Root Entries under RecentDocs folder 93 | subkeys = reg_get_subkeys(key) # Get subfolder values 94 | 95 | for key in subkeys: 96 | report((key_path + "\\" + reg_get_key_name(key), reg_get_lastwrite(key))) 97 | get_recent_doc_values(key) 98 | 99 | -------------------------------------------------------------------------------- /templates/template_files/sbp2.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # SBP2 26 | 27 | pluginname = "SBP2 - FireWire" 28 | description = "Displays FireWire (IEEE 1394) device connection information" 29 | hive = "SYSTEM" 30 | 31 | 32 | def run_me(): 33 | 34 | reg_set_report_header(("Last Write Time", "Device Name","Serial Number")) 35 | 36 | regkey = reg_get_required_key("\ControlSet00"+get_current_control_set()+"\Enum\SBP2") 37 | 38 | for rkey in reg_get_subkeys(regkey): 39 | for key in reg_get_subkeys(rkey): 40 | ltime = reg_get_lastwrite(rkey) 41 | serial = reg_get_key_name(key) 42 | fname = "" 43 | prefix = "" 44 | for val in reg_get_values(key): 45 | name = reg_get_value_name(val) 46 | if name == "FriendlyName": 47 | fname = reg_get_value_data(val) 48 | reg_report((ltime, fname, serial)) 49 | 50 | -------------------------------------------------------------------------------- /templates/template_files/services.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Mounted Devices 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Services" 30 | description = "Displays info on running services." 31 | hive = "SYSTEM" 32 | 33 | svc_types = { 0x001 : "Kernel driver", 34 | 0x002 : "File system driver", 35 | 0x010 : "Own_Process", 36 | 0x020 : "Share_Process", 37 | 0x100 : "Interactive" } 38 | 39 | start_types = { 0x00 : "Boot Start", 40 | 0x01 : "System Start", 41 | 0x02 : "Auto Start", 42 | 0x03 : "Manual", 43 | 0x04 : "Disabled" } 44 | 45 | 46 | def run_me(): 47 | 48 | reg_set_report_header(("Name","Display Name","Image Path", "Type", "Start", "Group")) 49 | 50 | regkey = reg_get_required_key("\ControlSet00"+get_current_control_set()+"\services") 51 | subkeys = reg_get_subkeys(regkey) 52 | 53 | for key in subkeys: 54 | fields = { 55 | "Name" : "", 56 | "DisplayName" : "", 57 | "ImagePath" : "", 58 | "Type" : "", 59 | "Start" : "", 60 | "Group" : "" 61 | } 62 | 63 | fields["Name"] = reg_get_key_name(key) 64 | values = reg_get_values(key) 65 | for val in values: 66 | name = reg_get_value_name(val) 67 | data = reg_get_value_data(val) 68 | 69 | 70 | if name in fields.keys(): 71 | fields[name] = data 72 | if name == "Type": 73 | if data: 74 | idata = int(data) 75 | else: 76 | idata = 0 77 | if idata in svc_types.keys(): 78 | fields[name] = svc_types[idata] 79 | if name == "Start": 80 | if data: 81 | idata = int(data) 82 | else: 83 | idata = 0 84 | fields[name] = start_types[idata] 85 | 86 | reg_report((fields["Name"], fields["DisplayName"], fields["ImagePath"], fields["Type"], fields["Start"], fields["Group"])) 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /templates/template_files/system_run.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | 30 | pluginname = "System Runs" 31 | description = "Displays (some of the) programs that run at system startup." 32 | hive = "SOFTWARE" 33 | documentation = "" 34 | 35 | 36 | def run_me(): 37 | 38 | run_keys = ( 39 | "\Microsoft\Windows\CurrentVersion\Runonce", 40 | "\Microsoft\Windows\CurrentVersion\policies\Explorer\Run", 41 | "\Microsoft\Windows\CurrentVersion\Run" ) 42 | 43 | reg_set_report_header(("Name", "Path")) 44 | 45 | for rk in run_keys: 46 | regkey = reg_get_key(rk) 47 | if regkey: 48 | reg_report_values_name_data(regkey) 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /templates/template_files/system_run_update.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # Updated 3/9/12 27 | # Kevin Moore - km@while1forensics.com 28 | # 29 | # 30 | 31 | 32 | pluginname = "System Runs" 33 | description = "Displays (some of the) programs that run at system startup." 34 | hive = "SOFTWARE" 35 | documentation = "" 36 | 37 | 38 | def run_me(): 39 | 40 | run_keys = ( 41 | "\Microsoft\Windows\CurrentVersion\Runonce", 42 | "\Microsoft\Windows\CurrentVersion\policies\Explorer\Run", 43 | "\Microsoft\Windows\CurrentVersion\Run", 44 | "\Microsoft\Windows\CurrentVersion\RunOnceEx", 45 | "\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunOnceEx", 46 | "\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunOnce", 47 | "\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run", 48 | "\Microsoft\Windows NT\CurrentVersion\Winlogon", 49 | "\Policies\Microsoft\Windows\System" ) 50 | 51 | parse_keys = ['\Microsoft\Windows NT\CurrentVersion\Winlogon', 52 | '\Policies\Microsoft\Windows\System'] 53 | 54 | parse_vals = ['shell','userinit'] 55 | 56 | reg_set_report_header(("Key", "Name", "Path")) 57 | 58 | for rk in run_keys: 59 | 60 | regkey = reg_get_key(rk) 61 | 62 | if regkey: 63 | 64 | if rk in parse_keys: 65 | 66 | key = reg_get_required_key(rk) 67 | values = reg_get_values(key) 68 | 69 | for val in values: 70 | name = reg_get_value_name(val) 71 | name = name.lower() 72 | 73 | if name in parse_vals: 74 | reg_report((rk, name, reg_get_value_data(val))) 75 | 76 | else: 77 | 78 | values = reg_get_values(regkey) 79 | 80 | for val in values: 81 | reg_report((rk, reg_get_value_name(val), reg_get_value_data(val))) 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /templates/template_files/typed_paths.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "Typed Paths" 30 | description = "Displays paths stored in user TypedPaths key" 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths") 38 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 39 | reg_report_values_name_data(regkey) 40 | 41 | 42 | -------------------------------------------------------------------------------- /templates/template_files/usbstor.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # USBSTOR 26 | 27 | pluginname = "USBSTOR" 28 | description = "Displays USB insertion information" 29 | hive = "SYSTEM" 30 | 31 | 32 | def run_me(): 33 | 34 | reg_set_report_header(("Last Write Time", "Device Name","Serial Number")) 35 | 36 | regkey = reg_get_required_key("\ControlSet00"+get_current_control_set()+"\Enum\USBSTOR") 37 | 38 | for rkey in reg_get_subkeys(regkey): 39 | for key in reg_get_subkeys(rkey): 40 | ltime = reg_get_lastwrite(rkey) 41 | serial = reg_get_key_name(key) 42 | fname = "" 43 | prefix = "" 44 | for val in reg_get_values(key): 45 | name = reg_get_value_name(val) 46 | if name == "FriendlyName": 47 | fname = reg_get_value_data(val) 48 | reg_report((ltime, fname, serial)) 49 | 50 | -------------------------------------------------------------------------------- /templates/template_files/user_assist.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Kevin Moore - CERT - kevinm@cert.org 26 | 27 | pluginname = "User Assist" 28 | description = "" 29 | hive = "NTUSER" 30 | documentation = "" 31 | 32 | ver_7_2008_ids = ("{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}", "{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}") 33 | 34 | def run_me(): 35 | 36 | import struct 37 | from datetime import datetime 38 | 39 | date_format = '%Y/%m/%d %H:%M:%S UTC' # Change this to the format you prefer 40 | 41 | def convert_win_to_unix(windate): 42 | 43 | # Converts 8-byte Windows Date/Time stamps to Unix Date/Time stamps so python can deal with it better 44 | 45 | no_nano = windate/10000000 # 10000000 - 100 nanosecond intervals in windows timestamp, remove them to get to seconds since windows epoch 46 | unix = no_nano - 11644473600 # number of seconds between 1/1/1601 and 1/1/1970 47 | return unix 48 | 49 | # ENDFUNCTION - convert_win_to_unix 50 | 51 | reg_set_report_header(("UserAssist Value","SessionID","Run Count","Last Ran Date", "Key ID")) 52 | 53 | regkey = reg_get_required_key("\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist") 54 | subkeys = reg_get_subkeys(regkey) 55 | 56 | for key in subkeys: 57 | 58 | key_name = reg_get_key_name(key) 59 | 60 | key_path = "\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist" 61 | key_path += "\%s\count" % key_name 62 | 63 | skey = reg_get_required_key(key_path) 64 | values = reg_get_values(skey) 65 | 66 | for val in values: 67 | 68 | name = rot13(reg_get_value_name(val)) 69 | data = reg_get_raw_value_data(val) # Grabs raw hex values associated with registry entry 70 | 71 | if key_name in ver_7_2008_ids: 72 | 73 | if data >= 68: 74 | 75 | runcount, = struct.unpack("I", data[4:8]) # Run Count - 4 byte int 76 | dateval, = struct.unpack("Q", data[60:68]) # Windows Date - Quad - 8 btye date/time value 77 | 78 | if dateval > 0: # Make sure it is a valid date 79 | 80 | dt = convert_win_to_unix(dateval) # converts from Windows to Unix so python can deal with it 81 | 82 | if dt >= 0: # Makes sure it is a valid date 83 | reg_report((name, '', str(runcount), datetime.fromtimestamp(int(dt)).strftime(date_format), key_name)) 84 | else: # If not valid, just print name and runcount 85 | reg_report((name, '', str(runcount), '', key_name)) 86 | else: 87 | reg_report((name, '', str(runcount), '', key_name)) 88 | 89 | else: # Else just print the name 90 | reg_report((name, '', '', key_name)) 91 | 92 | # Vista, XP & 2K3 93 | elif len(data) == 16: # All XP & 2003 UserAssist values are 16 btyes long 94 | 95 | session, runcount, dateval = struct.unpack("IIQ", data) # SessionID , RunCount , Last Ran Date 96 | runcount -= 5 # In 2K3 and XP RunCount starts counting at 5 97 | 98 | if dateval > 0: 99 | 100 | dt = convert_win_to_unix(dateval) # converts from Windows to Unix so python can deal with it 101 | 102 | if dt >= 0: # Like above, checks for valid date/time value 103 | reg_report((name, str(session), str(runcount), datetime.fromtimestamp(int(dt)).strftime(date_format), key_name)) # ROT13 name, Session ID, RunCount, Last Run Date 104 | else: 105 | reg_report((name, str(session), str(runcount), key_name)) # UserAssist Values with invalid last run date 106 | 107 | else: 108 | reg_report((name, '', '', '', key_name)) # UserAssist Values with blank last run date 109 | 110 | elif len(data) < 16: 111 | reg_report((name, '', '', '', key_name)) 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /templates/template_files/user_run.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # User Run 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "User Run" 30 | description = "Displays autoruns for this user." 31 | hive = "NTUSER" 32 | 33 | 34 | def run_me(): 35 | 36 | run_keys = ( 37 | "\Software\Microsoft\Windows\CurrentVersion\Runonce", 38 | "\Software\Microsoft\Windows NT\CurrentVersion\Windows\Run", 39 | "\Software\Microsoft\Windows\CurrentVersion\Run" ) 40 | 41 | 42 | reg_set_report_header(("Name", "Path")) 43 | 44 | for rk in run_keys: 45 | regkey = reg_get_key(rk) 46 | if regkey: 47 | reg_report_values_name_data(regkey) 48 | 49 | 50 | -------------------------------------------------------------------------------- /templates/template_files/user_software.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "User Software" 30 | description = "Lists the contents of the Software key for a user's NTUSER hive." 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Software") 38 | 39 | for key in reg_get_subkeys(regkey): 40 | reg_report((reg_get_key_name(key))) 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /templates/template_files/windows_install_info.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Windows Install Info 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Windows Install Information" 30 | description = "Displays the exact Windows version and other associated install data." 31 | hive = "SOFTWARE" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion") 38 | values = reg_get_values(regkey) 39 | 40 | for val in values: 41 | name = reg_get_value_name(val) 42 | data = reg_get_value_data(val) 43 | if name == "InstallDate": 44 | data = pretty_unixtime(data) 45 | reg_report((name, data)) 46 | 47 | 48 | -------------------------------------------------------------------------------- /templates/template_files/windows_logon_info.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Windows Logon Info 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Windows Logon Information" 30 | description = "Displays info on Windows login settings." 31 | hive = "SOFTWARE" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion\Winlogon") 38 | reg_report_values_name_data(regkey) 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/template_files/windows_uninstall.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Windows Uninstall 26 | # Version 0.1 27 | # 28 | # Kevin Moore - km@while1forensics.com 29 | # 30 | 31 | pluginname = "Windows Uninstall" 32 | description = "Displays Windows compatible programs with an uninstall application or feature" 33 | hive = "SOFTWARE" 34 | 35 | def run_me(): 36 | 37 | def get_values(key): 38 | 39 | reg_entries = reg_get_values(key) 40 | 41 | for val in reg_entries: 42 | 43 | name = reg_get_value_name(val) 44 | data = reg_get_value_data(val) 45 | reg_report((name,data)) # Once we have gathered an order list and all our RecentDocs values, print them out in the order in which they were last accessed 46 | 47 | reg_report(('')) 48 | # END FUNCTION - get_values 49 | 50 | # Start of Plugin's processing... 51 | 52 | key_path = "\Microsoft\Windows\CurrentVersion\Uninstall" 53 | key = reg_get_required_key(key_path) # Header format for each RecentDocs folder is: RegistryPath, LastWrittenDate 54 | 55 | subkeys = reg_get_subkeys(key) # RecentDocs folder sometimes contains subfolders 56 | 57 | for key in subkeys: 58 | 59 | reg_report((key_path + "\\" + reg_get_key_name(key), reg_get_lastwrite(key))) # Subfolder report value header: RegistryPath, LastWrittenDate 60 | get_values(key) # Get Values from Subkey 61 | 62 | 63 | -------------------------------------------------------------------------------- /templates/template_files/windows_version.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "Windows Version" 30 | description = "Display inofrmation on exact Windows version installed." 31 | hive = "SOFTWARE" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion") 38 | reg_set_report_timestamp(reg_get_lastwrite(regkey)) 39 | 40 | fields = ["ProductName", "CSDVersion", "BuildName", "BuildNameEx", "InstallDate"] 41 | 42 | for val in reg_get_values(regkey): 43 | valname = reg_get_value_name(val) 44 | if valname in fields: 45 | if valname == "InstallDate": 46 | reg_report((valname, pretty_unixtime(reg_get_value_data(val)))) 47 | else: 48 | reg_report((valname, reg_get_value_data(val))) 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /templates/template_files/winrar_archive_history.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Kevin Moore - km@while1forensics.com 26 | # Version 0.1 27 | # 28 | # 29 | 30 | pluginname = "WinRAR Archive History" 31 | description = "Provides information on recent WinRAR archives and extraction locations" 32 | hive = "NTUSER" 33 | documentation = "" 34 | 35 | def run_me(): 36 | 37 | def process_subkeys(subkeys): 38 | 39 | for sub in subkeys: 40 | 41 | key = reg_get_key_name(sub) 42 | 43 | if key == 'ArcHistory': 44 | 45 | reg_report(('Archive History')) 46 | reg_report_values_name_data(sub) 47 | reg_report(('')) 48 | 49 | elif key == 'DialogEditHistory': 50 | 51 | reg_report(('Dialog Edit History')) 52 | 53 | new_key = reg_get_required_key("\Software\WinRAR\DialogEditHistory") 54 | reg_report_values_name_data(new_key) 55 | subsub_keys = reg_get_subkeys(new_key) 56 | 57 | for sk in subsub_keys: 58 | 59 | reg_report(reg_get_key_name(sk)) 60 | reg_report_values_name_data(sk) 61 | 62 | reg_report(('')) 63 | 64 | # END FUNCTION process_subkeys 65 | 66 | try: 67 | regkey = reg_get_required_key("\Software\WinRAR") 68 | subkeys = reg_get_subkeys(regkey) 69 | process_subkeys(subkeys) 70 | 71 | except: 72 | reg_report(('WinRAR Folder Not Identified in Registry File')) -------------------------------------------------------------------------------- /templates/template_files/wireless_networks.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # Wireless Networks 26 | # ver 1.0 27 | # 07/18/2011 28 | 29 | pluginname = "Wireless Networks" 30 | description = "Displays info on connections to wireless networks." 31 | hive = "SOFTWARE" 32 | documentation = "" 33 | 34 | 35 | def run_me(): 36 | 37 | regkey = reg_get_required_key("\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles") 38 | subkeys = reg_get_subkeys(regkey) 39 | 40 | for key in subkeys: 41 | values = reg_get_values(key) 42 | 43 | for val in values: 44 | name = reg_get_value_name(val) 45 | if name == "DateCreated" or name == "DateLastConnected": 46 | data = reg_get_raw_value_data(val) 47 | data = pretty_date128(data) 48 | else: 49 | data = reg_get_value_data(val) 50 | 51 | reg_report((name, data)) 52 | 53 | 54 | -------------------------------------------------------------------------------- /templates/template_files/wordwheelquery.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | # 26 | # 27 | # 28 | 29 | pluginname = "Word Wheel Query" 30 | description = "Lists Windows 7 user-entered search queries." 31 | hive = "NTUSER" 32 | documentation = "" 33 | 34 | def run_me(): 35 | 36 | regkey = reg_get_required_key("\Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery") 37 | reg_report_values_name_data(regkey) 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /templates/util/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Registry Decoder 3 | # Copyright (c) 2011 Digital Forensics Solutions, LLC 4 | # 5 | # Contact email: registrydecoder@digitalforensicssolutions.com 6 | # 7 | # Authors: 8 | # Andrew Case - andrew@digitalforensicssolutions.com 9 | # Lodovico Marziale - vico@digitalforensicssolutions.com 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or (at 14 | # your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, but 17 | # WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | # General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License 22 | # along with this program; if not, write to the Free Software 23 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | # 25 | __all__ = ["util"] 26 | --------------------------------------------------------------------------------