diff --git a/trunk/datainterpreter.cpp b/trunk/datainterpreter.cpp index 6cf0e84..6d6bd74 100644 --- a/trunk/datainterpreter.cpp +++ b/trunk/datainterpreter.cpp @@ -1,72 +1,76 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "datainterpreter.h" #include #include DataInterpreter::DataInterpreter(QWidget *p_parent) : QTableWidget(p_parent) { this->setColumnCount(2); this->setTextElideMode(Qt::ElideNone); this->horizontalHeader()->setHidden(true); this->verticalHeader()->setHidden(true); + this->setSelectionBehavior(QAbstractItemView::SelectRows); + this->setSelectionMode(QAbstractItemView::SingleSelection); } DataInterpreter::~DataInterpreter() { // Free table widget items this->ClearValues(); } void DataInterpreter::AddValue(QString name, QString value) { QTableWidgetItem *p_name_item=new QTableWidgetItem(name); + p_name_item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); QTableWidgetItem *p_value_item=new QTableWidgetItem(value); + p_value_item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); this->setRowCount(this->rowCount()+1); this->setItem(this->rowCount()-1,0,p_name_item); this->setItem(this->rowCount()-1,1,p_value_item); this->resizeColumnsToContents(); this->resizeRowsToContents(); } void DataInterpreter::ClearValues() { // Free all items while(this->rowCount()>0) { delete this->item(0,0); delete this->item(0,1); this->setRowCount(this->rowCount()-1); } } int DataInterpreter::sizeHintForColumn(int column) const { int size_hint=0; int i=0; int item_width=0; QFontMetrics fm(this->fontMetrics()); // Find string that needs the most amount of space for(i=0;irowCount();i++) { item_width=fm.width(this->item(i,column)->text())+10; if(item_width>size_hint) size_hint=item_width; } return size_hint; } diff --git a/trunk/datareporter.cpp b/trunk/datareporter.cpp index 10072dc..8a80086 100644 --- a/trunk/datareporter.cpp +++ b/trunk/datareporter.cpp @@ -1,152 +1,171 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "datareporter.h" #include #include #include #include DataReporter::DataReporter() { this->report_templates.clear(); //this->p_report_engine=new DataReporterEngine(); } DataReporter::~DataReporter() { //delete this->p_report_engine; qDeleteAll(this->report_templates); } void DataReporter::LoadReportTemplates(QString dir) { QString report_template=""; int i=0; + int ii=0; + bool found=false; QString report_category=""; QString report_name=""; ReportTemplate *p_report; // Get all template files in report_templates directory QDir report_dir(dir); QStringList found_report_templates=report_dir. entryList(QStringList()<<"*.qs"); for(i=0;i_.qs) report_category=found_report_templates.value(i).left( found_report_templates.value(i).indexOf("_")); report_name=found_report_templates.value(i).mid( found_report_templates.value(i).indexOf("_")+1); report_name=report_name.left(report_name.lastIndexOf(".")); - // Add report to list - p_report=new ReportTemplate(report_category, - report_name, - report_template); - this->report_templates.append(p_report); + // Check if a report with the same category/name was already added + found=false; + for(ii=0;iireport_templates.count();ii++) { + if(this->report_templates.at(ii)->Category()==report_category && + this->report_templates.at(ii)->Name()==report_name) + { + found=true; + break; + } + } + + if(!found) { + // Add report to list + p_report=new ReportTemplate(report_category, + report_name, + report_template); + this->report_templates.append(p_report); + } else { + // Update report entry + p_report=this->report_templates.at(ii); + p_report->SetFile(report_template); + } } } QStringList DataReporter::GetAvailableReportCategories() { QStringList ret; QString cat; int i=0; ret.clear(); for(i=0;ireport_templates.count();i++) { cat=this->report_templates.value(i)->Category(); if(!ret.contains(cat)) ret.append(cat); } ret.sort(); return ret; } QStringList DataReporter::GetAvailableReports(QString category) { QStringList ret; QString cat; int i=0; ret.clear(); for(i=0;ireport_templates.count();i++) { cat=this->report_templates.value(i)->Category(); if(cat==category) ret.append(this->report_templates.value(i)->Name()); } ret.sort(); return ret; } QString DataReporter::GenerateReport(RegistryHive *p_hive, QString report_category, QString report_name) { int i=0; ReportTemplate *p_report; DataReporterEngine engine(p_hive); QString report_code; //ReportData report_data; for(i=0;ireport_templates.count();i++) { p_report=this->report_templates.value(i); if(p_report->Category()!=report_category || p_report->Name()!=report_name) { continue; } QScriptValue hive_value=engine.newQObject(p_hive); engine.globalObject().setProperty("RegistryHive",hive_value); //QScriptValue return_value=engine.newQObject(&report_data); //engine.globalObject().setProperty("ReportData",return_value); // Open report template QFile template_file(p_report->File()); if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug("Couldn't open file '%s'",p_report->File().toAscii().constData()); return QString(); } // Read template file QTextStream in(&template_file); while(!in.atEnd()) { report_code.append(in.readLine()).append("\n"); } // Close report template file template_file.close(); QScriptValue report_result=engine.evaluate(report_code,p_report->File()); if (report_result.isError() || engine.hasUncaughtException()) { QMessageBox::critical(0, "Hello Script", QString::fromLatin1("%0:%1: %2") .arg(p_report->File()) .arg(report_result.property("lineNumber").toInt32()) .arg(report_result.toString())); return QString(); } return engine.report_content; } return QString(); } diff --git a/trunk/fred.pro b/trunk/fred.pro index 934bb59..ac6f55a 100644 --- a/trunk/fred.pro +++ b/trunk/fred.pro @@ -1,80 +1,84 @@ #******************************************************************************* # fred Copyright (c) 2011 by Gillen Daniel * # * # Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * # with special feautures useful during forensic analysis. * # * # This program is free software: you can redistribute it and/or modify it * # under the terms of the GNU General Public License as published by the Free * # Software Foundation, either version 3 of the License, or (at your option) * # any later version. * # * # This program is distributed in the hope that it will be useful, but WITHOUT * # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * # more details. * # * # You should have received a copy of the GNU General Public License along with * # this program. If not, see . * #******************************************************************************/ system(bash compileinfo.sh > compileinfo.h) QT += core \ gui \ xml \ script \ webkit TARGET = fred TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp \ registrynode.cpp \ registrynodetreemodel.cpp \ registrykey.cpp \ registrykeytablemodel.cpp \ dlgabout.cpp \ dlgkeydetails.cpp \ qhexedit/qhexedit_p.cpp \ qhexedit/qhexedit.cpp \ datainterpreter.cpp \ reporttemplate.cpp \ datareporter.cpp \ datareporterengine.cpp \ registryhive.cpp \ qtscript_types/bytearray.cpp \ qtscript_types/bytearrayprototype.cpp \ qtscript_types/bytearrayiterator.cpp \ - dlgreportviewer.cpp + dlgreportviewer.cpp \ + registrykeytable.cpp \ + registrynodetree.cpp HEADERS += mainwindow.h \ registrynode.h \ registrynodetreemodel.h \ registrykey.h \ registrykeytablemodel.h \ dlgabout.h \ dlgkeydetails.h \ qhexedit/qhexedit_p.h \ qhexedit/qhexedit.h \ datainterpreter.h \ reporttemplate.h \ datareporter.h \ datareporterengine.h \ registryhive.h \ qtscript_types/bytearray.h \ qtscript_types/bytearrayprototype.h \ qtscript_types/bytearrayiterator.h \ - dlgreportviewer.h + dlgreportviewer.h \ + registrykeytable.h \ + registrynodetree.h FORMS += mainwindow.ui \ dlgabout.ui \ dlgkeydetails.ui \ dlgreportviewer.ui LIBS += -lhivex RESOURCES += fred.qrc diff --git a/trunk/mainwindow.cpp b/trunk/mainwindow.cpp index a9dd55f..ab19b99 100644 --- a/trunk/mainwindow.cpp +++ b/trunk/mainwindow.cpp @@ -1,541 +1,538 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef FRED_REPORT_TEMPLATE_DIR #define FRED_REPORT_TEMPLATE_DIR "/usr/share/fred/report_templates/" #endif #include #include #include #include #include #include #include "mainwindow.h" #include "ui_mainwindow.h" #include "dlgabout.h" #include "dlgkeydetails.h" #include "dlgreportviewer.h" #include "compileinfo.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // Initialize private vars this->p_hive=new RegistryHive(this); this->is_hive_open=false; this->p_reg_node_tree_model=NULL; this->p_reg_key_table_model=NULL; // Check for ~/.fred config dir this->CheckUserConfigDir(); // Set main window size int cur_screen=QApplication::desktop()->screenNumber(this); int window_width= QApplication::desktop()->availableGeometry(cur_screen).width()*0.5; int window_height= QApplication::desktop()->availableGeometry(cur_screen).height()*0.5; int window_x= (QApplication::desktop()->availableGeometry(cur_screen).width()/2)- (window_width/2); int window_y= (QApplication::desktop()->availableGeometry(cur_screen).height()/2)- (window_height/2); this->setGeometry(window_x, window_y, window_width, window_height); // Create widgets this->p_horizontal_splitter=new QSplitter(); this->p_horizontal_splitter->setOrientation(Qt::Horizontal); - this->p_node_tree=new QTreeView(this->p_horizontal_splitter); + this->p_node_tree=new RegistryNodeTree(this->p_horizontal_splitter); this->p_node_tree->setHeaderHidden(true); this->p_vertical_splitter=new QSplitter(this->p_horizontal_splitter); this->p_vertical_splitter->setOrientation(Qt::Vertical); - this->p_key_table=new QTableView(this->p_vertical_splitter); - this->p_key_table->setSelectionBehavior(QAbstractItemView::SelectRows); + this->p_key_table=new RegistryKeyTable(this->p_vertical_splitter); this->p_horizontal_splitter2=new QSplitter(this->p_vertical_splitter); this->p_horizontal_splitter2->setOrientation(Qt::Horizontal); this->p_hex_edit_widget=new QWidget(this->p_horizontal_splitter2); this->p_hex_edit_layout=new QVBoxLayout(this->p_hex_edit_widget); this->p_hex_edit_layout->setContentsMargins(0,0,0,0); this->p_hex_edit=new QHexEdit(); this->p_hex_edit->setReadOnly(true); this->p_hex_edit_status_bar=new QLabel(); this->p_data_interpreter=new DataInterpreter(this->p_horizontal_splitter2); // Make sure hex viewer font is monospaced. QFont mono_font("Monospace"); mono_font.setStyleHint(QFont::TypeWriter); this->p_hex_edit->setFont(mono_font); // Lay out widgets this->p_hex_edit_layout->addWidget(this->p_hex_edit); this->p_hex_edit_layout->addWidget(this->p_hex_edit_status_bar); this->p_horizontal_splitter2->addWidget(this->p_hex_edit_widget); this->p_horizontal_splitter2->addWidget(this->p_data_interpreter); this->p_vertical_splitter->addWidget(this->p_key_table); this->p_vertical_splitter->addWidget(this->p_horizontal_splitter2); this->p_horizontal_splitter->addWidget(this->p_node_tree); this->p_horizontal_splitter->addWidget(this->p_vertical_splitter); // Set stretch factors QSizePolicy node_tree_policy=this->p_node_tree->sizePolicy(); node_tree_policy.setHorizontalStretch(1); node_tree_policy.setVerticalStretch(100); this->p_node_tree->setSizePolicy(node_tree_policy); QSizePolicy vertical_splitter_policy=this->p_vertical_splitter->sizePolicy(); vertical_splitter_policy.setHorizontalStretch(4); vertical_splitter_policy.setVerticalStretch(100); this->p_vertical_splitter->setSizePolicy(vertical_splitter_policy); QSizePolicy key_table_policy=this->p_key_table->sizePolicy(); key_table_policy.setVerticalStretch(5); key_table_policy.setHorizontalStretch(100); this->p_key_table->setSizePolicy(key_table_policy); QSizePolicy hex_edit_widget_policy=this->p_hex_edit_widget->sizePolicy(); hex_edit_widget_policy.setVerticalStretch(2); hex_edit_widget_policy.setHorizontalStretch(200); this->p_hex_edit_widget->setSizePolicy(hex_edit_widget_policy); QSizePolicy data_interpreter_policy=this->p_data_interpreter->sizePolicy(); data_interpreter_policy.setVerticalStretch(2); data_interpreter_policy.setHorizontalStretch(0); this->p_data_interpreter->setSizePolicy(data_interpreter_policy); // Connect signals this->connect(this->p_node_tree, SIGNAL(clicked(QModelIndex)), this, SLOT(SlotNodeTreeClicked(QModelIndex))); this->connect(this->p_node_tree, SIGNAL(activated(QModelIndex)), this, SLOT(SlotNodeTreeClicked(QModelIndex))); this->connect(this->p_key_table, SIGNAL(clicked(QModelIndex)), this, SLOT(SlotKeyTableClicked(QModelIndex))); this->connect(this->p_key_table, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(SlotKeyTableDoubleClicked(QModelIndex))); this->connect(this->p_hex_edit, SIGNAL(currentAddressChanged(int)), this, SLOT(SlotHexEditAddressChanged(int))); // Add central widget this->setContentsMargins(4,4,4,0); this->setCentralWidget(this->p_horizontal_splitter); // Set window title this->UpdateWindowTitle(); // Set last open location to home dir this->last_open_location=QDir::homePath(); // Load report templates and update menu this->p_data_reporter=new DataReporter(); // Load reports from system wide include dir this->p_data_reporter->LoadReportTemplates(FRED_REPORT_TEMPLATE_DIR); // Load user's report templates this->p_data_reporter->LoadReportTemplates(QDir::homePath() .append(QDir::separator()) .append(".fred") .append(QDir::separator()) .append("report_templates")); this->UpdateDataReporterMenu(); // Finally, parse command line arguments this->ParseCommandLineArgs(); } MainWindow::~MainWindow() { if(this->is_hive_open) { this->p_hive->Close(); } delete ui; } void MainWindow::on_action_Quit_triggered() { qApp->exit(); } void MainWindow::on_action_Open_hive_triggered() { QString hive_file=""; hive_file=QFileDialog::getOpenFileName(this, tr("Open registry hive"), this->last_open_location, tr("All files (*)")); if(hive_file=="") return; this->OpenHive(hive_file); } void MainWindow::on_action_Close_hive_triggered() { if(this->is_hive_open) { // Delete models if(this->p_reg_node_tree_model!=NULL) { + this->p_node_tree->setModel(NULL); delete this->p_reg_node_tree_model; this->p_reg_node_tree_model=NULL; } if(this->p_reg_key_table_model!=NULL) { + this->p_key_table->setModel(NULL); delete this->p_reg_key_table_model; this->p_reg_key_table_model=NULL; } // Remove any data from hex edit and data interpreter this->p_hex_edit->setData(QByteArray()); this->p_hex_edit_status_bar->setText(""); this->p_data_interpreter->ClearValues(); // Close hive this->p_hive->Close(); this->is_hive_open=false; this->ui->action_Close_hive->setEnabled(false); this->ui->MenuReports->setEnabled(false); this->UpdateWindowTitle(); } } void MainWindow::on_actionAbout_Qt_triggered() { QMessageBox::aboutQt(this,tr("About Qt")); } void MainWindow::on_actionAbout_fred_triggered() { DlgAbout dlg_about(this); dlg_about.exec(); } void MainWindow::SlotNodeTreeClicked(QModelIndex index) { QString node_path; if(!index.isValid()) return; //Built node path node_path.clear(); node_path=this->p_reg_node_tree_model->data(index,Qt::DisplayRole) .toString().prepend("\\"); while(this->p_reg_node_tree_model->parent(index)!=QModelIndex()) { // Prepend all parent nodes index=this->p_reg_node_tree_model->parent(index); node_path.prepend(this->p_reg_node_tree_model->data(index,Qt::DisplayRole) .toString().prepend("\\")); } // Create table model and attach it to the table view if(this->p_reg_key_table_model!=NULL) { + this->p_key_table->setModel(NULL); delete this->p_reg_key_table_model; this->p_hex_edit->setData(QByteArray()); this->p_hex_edit_status_bar->setText(""); this->p_data_interpreter->ClearValues(); } this->p_reg_key_table_model=new RegistryKeyTableModel(this->p_hive,node_path); this->p_key_table->setModel(this->p_reg_key_table_model); - - // Resize table rows / columns to fit data - this->p_key_table->resizeColumnsToContents(); - this->p_key_table->horizontalHeader()->stretchLastSection(); } void MainWindow::SlotKeyTableDoubleClicked(QModelIndex index) { Q_UNUSED(index); /* QModelIndex key_index; QModelIndex node_index; QStringList nodes; QString key_name; QString key_type; QByteArray key_value; if(!index.isValid()) return; // Get key name, type and value key_index=this->p_reg_key_table_model->index(index.row(),0); key_name=this->p_reg_key_table_model->data(key_index,Qt::DisplayRole) .toString(); key_index=this->p_reg_key_table_model->index(index.row(),1); key_type=this->p_reg_key_table_model->data(key_index,Qt::DisplayRole) .toString(); key_index=this->p_reg_key_table_model->index(index.row(),2); key_value=this->p_reg_key_table_model->data(key_index, RegistryKeyTableModel:: AdditionalRoles_GetRawData) .toByteArray(); // Get current node node_index=this->p_node_tree->currentIndex(); //Built node path nodes.clear(); nodes.append(this->p_reg_node_tree_model-> data(node_index,Qt::DisplayRole).toString()); while(this->p_reg_node_tree_model->parent(node_index)!=QModelIndex()) { // Prepend all parent nodes node_index=this->p_reg_node_tree_model->parent(node_index); nodes.prepend(this->p_reg_node_tree_model-> data(node_index,Qt::DisplayRole).toString()); } DlgKeyDetails dlg_key_details(this); dlg_key_details.SetValues(nodes,key_name,key_type,key_value); dlg_key_details.exec(); */ } void MainWindow::SlotKeyTableClicked(QModelIndex index) { if(!index.isValid()) return; this->selected_key_value= this->p_reg_key_table_model->data(this->p_reg_key_table_model-> index(index.row(),2), RegistryKeyTableModel:: AdditionalRoles_GetRawData) .toByteArray(); this->p_hex_edit->setData(this->selected_key_value); } void MainWindow::SlotHexEditAddressChanged(int hex_offset) { + if(!this->is_hive_open || this->selected_key_value.isEmpty()) return; + // Update hex edit status bar this->p_hex_edit_status_bar-> setText(QString().sprintf("Byte offset: 0x%04X (%u)",hex_offset,hex_offset)); // Update data interpreter this->UpdateDataInterpreter(hex_offset); } void MainWindow::SlotReportClicked() { // Get report category and name from sender and it's parent QString category=((QMenu*)((QAction*)QObject::sender())->parent())->title(); QString report=((QAction*)QObject::sender())->text(); // Generate report QString report_content=this->p_data_reporter->GenerateReport(this->p_hive, category, report); // Show result in report viewer if(report_content!=QString()) { DlgReportViewer *p_dlg_report_view=new DlgReportViewer(report_content,this); p_dlg_report_view->exec(); delete p_dlg_report_view; } else { // TODO: Something went wrong! } } void MainWindow::CheckUserConfigDir() { QString user_config_dir=QDir::homePath() .append(QDir::separator()) .append(".fred"); if(!QDir(user_config_dir).exists()) { // User config dir does not exists, try to create it if(!QDir().mkpath(user_config_dir)) { // TODO: Maybe warn user return; } user_config_dir.append(QDir::separator()).append("report_templates"); if(!QDir().mkpath(user_config_dir)) { // TODO: Maybe warn user return; } } } void MainWindow::UpdateWindowTitle(QString filename) { if(filename=="") { this->setWindowTitle(QString().sprintf("%s v%s",APP_TITLE,APP_VERSION)); } else { this->setWindowTitle(QString().sprintf("%s v%s - %s", APP_TITLE, APP_VERSION, filename.toLocal8Bit().constData())); } } void MainWindow::UpdateDataInterpreter(int hex_offset) { QDateTime date_time; const char *p_data; int remaining_data_len; // Remove all old values from data interpreter this->p_data_interpreter->ClearValues(); // Calculate how many bytes are remainig after current offset remaining_data_len=this->selected_key_value.size()-hex_offset; if(!remaining_data_len>0) { // Nothing to show return; } // Get pointer to data at current offset p_data=this->selected_key_value.constData(); p_data+=hex_offset; //#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) //#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) //#define rotl64(x,n) (((x) << n) | ((x) >> (64 - n))) //#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) if(remaining_data_len>=1) { this->p_data_interpreter->AddValue("int8:", RegistryHive::KeyValueToString( this->selected_key_value, "int8", hex_offset)); this->p_data_interpreter->AddValue("uint8:", RegistryHive::KeyValueToString( this->selected_key_value, "uint8", hex_offset)); } if(remaining_data_len>=2) { this->p_data_interpreter->AddValue("int16:", RegistryHive::KeyValueToString( this->selected_key_value, "int16", hex_offset)); this->p_data_interpreter->AddValue("uint16:", RegistryHive::KeyValueToString( this->selected_key_value, "uint16", hex_offset)); } if(remaining_data_len>=4) { this->p_data_interpreter->AddValue("int32:", RegistryHive::KeyValueToString( this->selected_key_value, "int32", hex_offset)); this->p_data_interpreter->AddValue("uint32:", RegistryHive::KeyValueToString( this->selected_key_value, "uint32", hex_offset)); - this->p_data_interpreter->AddValue("Unixtime:", + this->p_data_interpreter->AddValue("unixtime:", RegistryHive::KeyValueToString( this->selected_key_value, "unixtime", hex_offset)); } if(remaining_data_len>=8) { this->p_data_interpreter->AddValue("int64:", RegistryHive::KeyValueToString( this->selected_key_value, "int64", hex_offset)); this->p_data_interpreter->AddValue("uint64:", RegistryHive::KeyValueToString( this->selected_key_value, "uint64", hex_offset)); - this->p_data_interpreter->AddValue("Filetime:", + this->p_data_interpreter->AddValue("filetime64:", RegistryHive::KeyValueToString( this->selected_key_value, "filetime", hex_offset)); } //#undef rotl32 //#undef rotl64 } void MainWindow::UpdateDataReporterMenu() { int i=0,ii=0; QMenu *p_category_entry; QAction *p_report_entry; QStringList categories=this->p_data_reporter->GetAvailableReportCategories(); QStringList reports; for(i=0;iui->MenuReports->addMenu(categories.value(i)); // Now add category reports reports=this->p_data_reporter->GetAvailableReports(categories.value(i)); for(ii=0;iiaddAction(p_report_entry); this->connect(p_report_entry, SIGNAL(triggered()), this, SLOT(SlotReportClicked())); } } } void MainWindow::OpenHive(QString hive_file) { // Update last open location this->last_open_location=hive_file.left(hive_file. lastIndexOf(QDir::separator())); // If another hive is currently open, close it if(this->is_hive_open) this->on_action_Close_hive_triggered(); // Try to open hive if(!this->p_hive->Open(hive_file)) { QMessageBox::critical(this, tr("Error opening hive file"), tr("Unable to open file '%1'").arg(hive_file)); return; } // Create tree model this->p_reg_node_tree_model= new RegistryNodeTreeModel(this->p_hive); this->p_node_tree->setModel(this->p_reg_node_tree_model); this->is_hive_open=true; this->ui->action_Close_hive->setEnabled(true); this->ui->MenuReports->setEnabled(true); this->UpdateWindowTitle(hive_file); } void MainWindow::ParseCommandLineArgs() { QStringList args=qApp->arguments(); - // Return if no args were specified - if(args.count()==1) return; - + // If exactly 1 argument was specified, it should be a hive to open if(args.count()==2) { - // Try to open specified hive file this->OpenHive(args.at(1)); } } diff --git a/trunk/mainwindow.h b/trunk/mainwindow.h index 68d4b6e..f2b0c4b 100644 --- a/trunk/mainwindow.h +++ b/trunk/mainwindow.h @@ -1,119 +1,121 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include "registryhive.h" +#include "registrynodetree.h" #include "registrynodetreemodel.h" +#include "registrykeytable.h" #include "registrykeytablemodel.h" #include "qhexedit/qhexedit.h" #include "datainterpreter.h" #include "datareporter.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_action_Quit_triggered(); void on_action_Open_hive_triggered(); void on_action_Close_hive_triggered(); void on_actionAbout_Qt_triggered(); void on_actionAbout_fred_triggered(); void SlotNodeTreeClicked(QModelIndex index); void SlotKeyTableClicked(QModelIndex index); void SlotKeyTableDoubleClicked(QModelIndex index); void SlotHexEditAddressChanged(int hex_offset); void SlotReportClicked(); private: Ui::MainWindow *ui; QString last_open_location; RegistryHive *p_hive; bool is_hive_open; RegistryNodeTreeModel *p_reg_node_tree_model; RegistryKeyTableModel *p_reg_key_table_model; QByteArray selected_key_value; // Widgets etc... - QTreeView *p_node_tree; - QTableView *p_key_table; + RegistryNodeTree *p_node_tree; + RegistryKeyTable *p_key_table; QWidget *p_hex_edit_widget; QHexEdit *p_hex_edit; QLabel *p_hex_edit_status_bar; DataInterpreter *p_data_interpreter; QVBoxLayout *p_hex_edit_layout; QSplitter *p_horizontal_splitter; QSplitter *p_horizontal_splitter2; QSplitter *p_vertical_splitter; DataReporter *p_data_reporter; /* * CheckUserConfigDir * * Checks for and possibly creates the ~/.fred directory */ void CheckUserConfigDir(); /* * UpdateWindowTitle * * Updates the window title */ void UpdateWindowTitle(QString filename=""); /* * UpdateDataInterpreter * * Update data interpreter */ void UpdateDataInterpreter(int hex_offset); /* * UpdateDataReporterMenu * */ void UpdateDataReporterMenu(); /* * OpenHive * * Open a registry hive */ void OpenHive(QString hive_file); /* * ParseCommandLineArgs * * Parse command line arguments */ void ParseCommandLineArgs(); }; #endif // MAINWINDOW_H diff --git a/trunk/registrykeytable.cpp b/trunk/registrykeytable.cpp new file mode 100644 index 0000000..6fc383a --- /dev/null +++ b/trunk/registrykeytable.cpp @@ -0,0 +1,37 @@ +#include "registrykeytable.h" + +#include + +RegistryKeyTable::RegistryKeyTable(QWidget *p_parent) : QTableView(p_parent) { + // Configure widget + this->setSelectionMode(QAbstractItemView::SingleSelection); + this->setSelectionBehavior(QAbstractItemView::SelectRows); + this->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); +} + +void RegistryKeyTable::setModel(QAbstractItemModel *p_model) { + QTableView::setModel(p_model); + // Resize table rows / columns to fit data + this->resizeColumnsToContents(); + this->horizontalHeader()->stretchLastSection(); +} + +int RegistryKeyTable::sizeHintForColumn(int column) const { + int size_hint=-1; + int i=0; + int item_width=0; + QFontMetrics fm(this->fontMetrics()); + QModelIndex idx; + + if(this->model()==NULL) return -1; + + // Find string that needs the most amount of space + idx=this->model()->index(i,column); + while(idx.isValid()) { + item_width=fm.width(this->model()->data(idx).toString())+10; + if(item_width>size_hint) size_hint=item_width; + idx=this->model()->index(++i,column); + } + + return size_hint; +} diff --git a/trunk/registrykeytable.h b/trunk/registrykeytable.h new file mode 100644 index 0000000..b565a7a --- /dev/null +++ b/trunk/registrykeytable.h @@ -0,0 +1,18 @@ +#ifndef REGISTRYKEYTABLE_H +#define REGISTRYKEYTABLE_H + +#include + +class RegistryKeyTable : public QTableView { + Q_OBJECT + + public: + RegistryKeyTable(QWidget *p_parent=0); + + void setModel(QAbstractItemModel *p_model); + + protected: + int sizeHintForColumn(int column) const; +}; + +#endif // REGISTRYKEYTABLE_H diff --git a/trunk/registrynodetree.cpp b/trunk/registrynodetree.cpp new file mode 100644 index 0000000..f9ba344 --- /dev/null +++ b/trunk/registrynodetree.cpp @@ -0,0 +1,16 @@ +#include "registrynodetree.h" + +#include + +RegistryNodeTree::RegistryNodeTree(QWidget *p_parent) : QTreeView(p_parent) { + // Configure widget + this->setTextElideMode(Qt::ElideNone); +} + +void RegistryNodeTree::setModel(QAbstractItemModel *p_model) { + QTreeView::setModel(p_model); + this->header()->setResizeMode(0,QHeaderView::ResizeToContents); + this->header()->setStretchLastSection(false); +} + +//int RegistryNodeTree::sizeHintForColumn(int column) const {} diff --git a/trunk/registrynodetree.h b/trunk/registrynodetree.h new file mode 100644 index 0000000..93326a4 --- /dev/null +++ b/trunk/registrynodetree.h @@ -0,0 +1,19 @@ +#ifndef REGISTRYNODETREE_H +#define REGISTRYNODETREE_H + +#include +#include + +class RegistryNodeTree : public QTreeView { + Q_OBJECT + + public: + RegistryNodeTree(QWidget *p_parent=0); + + void setModel(QAbstractItemModel *p_model); + + //protected: + // int sizeHintForColumn(int column) const; +}; + +#endif // REGISTRYNODETREE_H diff --git a/trunk/report_templates/SAM_UserAccounts.qs b/trunk/report_templates/SAM_UserAccounts.qs index 7ab402c..94a9616 100644 --- a/trunk/report_templates/SAM_UserAccounts.qs +++ b/trunk/report_templates/SAM_UserAccounts.qs @@ -1,81 +1,81 @@ // See http://windowsir.blogspot.com/2006/08/getting-user-info-from-image.html function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function print_v_info(v_key_value,info_name,str_off) { var offset=Number(RegistryKeyValueToVariant(v_key_value,"uint16",str_off))+0x0cc; var len=Number(RegistryKeyValueToVariant(v_key_value,"uint16",str_off+4))/2; if(len>0) print_table_row(info_name,RegistryKeyValueToVariant(v_key_value,"utf16",offset,len)); } println(""); println(" User Accounts"); println(" "); println("

User accounts

"); // Iterate over all user names var user_names=GetRegistryNodes("\\SAM\\Domains\\Account\\Users\\Names"); for(var i=0;i"); + println("

"); // Print user name println(" ",user_names[i],"
"); println(" "); // Get user rid stored in "default" key var user_rid=GetRegistryKeyValue(String().concat("\\SAM\\Domains\\Account\\Users\\Names\\",user_names[i]),""); user_rid=RegistryKeyTypeToString(user_rid.type); println(" "); // RegistryKeyTypeToString returns the rid prepended with "0x". We have to remove that for further processing user_rid=String(user_rid).substr(2); // Get user's V key and print various infos var v_key=GetRegistryKeyValue(String().concat("\\SAM\\Domains\\Account\\Users\\",user_rid),"V"); print_v_info(v_key.value,"Full name:",0x18); print_v_info(v_key.value,"Comment:",0x24); print_v_info(v_key.value,"Home directory:",0x48); print_v_info(v_key.value,"Home directory drive:",0x54); print_v_info(v_key.value,"Logon script path:",0x60); print_v_info(v_key.value,"Profile path:",0x6c); // Get user's F key and print various infos var f_key=GetRegistryKeyValue(String().concat("\\SAM\\Domains\\Account\\Users\\",user_rid),"F"); print_table_row("Last login time:",RegistryKeyValueToVariant(f_key.value,"filetime",8)); print_table_row("Last pw change:",RegistryKeyValueToVariant(f_key.value,"filetime",24)); print_table_row("Last failed login:",RegistryKeyValueToVariant(f_key.value,"filetime",40)); print_table_row("Account expires:",RegistryKeyValueToVariant(f_key.value,"filetime",32)); print_table_row("Total logins:",RegistryKeyValueToVariant(f_key.value,"uint16",66)); print_table_row("Failed logins:",RegistryKeyValueToVariant(f_key.value,"uint16",64)); var acc_flags=Number(RegistryKeyValueToVariant(f_key.value,"uint16",56)); print(" "); // Get password hint if available var hint=GetRegistryKeyValue(String().concat("\\SAM\\Domains\\Account\\Users\\",user_rid),"UserPasswordHint"); if(typeof hint !== 'undefined') { print_table_row("Password hint:",RegistryKeyValueToVariant(hint.value,"utf16",0)); } // TODO: User group membership println("
RID:",Number(user_rid).toString(10)," (",user_rid,")","
Account flags:"); if(acc_flags&0x0001) print("Disabled "); if(acc_flags&0x0002) print("HomeDirReq "); if(acc_flags&0x0004) print("PwNotReq "); if(acc_flags&0x0008) print("TempDupAcc "); // I don't think this would be useful to show //if(acc_flags&0x0010) print("NormUserAcc "); if(acc_flags&0x0020) print("MnsAcc "); if(acc_flags&0x0040) print("DomTrustAcc "); if(acc_flags&0x0080) print("WksTrustAcc "); if(acc_flags&0x0100) print("SrvTrustAcc "); if(acc_flags&0x0200) print("NoPwExpiry "); if(acc_flags&0x0400) print("AccAutoLock "); println("
"); println("

"); } println(""); diff --git a/trunk/report_templates/SOFTWARE_WindowsVersion.qs b/trunk/report_templates/SOFTWARE_WindowsVersion.qs index 5c301c8..0b28e64 100644 --- a/trunk/report_templates/SOFTWARE_WindowsVersion.qs +++ b/trunk/report_templates/SOFTWARE_WindowsVersion.qs @@ -1,82 +1,82 @@ function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function DecodeProductKey(arr) { //ProductKey is base24 encoded var keychars=new Array("B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9"); var key=new Array(30); var ret=""; var ncur; if(arr.length<66) return ret; arr=arr.mid(52,15); for(var ilbyte=24;ilbyte>=0;ilbyte--) { ncur=0; for(var ilkeybyte=14;ilkeybyte>=0;ilkeybyte--) { ncur=ncur*256^arr[ilkeybyte]; arr[ilkeybyte]=ncur/24; ncur%=24; } ret=keychars[ncur]+ret; if(ilbyte%5==0 && ilbyte!=0) ret="-"+ret; } return ret; } println(""); println(" Windows version info"); println(" "); println("

Windows version info

"); -println("

"); -println(" "); +println("

"); +println("

"); // Windows version sp and build info var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","ProductName"); print(" "); // Build string var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","BuildLab"); print_table_row("Build string:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); // Extended build string var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","BuildLabEx"); print_table_row("Extended build string:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); // Install date var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","InstallDate"); print_table_row("Install date:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"unixtime") : "n/a"); // Owner and Organization info var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","RegisteredOwner"); print_table_row("Registered owner:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","RegisteredOrganization"); print_table_row("Registered organization:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); // Windows ID / Key var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","ProductId"); print_table_row("Product ID:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","DigitalProductId"); if(typeof val !== 'undefined') { var key=DecodeProductKey(val.value); if(key!="BBBBB-BBBBB-BBBBB-BBBBB-BBBBB") print_table_row("Product Key:",key); else print_table_row("Product Key:","n/a (Probably a volume license key was used)"); } else print_table_row("Product Key:","n/a"); // Install directory / Source directory var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","PathName"); print_table_row("Install path:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","SourcePath"); print_table_row("Source path:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); println("
Windows version:",RegistryKeyValueToString(val.value,val.type)); var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","CSDVersion"); if(typeof val !== 'undefined') { print(" ",RegistryKeyValueToString(val.value,val.type)); } var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","CurrentBuildNumber"); if(typeof val !== 'undefined') { print(" build ",RegistryKeyValueToString(val.value,val.type)); } println("
"); println("

"); println(""); diff --git a/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs b/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs index 583fc63..7bfb9b2 100644 --- a/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs +++ b/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs @@ -1,91 +1,91 @@ function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } // Global vars var val; // Get current controlset var cur_controlset=GetRegistryKeyValue("\\Select","Current"); cur_controlset=RegistryKeyValueToString(cur_controlset.value,cur_controlset.type); // Current holds a DWORD value, thus we get a string like 0x00000000, but // control sets are referenced only with the last 3 digits. cur_controlset="ControlSet"+String(cur_controlset).substr(7,3); println(""); println(" Current Network Settings (Tcp/Ip)"); println(" "); println("

Current network settings (Tcp/Ip)

"); -println("

"); -println(" "); +println("

"); +println("

"); print_table_row("Active control set:",cur_controlset); // Computer name val=GetRegistryKeyValue(cur_controlset+"\\Control\\ComputerName\\ComputerName","ComputerName"); print_table_row("Computer name:",RegistryKeyValueToString(val.value,val.type)); println("
"); println("
"); // Iterate over all available network adapters var adapters=GetRegistryNodes(cur_controlset+"\\Services\\Tcpip\\Parameters\\Adapters"); for(var i=0;i"); + println(" "); // Get configuration mode val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"EnableDHCP"); val=Number(RegistryKeyValueToString(val.value,val.type)); if(val) { // DHCP enabled print_table_row("Configuration mode:","DHCP"); // DHCP server val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DhcpServer"); print_table_row("Last used DHCP server:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); // IP address val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DhcpIPAddress"); print_table_row("IP address:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); // Subnet mask val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DhcpSubnetMask"); print_table_row("Subnet mask:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); // Nameserver(s) val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DhcpNameServer"); print_table_row("Nameserver(s):",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); // Default gw val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DhcpDefaultGateway"); print_table_row("Default gateway:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"utf16",0) : ""); // Lease obtained val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"LeaseObtainedTime"); print_table_row("Lease obtained:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"unixtime",0) : ""); // Lease valid until val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"LeaseTerminatesTime"); print_table_row("Lease terminates:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"unixtime",0) : ""); } else { print_table_row("Configuration mode:","Manual"); // IP address val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"IPAddress"); print_table_row("IP address:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"utf16",0) : ""); // Subnet mask val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"SubnetMask"); print_table_row("Subnet mask:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"utf16",0) : ""); // Nameserver // TODO: Has to be validated val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"NameServer"); print_table_row("Nameserver:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"utf16",0) : ""); // Default gw val=GetRegistryKeyValue(cur_controlset+"\\Services\\"+adapter_settings_node,"DefaultGateway"); print_table_row("Default gateway:",(typeof val !== 'undefined') ? RegistryKeyValueToVariant(val.value,"utf16",0) : ""); } println("
"); println("
"); } println("

"); println(""); diff --git a/trunk/report_templates/SYSTEM_SystemTimeInfo.qs b/trunk/report_templates/SYSTEM_SystemTimeInfo.qs index 17af169..1063b7c 100644 --- a/trunk/report_templates/SYSTEM_SystemTimeInfo.qs +++ b/trunk/report_templates/SYSTEM_SystemTimeInfo.qs @@ -1,90 +1,90 @@ function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function ToUTC(num) { var retnum=new Number(num); if(retnum&0x80000000) { retnum=((0xFFFFFFFF-retnum)+1)/60; return "UTC+"+Number(retnum).toString(10); } else { retnum=retnum/60; if(retnum!=0) return "UTC-"+Number(retnum).toString(10); else return "UTC+"+Number(retnum).toString(10); } } // Global vars var val; // Get current controlset var cur_controlset=GetRegistryKeyValue("\\Select","Current"); cur_controlset=RegistryKeyValueToString(cur_controlset.value,cur_controlset.type); // Current holds a DWORD value, thus we get a string like 0x00000000, but // control sets are referenced only with the last 3 digits. cur_controlset="ControlSet"+String(cur_controlset).substr(7,3); println(""); println(" System Time Info"); println(" "); println("

System time info (",cur_controlset,")

"); -println("

"); +println("

"); println(" Time zone info"); -println(" "); +println("
"); // Active time bias val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","ActiveTimeBias"); print_table_row("Active time bias:",(typeof val !== 'undefined') ? ToUTC(RegistryKeyValueToString(val.value,val.type)) : "n/a"); // Std. tz name and bias val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","StandardName"); print_table_row("Std. time zone name:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","StandardBias"); print_table_row("Std. time bias:",(typeof val !== 'undefined') ? ToUTC(RegistryKeyValueToString(val.value,val.type)) : "n/a"); // Daylight tz name and bias val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","DaylightName"); print_table_row("Daylight time zone name:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","DaylightBias"); print_table_row("Daylight time bias:",(typeof val !== 'undefined') ? ToUTC(RegistryKeyValueToString(val.value,val.type)) : "n/a"); println("
"); println("
"); println(" W32Time service info"); -println(" "); +println("
"); // Get W32Time service settings val=GetRegistryKeyValue(cur_controlset+"\\Services\\W32Time","Start"); if(typeof val !== 'undefined') { print(" "); // If service is enabled, get ntp server if(Number(val)<4) { val=GetRegistryKeyValue(cur_controlset+"\\Services\\W32Time\\Parameters","NtpServer"); print_table_row("NTP server(s):",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); } } else print_table_row("Startup method:","n/a"); println("
Startup method:"); val=RegistryKeyValueToString(val.value,val.type); switch(Number(val)) { case 0: print("Boot"); break; case 1: print("System"); break; case 2: print("Automatic"); break; case 3: print("Manual"); break; case 4: print("Disabled"); break; default: print("Unknown"); } println("
"); println("

"); println(""); diff --git a/trunk/report_templates/SYSTEM_UsbStorageDevices.qs b/trunk/report_templates/SYSTEM_UsbStorageDevices.qs index 65b6e5b..ac0e109 100644 --- a/trunk/report_templates/SYSTEM_UsbStorageDevices.qs +++ b/trunk/report_templates/SYSTEM_UsbStorageDevices.qs @@ -1,68 +1,86 @@ // TODO: There is more here. Check http://www.forensicswiki.org/wiki/USB_History_Viewing function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } // Global vars var val; // Preload MountedDevices to possibly identify mount points of USB storage devices var mnt_keys=GetRegistryKeys("\\MountedDevices"); var mnt_values=new Array(); for(var i=0;i"); println(" USB Storage Devices"); println(" "); println("

USB storage devices

"); -println("

"); +println("

"); var storage_roots=GetRegistryNodes(cur_controlset+"\\Enum\\USBSTOR"); for(var i=0;i",storage_roots[i],"
"); var storage_subroots=GetRegistryNodes(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]); for(ii=0;ii"); + println(" "); // If the second character of the unique instance ID is a '&', then the ID was // generated by the system, as the device did not have a serial number. if(String(storage_subroots[ii]).charAt(1)=="&") print_table_row("Unique ID:",storage_subroots[ii]+" (Generated by system)"); else print_table_row("Unique ID:",storage_subroots[ii]); val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"Class"); print_table_row("Class:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"DeviceDesc"); print_table_row("Device description:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"FriendlyName"); print_table_row("Friendly name:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"ParentIdPrefix"); if(typeof val !== 'undefined') { + // Windows XP used the ParentId to link to MountedDevices var parent_id=RegistryKeyValueToString(val.value,val.type); print_table_row("Parent ID prefix:",parent_id); // Find mount point(s) print(" "); - } else print_table_row("Parent ID prefix:","n/a"); + } else { + // Since Vista, Unique ID is used + // Find mount point(s) + print(" "); + } + println("
Mount point(s):"); var br=0; for(var iii=0;iii"); else br=1; print(mnt_keys[iii]); } } + if(br==0) print("n/a"); println("
Mount point(s):"); + var br=0; + for(var iii=0;iii"); + else br=1; + print(mnt_keys[iii]); + } + } + if(br==0) print("n/a"); + println("
"); + println("
"); } } println("

"); println(""); diff --git a/trunk/reporttemplate.cpp b/trunk/reporttemplate.cpp index 8f6ee11..eceb427 100644 --- a/trunk/reporttemplate.cpp +++ b/trunk/reporttemplate.cpp @@ -1,42 +1,54 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "reporttemplate.h" ReportTemplate::ReportTemplate(QString report_category, QString report_name, QString report_template_file) { this->category=report_category; this->name=report_name; this->template_file=report_template_file; } +void ReportTemplate::SetCategory(QString new_category) { + this->category=new_category; +} + +void ReportTemplate::SetName(QString new_name) { + this->name=new_name; +} + +void ReportTemplate::SetFile(QString new_file) { + this->template_file=new_file; +} + QString ReportTemplate::ReportTemplate::Category() { return this->category; } QString ReportTemplate::ReportTemplate::Name() { return this->name; } QString ReportTemplate::ReportTemplate::File() { return this->template_file; } diff --git a/trunk/reporttemplate.h b/trunk/reporttemplate.h index 5acebeb..86624af 100644 --- a/trunk/reporttemplate.h +++ b/trunk/reporttemplate.h @@ -1,42 +1,46 @@ /******************************************************************************* * fred Copyright (c) 2011 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef REPORTTEMPLATE_H #define REPORTTEMPLATE_H #include class ReportTemplate { public: ReportTemplate(QString report_category, QString report_name, QString report_template_file); + void SetCategory(QString new_category); + void SetName(QString new_name); + void SetFile(QString new_file); + QString Category(); QString Name(); QString File(); private: QString category; QString name; QString template_file; }; #endif // REPORTTEMPLATE_H