diff --git a/trunk/dlgreportchooser.cpp b/trunk/dlgreportchooser.cpp index 223fb92..bb95439 100644 --- a/trunk/dlgreportchooser.cpp +++ b/trunk/dlgreportchooser.cpp @@ -1,94 +1,148 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 "dlgreportchooser.h" #include "ui_dlgreportchooser.h" #include #include #include -DlgReportChooser::DlgReportChooser(Reports *p_reps, QWidget *p_parent) +#include + +DlgReportChooser::DlgReportChooser(Reports *p_reps, + QString hive_type_string, + QWidget *p_parent) : QDialog(p_parent), ui(new Ui::DlgReportChooser) { - QTreeWidgetItem *p_category; - QTreeWidgetItem *p_category_report; + QStringList tree_cats; + QString cur_tree_cat; + QTreeWidgetItem *p_tree_cat_widget; + QTreeWidgetItem *p_tree_cat_rep_widget; + QList tree_cat_reports; + ReportTemplate* p_report; + // Init private vars this->ui->setupUi(this); - - // Save values for later use this->p_reports=p_reps; + this->hive_type=hive_type_string; + this->tree_category_items.clear(); + this->selected_reports.clear(); // Populate tree with reports - QStringList report_cats=this->p_reports->GetAvailableReportCategories(); - QListIterator cat_it(report_cats); - QString cur_cat; - while(cat_it.hasNext()) { - cur_cat=cat_it.next(); - p_category=new QTreeWidgetItem(this->ui->TrReports); - p_category->setText(0,cur_cat); - QStringList reports=this->p_reports->GetAvailableReports(cur_cat); - QListIterator rep_it(reports); - while(rep_it.hasNext()) { - p_category_report=new QTreeWidgetItem(p_category); - p_category_report->setText(0,rep_it.next()); - p_category_report->setFlags(Qt::ItemIsEnabled| - Qt::ItemIsSelectable| - Qt::ItemIsUserCheckable); - p_category_report->setCheckState(0,Qt::Unchecked); + tree_cats=this->p_reports->GetAvailableReportCategories(); + QListIterator tree_cat_it(tree_cats); + while(tree_cat_it.hasNext()) { + cur_tree_cat=tree_cat_it.next(); + p_tree_cat_widget=new QTreeWidgetItem(this->ui->TrReports); + p_tree_cat_widget->setText(0,cur_tree_cat); + p_tree_cat_widget->setFlags(Qt::ItemIsEnabled| + Qt::ItemIsUserCheckable| + Qt::ItemIsTristate); + p_tree_cat_widget->setCheckState(0,Qt::Unchecked); + tree_cat_reports=this->p_reports->GetAvailableReports(cur_tree_cat); + QListIterator tree_cat_rep_it(tree_cat_reports); + while(tree_cat_rep_it.hasNext()) { + p_report=tree_cat_rep_it.next(); + + p_tree_cat_rep_widget=new QTreeWidgetItem(p_tree_cat_widget); + // Save pointer to ReportTemplate alongside + p_tree_cat_rep_widget->setData(0, + Qt::UserRole, + QVariant().fromValue(p_report)); + p_tree_cat_rep_widget->setText(0,p_report->Name()); + p_tree_cat_rep_widget->setFlags(Qt::ItemIsEnabled| + Qt::ItemIsSelectable| + Qt::ItemIsUserCheckable); + if(this->hive_type!="UNKNOWN" && this->hive_type==p_report->Hive()) { + p_tree_cat_rep_widget->setCheckState(0,Qt::Checked); + } else { + p_tree_cat_rep_widget->setCheckState(0,Qt::Unchecked); + } } + this->tree_category_items.append(p_tree_cat_widget); } + + // Finally, expand all categories + this->ui->TrReports->expandAll(); } DlgReportChooser::~DlgReportChooser() { delete this->ui; } +QList DlgReportChooser::GetSelectedReports() +{ + return this->selected_reports; +} + void DlgReportChooser::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: this->ui->retranslateUi(this); break; default: break; } } void DlgReportChooser::on_BtnCancel_clicked() { this->reject(); } -void DlgReportChooser::on_TrReports_currentItemChanged(QTreeWidgetItem *current, - QTreeWidgetItem *previous) +void DlgReportChooser::on_TrReports_currentItemChanged( + QTreeWidgetItem *p_current, QTreeWidgetItem *p_previous) { - QString category,name; - - if(current->parent()==NULL) return; - - category=current->parent()->text(0); - name=current->text(0); - QMap report_infos= - this->p_reports->GetReportInfo(category,name); - this->ui->LblAuthor->setText(tr("Author: %1") - .arg(report_infos["report_author"])); - this->ui->LblDesc->setText(tr("Description:\n\n %1") - .arg(report_infos["report_desc"])); + Q_UNUSED(p_previous) + + // If item has no parent, clear labels and return + if(p_current->parent()==NULL) { + this->ui->LblAuthor->clear(); + this->ui->LblDesc->clear(); + return; + } + + // Update labels + this->ui->LblAuthor->setText( + p_current->data(0,Qt::UserRole).value()->Author()); + this->ui->LblDesc->setText( + p_current->data(0,Qt::UserRole).value()->Description()); +} + +void DlgReportChooser::on_BtnGenerate_clicked() { + QTreeWidgetItem *p_cat; + int i; + + // Add selected reports to selected_reports + QListIterator cat_it(this->tree_category_items); + while(cat_it.hasNext()) { + p_cat=cat_it.next(); + for(i=0;ichildCount();i++) { + if(p_cat->child(i)->checkState(0)==Qt::Checked) { + // Get saved pointer to ReportTemplate and append it to selected_reps + this->selected_reports.append(p_cat-> + child(i)->data(0,Qt::UserRole).value()); + } + } + } + + this->accept(); } diff --git a/trunk/dlgreportchooser.h b/trunk/dlgreportchooser.h index 8751723..a8820b7 100644 --- a/trunk/dlgreportchooser.h +++ b/trunk/dlgreportchooser.h @@ -1,53 +1,62 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 DLGREPORTCHOOSER_H #define DLGREPORTCHOOSER_H #include "reports.h" #include +#include #include namespace Ui { class DlgReportChooser; } class DlgReportChooser : public QDialog { Q_OBJECT public: - explicit DlgReportChooser(Reports *p_reps, QWidget *p_parent=0); + explicit DlgReportChooser(Reports *p_reps, + QString hive_type_string, + QWidget *p_parent=0); ~DlgReportChooser(); + QList GetSelectedReports(); + protected: void changeEvent(QEvent *e); private slots: void on_BtnCancel_clicked(); - - void on_TrReports_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_TrReports_currentItemChanged(QTreeWidgetItem *p_current, + QTreeWidgetItem *p_previous); + void on_BtnGenerate_clicked(); private: Ui::DlgReportChooser *ui; Reports *p_reports; + QString hive_type; + QList tree_category_items; + QList selected_reports; }; #endif // DLGREPORTCHOOSER_H diff --git a/trunk/dlgreportchooser.ui b/trunk/dlgreportchooser.ui index 6e4877d..6d023e3 100644 --- a/trunk/dlgreportchooser.ui +++ b/trunk/dlgreportchooser.ui @@ -1,125 +1,209 @@ DlgReportChooser 0 0 - 400 + 599 300 Generate report :/icons/resources/fred.png:/icons/resources/fred.png + + + 0 + 0 + + Available reports 6 0 + + 9 + + + 9 + + + 0 + + + + 0 + 0 + + true 1 + + + 3 + 0 + + + + + 300 + 0 + + Report details + + 0 + + + 9 + + + 0 + + + + + + 50 + false + true + + + + Author: + + + + + 10 + + + + + + + + 50 + false + true + + + + Description: + + + true + + + 10 + Qt::Vertical 20 40 &Cancel Qt::Horizontal 40 20 &Generate + + BtnGenerate + BtnCancel + TrReports + diff --git a/trunk/dlgreportviewer.cpp b/trunk/dlgreportviewer.cpp index a962057..30d5675 100644 --- a/trunk/dlgreportviewer.cpp +++ b/trunk/dlgreportviewer.cpp @@ -1,88 +1,107 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 "dlgreportviewer.h" #include "ui_dlgreportviewer.h" #include #include +#include +#include +#include DlgReportViewer::DlgReportViewer(QString &report_data, QWidget *p_parent) : QMainWindow(p_parent,Qt::Dialog | Qt::Popup), ui(new Ui::DlgReportViewer) { // Init local vars ui->setupUi(this); this->p_local_event_loop=NULL; + this->orig_report_data=report_data; // Set report content this->ui->WebView->setHtml(report_data); // Set dialog title based on report content title QString report_title=this->ui->WebView->title(); - if(report_title.isEmpty()) this->setWindowTitle("Report Viewer"); - else this->setWindowTitle(report_title.prepend("Report Viewer : ")); + this->setWindowTitle("Report Viewer"); } DlgReportViewer::~DlgReportViewer() { delete ui; if(this->p_local_event_loop!=NULL) this->p_local_event_loop->exit(); } void DlgReportViewer::changeEvent(QEvent *e) { QMainWindow::changeEvent(e); switch(e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void DlgReportViewer::closeEvent(QCloseEvent *event) { // Make sure we exit the local event loop on exit if(this->p_local_event_loop!=NULL) { this->p_local_event_loop->exit(); this->p_local_event_loop=NULL; } event->accept(); } void DlgReportViewer::exec() { // Create local event loop this->p_local_event_loop=new QEventLoop(this); // Show window and enter loop this->show(); this->p_local_event_loop->exec(); } void DlgReportViewer::on_action_Print_triggered() { // Print report QPrinter printer; QPrintDialog *p_dlg_print=new QPrintDialog(&printer); if(p_dlg_print->exec()==QDialog::Accepted) { this->ui->WebView->print(&printer); } delete p_dlg_print; } void DlgReportViewer::on_action_Close_triggered() { this->close(); } + +void DlgReportViewer::on_action_Save_triggered() { + QString filename=QFileDialog::getSaveFileName(this, + tr("Save report as"), + "", + "ODF file (*.odf)"); + if(filename!="") { + QTextDocument *p_doc=new QTextDocument(this); + p_doc->setHtml(this->orig_report_data); + QTextDocumentWriter *p_doc_writer=new QTextDocumentWriter(filename); + p_doc_writer->setFormat(QByteArray("ODF")); + p_doc_writer->write(p_doc); + delete p_doc_writer; + delete p_doc; + } +} diff --git a/trunk/dlgreportviewer.h b/trunk/dlgreportviewer.h index 88c182f..89fc1d5 100644 --- a/trunk/dlgreportviewer.h +++ b/trunk/dlgreportviewer.h @@ -1,56 +1,59 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 DLGREPORTVIEWER_H #define DLGREPORTVIEWER_H #include #include #include namespace Ui { class DlgReportViewer; } class DlgReportViewer : public QMainWindow { Q_OBJECT public: explicit DlgReportViewer(QString &report_data, QWidget *p_parent=0); ~DlgReportViewer(); void exec(); protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent *event); private slots: void on_action_Print_triggered(); void on_action_Close_triggered(); -private: + void on_action_Save_triggered(); + + private: Ui::DlgReportViewer *ui; QEventLoop *p_local_event_loop; + QString orig_report_data; }; #endif // DLGREPORTVIEWER_H diff --git a/trunk/dlgreportviewer.ui b/trunk/dlgreportviewer.ui index 8e90a91..20a6ff9 100644 --- a/trunk/dlgreportviewer.ui +++ b/trunk/dlgreportviewer.ui @@ -1,82 +1,83 @@ DlgReportViewer Qt::NonModal 0 0 605 497 :/icons/resources/fred.png:/icons/resources/fred.png - - + + about:blank 0 0 605 - 27 + 29 &File + - - - &Save - - &Print &Close + + + &Save + + QWebView QWidget
QtWebKit/QWebView
diff --git a/trunk/mainwindow.cpp b/trunk/mainwindow.cpp index 7ddfe45..22d10e2 100644 --- a/trunk/mainwindow.cpp +++ b/trunk/mainwindow.cpp @@ -1,599 +1,637 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 #ifndef __MINGW32__ #define FRED_REPORT_TEMPLATE_DIR "/usr/share/fred/report_templates/" #else #define FRED_REPORT_TEMPLATE_DIR ".\\report_templates\\" #endif #endif #include #include #include #include #include #include +#include + #include "mainwindow.h" #include "ui_mainwindow.h" #include "dlgabout.h" #include "dlgkeydetails.h" #include "dlgreportchooser.h" #include "dlgreportviewer.h" #include "dlgsearch.h" #include "compileinfo.h" +/******************************************************************************* + * Public + ******************************************************************************/ + MainWindow::MainWindow(ArgParser *p_arg_parser) : QMainWindow(0), ui(new Ui::MainWindow) { ui->setupUi(this); // Initialize private vars this->p_args=p_arg_parser; this->p_hive=new RegistryHive(this); this->is_hive_open=false; this->p_reg_node_tree_model=NULL; this->p_reg_node_tree_model_proxy=NULL; this->p_reg_key_table_model=NULL; this->p_search_thread=NULL; this->search_result_widgets.clear(); // 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 RegistryNodeTree(this->p_horizontal_splitter); this->p_vertical_splitter=new QSplitter(this->p_horizontal_splitter); this->p_vertical_splitter->setOrientation(Qt::Vertical); this->p_key_table=new RegistryKeyTable(this->p_vertical_splitter); this->p_tab_widget=new TabWidget(this->p_vertical_splitter); this->p_hex_edit_widget=new HexEditWidget(); // Add hexedit page to tab_widget this->p_tab_widget->addTab(this->p_hex_edit_widget,tr("Hex viewer")); // Add widgets to their splitters this->p_vertical_splitter->addWidget(this->p_key_table); this->p_vertical_splitter->addWidget(this->p_tab_widget); 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 tab_widget_policy=this->p_tab_widget->sizePolicy(); tab_widget_policy.setVerticalStretch(2); tab_widget_policy.setHorizontalStretch(200); this->p_tab_widget->setSizePolicy(tab_widget_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_node_tree, SIGNAL(CurrentItemChanged(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_key_table, SIGNAL(CurrentItemChanged(QModelIndex)), this, SLOT(SlotKeyTableClicked(QModelIndex))); this->connect(this->p_tab_widget, SIGNAL(tabCloseRequested(int)), this, SLOT(SlotTabCloseButtonClicked(int))); // Add central widget this->setCentralWidget(this->p_horizontal_splitter); this->centralWidget()->setContentsMargins(4,4,4,0); // Set window title this->UpdateWindowTitle(); // Set last open location to home dir this->last_open_location=QDir::homePath(); /* // Load report templates 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(); */ // Load report templates this->p_reports=new Reports(); // Load reports from system wide include dir this->p_reports->LoadReportTemplates(FRED_REPORT_TEMPLATE_DIR); // Load user's report templates this->p_reports->LoadReportTemplates(QDir::homePath() .append(QDir::separator()) .append(".fred") .append(QDir::separator()) .append("report_templates")); // Finally, react on some command line arguments if(this->p_args->IsSet("maximized")) { this->setWindowState(Qt::WindowMaximized); } if(this->p_args->IsSet("fullscreen")) { this->setWindowState(Qt::WindowFullScreen); } if(this->p_args->IsSet("hive-file")) { this->OpenHive(this->p_args->GetArgVal("hive-file")); } } MainWindow::~MainWindow() { if(this->is_hive_open) { this->p_hive->Close(); } delete ui; } +/******************************************************************************* + * Private slots + ******************************************************************************/ + 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) { // Remove search results while(this->p_tab_widget->count()>1) { this->p_tab_widget->removeTab(this->p_tab_widget->count()-1); delete this->search_result_widgets.at(this->p_tab_widget->count()-1); this->search_result_widgets.removeLast(); } // Delete models if(this->p_reg_node_tree_model!=NULL) { this->p_node_tree->setModel(NULL); delete this->p_reg_node_tree_model_proxy; delete this->p_reg_node_tree_model; this->p_reg_node_tree_model_proxy=NULL; 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_widget->SetData(QByteArray()); this->p_hex_edit_widget->setEnabled(false); // Close hive this->p_hive->Close(); this->is_hive_open=false; this->ui->action_Close_hive->setEnabled(false); this->ui->ActionSearch->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::on_ActionSearch_triggered() { DlgSearch dlg_search(this); if(dlg_search.exec()==QDialog::Accepted) { // Create search thread and connect needed signals/slots this->p_search_thread=new ThreadSearch(this); // Add new search widget to tabwidget and to internal widget list SearchResultWidget *p_search_widget= new SearchResultWidget(this->p_tab_widget); p_search_widget->setEnabled(false); this->search_result_widgets.append(p_search_widget); this->connect(p_search_widget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(SlotSearchResultWidgetDoubleClicked(QModelIndex))); this->p_tab_widget->addTab(p_search_widget,tr("Search results"),true); this->p_tab_widget->setCurrentIndex(this->p_tab_widget->count()-1); // Connect search thread to result widget this->connect(this->p_search_thread, SIGNAL(SignalFoundMatch(ThreadSearch::eMatchType, QString,QString,QString)), p_search_widget, SLOT(SlotFoundMatch(ThreadSearch::eMatchType, QString,QString,QString))); this->connect(this->p_search_thread, SIGNAL(finished()), this, SLOT(SlotSearchFinished())); this->connect(this->p_search_thread, SIGNAL(finished()), p_search_widget, SLOT(SlotSearchFinished())); // Start searching this->ui->ActionSearch->setEnabled(false); p_search_thread->Search(this->p_hive->Filename(), dlg_search.Keywords(), dlg_search.SearchNodeNames(), dlg_search.SearchKeyNames(), dlg_search.SearchKeyValues()); } } +void MainWindow::on_ActionGenerateReport_triggered() { + DlgReportChooser dlg_repchooser(this->p_reports, + this->p_hive->HiveTypeToString( + this->p_hive->HiveType()), + this); + if(dlg_repchooser.exec()==QDialog::Accepted) { + QList selected_reports; + + // Get selected report + selected_reports=dlg_repchooser.GetSelectedReports(); + if(selected_reports.isEmpty()) return; + + // Generate report(s) + QString report_result=""; + if(this->p_reports->GenerateReport(this->p_hive, + selected_reports, + report_result, + false)) + { + // Report generation was successfull, show reports + DlgReportViewer *p_dlg_report_view=new DlgReportViewer(report_result, + this); + p_dlg_report_view->exec(); + delete p_dlg_report_view; + } else { + // TODO: Inform user + qDebug()<<"ERROR: "<p_reg_node_tree_model_proxy->mapToSource(index); // Built node path node_path=this->p_reg_node_tree_model->GetNodePath(index); // Create table model and attach it to the table view if(this->p_reg_key_table_model!=NULL) { // If a previous model was set, delete it and clear hexedit etc... this->p_key_table->setModel(NULL); delete this->p_reg_key_table_model; this->p_hex_edit_widget->SetData(QByteArray()); } this->p_reg_key_table_model=new RegistryKeyTableModel(this->p_hive,node_path); this->p_key_table->setModel(this->p_reg_key_table_model); // Set focus back to nodetree to be able to navigate with keyboard this->p_node_tree->setFocus(); } +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_widget->SetData(this->selected_key_value); + // Set focus back to nodetree to be able to navigate with keyboard + this->p_key_table->setFocus(); +} + 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();ThreadSearch 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_widget->SetData(this->selected_key_value); - // Set focus back to nodetree to be able to navigate with keyboard - this->p_key_table->setFocus(); -} - /* 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::SlotSearchFinished() { delete this->p_search_thread; this->p_search_thread=NULL; this->ui->ActionSearch->setEnabled(true); // Enable result widget this->search_result_widgets.last()->setEnabled(true); } void MainWindow::SlotSearchResultWidgetDoubleClicked(QModelIndex index) { SearchResultWidget *p_sender; QString path; QString match_type; QString value; QString key=""; int i; if(!index.isValid()) return; // Get pointer to sender p_sender=(SearchResultWidget*)QObject::sender(); // Get path and matchtype path=p_sender->item(index.row(),0)->text(); match_type=p_sender->item(index.row(),1)->text(); value=p_sender->item(index.row(),2)->text(); if(match_type==tr("Node name")) { // Node name is not part of path. Add it if(path=="\\") path.append(value); else path.append("\\").append(value); } else if(match_type==tr("Key name")) { // Key name is stored in value key=value; } else if(match_type==tr("Key value")) { // Key name is part of path. Save and remove it QStringList nodes=path.split("\\",QString::SkipEmptyParts); key=nodes.at(nodes.count()-1); // Remove \ from path path.chop(key.length()+1); } // Expand treeview to correct node QList indexes= this->p_reg_node_tree_model->GetIndexListOf(path); for(i=0;ip_reg_node_tree_model_proxy-> mapFromSource(indexes.at(i))); this->p_node_tree->expand(indexes.at(i)); } if(indexes.count()>0) { // Scroll to last expanded node, select it and update widgets this->p_node_tree->scrollTo(indexes.at(indexes.count()-1), QAbstractItemView::PositionAtCenter); this->p_node_tree->selectionModel()->clear(); this->p_node_tree->selectionModel()-> select(indexes.at(indexes.count()-1), QItemSelectionModel::Select); // TODO: This does not work!! this->SlotNodeTreeClicked(indexes.at(indexes.count()-1)); } // Select correct key if search matched on keay name / value if(key!="") { int row=this->p_reg_key_table_model->GetKeyRow(key); this->p_key_table->clearSelection(); this->p_key_table->scrollTo(this->p_reg_key_table_model->index(row,0), QAbstractItemView::PositionAtCenter); this->p_key_table->selectRow(row); this->SlotKeyTableClicked(this->p_reg_key_table_model->index(row,0)); } } void MainWindow::SlotTabCloseButtonClicked(int index) { // Delete tab widget and remove tab this->p_tab_widget->removeTab(index); delete this->search_result_widgets.at(index-1); this->search_result_widgets.removeAt(index-1); } +/******************************************************************************* + * Private + ******************************************************************************/ + 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("%1 v%2").arg(APP_TITLE,APP_VERSION)); } else { this->setWindowTitle(QString("%1 v%2 - %3").arg(APP_TITLE, APP_VERSION, filename.toLocal8Bit() .constData())); } } /* 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 & proxy this->p_reg_node_tree_model=new RegistryNodeTreeModel(this->p_hive); this->p_reg_node_tree_model_proxy=new RegistryNodeTreeModelProxy(this); //this->p_reg_node_tree_model_proxy->setDynamicSortFilter(true); this->p_reg_node_tree_model_proxy-> setSourceModel(this->p_reg_node_tree_model); this->p_node_tree->setModel(this->p_reg_node_tree_model_proxy); this->is_hive_open=true; this->ui->action_Close_hive->setEnabled(true); this->ui->ActionSearch->setEnabled(true); this->ui->MenuReports->setEnabled(true); // Enable data interpreter this->p_hex_edit_widget->setEnabled(true); this->UpdateWindowTitle(hive_file); } - -void MainWindow::on_ActionGenerateReport_triggered() { - DlgReportChooser dlg_repchooser(this->p_reports,this); - if(dlg_repchooser.exec()==QDialog::Accepted) { - - } -} diff --git a/trunk/mainwindow.h b/trunk/mainwindow.h index 38de0c8..e20238e 100644 --- a/trunk/mainwindow.h +++ b/trunk/mainwindow.h @@ -1,131 +1,130 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 #include #include #include #include #include #include #include "argparser.h" #include "registryhive.h" #include "registrynodetree.h" #include "registrynodetreemodel.h" #include "registrynodetreemodelproxy.h" #include "registrykeytable.h" #include "registrykeytablemodel.h" #include "hexeditwidget.h" //#include "datareporter.h" #include "reports.h" #include "threadsearch.h" #include "searchresultwidget.h" #include "tabwidget.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(ArgParser *p_arg_parser); ~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 on_ActionSearch_triggered(); + void on_ActionGenerateReport_triggered(); void SlotNodeTreeClicked(QModelIndex index); void SlotKeyTableClicked(QModelIndex index); void SlotKeyTableDoubleClicked(QModelIndex index); // void SlotReportClicked(); void SlotSearchFinished(); void SlotSearchResultWidgetDoubleClicked(QModelIndex index); void SlotTabCloseButtonClicked(int index); - void on_ActionGenerateReport_triggered(); - private: Ui::MainWindow *ui; ArgParser *p_args; QString last_open_location; RegistryHive *p_hive; bool is_hive_open; QByteArray selected_key_value; QList search_result_widgets; // Models RegistryNodeTreeModel *p_reg_node_tree_model; RegistryNodeTreeModelProxy *p_reg_node_tree_model_proxy; RegistryKeyTableModel *p_reg_key_table_model; // Widgets etc... RegistryNodeTree *p_node_tree; RegistryKeyTable *p_key_table; TabWidget *p_tab_widget; HexEditWidget *p_hex_edit_widget; QSplitter *p_horizontal_splitter; QSplitter *p_vertical_splitter; // DataReporter *p_data_reporter; Reports *p_reports; // Threads ThreadSearch *p_search_thread; /* * CheckUserConfigDir * * Checks for and possibly creates the ~/.fred directory */ void CheckUserConfigDir(); /* * UpdateWindowTitle * * Updates the window title */ void UpdateWindowTitle(QString filename=""); /* * UpdateDataReporterMenu * */ // void UpdateDataReporterMenu(); /* * OpenHive * * Open a registry hive */ void OpenHive(QString hive_file); }; #endif // MAINWINDOW_H diff --git a/trunk/mainwindow.ui b/trunk/mainwindow.ui index 4fe3b89..88d50fd 100644 --- a/trunk/mainwindow.ui +++ b/trunk/mainwindow.ui @@ -1,154 +1,154 @@ MainWindow 0 0 508 317 0 0 0 0 MainWindow :/icons/resources/fred.png:/icons/resources/fred.png 0 0 508 - 27 + 29 &File &Help false &Reports &Edit &Open hive Ctrl+O false Close hive &Quit Ctrl+Q About Qt About fred false &Search Ctrl+S false &Preferences true Generate report Reload report templates diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp index fdf90bc..a11abea 100644 --- a/trunk/registryhive.cpp +++ b/trunk/registryhive.cpp @@ -1,628 +1,701 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 "registryhive.h" #include #include #include #include // TODO: __WORDSIZE is not defined under mingw and I currently have no idea how // to identify a 64bit windows #ifndef __WORDSIZE #define __WORDSIZE 32 #endif #if __WORDSIZE == 64 #define EPOCH_DIFF 0x19DB1DED53E8000 #else #define EPOCH_DIFF 0x19DB1DED53E8000LL #endif /* * RegistryHive */ RegistryHive::RegistryHive(QObject *p_parent) : QObject(p_parent) { this->erro_msg=""; this->is_error=false; this->hive_file=""; this->p_hive=NULL; this->is_hive_open=false; } /* * ~RegistryHive */ RegistryHive::~RegistryHive() { if(this->is_hive_open) this->Close(); } /* * Error */ bool RegistryHive::Error() { return this->is_error; } /* * GetErrorMsg */ QString RegistryHive::GetErrorMsg() { QString msg=this->erro_msg; this->erro_msg=""; this->is_error=false; return msg; } /* * Open */ bool RegistryHive::Open(QString file, bool read_only) { if(this->is_hive_open) return false; // Open hive file this->p_hive=hivex_open(file.toAscii().constData(), read_only ? 0 : HIVEX_OPEN_WRITE); if(this->p_hive==NULL) return false; // Set local vars this->hive_file=file; this->is_hive_open=true; return true; } /* * Close */ bool RegistryHive::Close(bool commit_changes) { if(this->is_hive_open) { if(commit_changes) { // Commit changes before closing hive. // TODO: Maybe it would be more secure to commit changes to a new file and // then move it over the original one. hivex_commit(this->p_hive,NULL,0); } // As hivex_close will _ALWAYS_ free the handle, we don't need the following // values anymore this->hive_file=""; this->is_hive_open=false; // Close hive if(hivex_close(this->p_hive)!=0) return false; } return true; } +/* + * Filename + */ QString RegistryHive::Filename() { if(this->is_hive_open) return this->hive_file; return QString(); } +/* + * HiveType + */ +RegistryHive::teHiveType RegistryHive::HiveType() { + // Check for SYSTEM hive + if(this->PathExists("\\Select") && this->PathExists("\\MountedDevices")) + return RegistryHive::eHiveType_SYSTEM; + // Check for SOFTWARE hive + if(this->PathExists("\\Microsoft\\Windows\\CurrentVersion") && + this->PathExists("\\Microsoft\\Windows NT\\CurrentVersion")) + return RegistryHive::eHiveType_SOFTWARE; + // Check for SAM + if(this->PathExists("SAM\\Domains\\Account\\Users")) + return RegistryHive::eHiveType_SAM; + // Check for SECURITY + if(this->PathExists("\\Policy\\Accounts") && + this->PathExists("\\Policy\\PolAdtEv")) + return RegistryHive::eHiveType_SECURITY; + // Check for NTUSER.DAT + if(this->PathExists("\\Software\\Microsoft\\Windows\\CurrentVersion")) + return RegistryHive::eHiveType_NTUSER; + // Unknown hive + return RegistryHive::eHiveType_UNKNOWN; +} + +/* + * HiveTypeToString + */ +QString RegistryHive::HiveTypeToString(teHiveType hive_type) { + switch(hive_type) { + case RegistryHive::eHiveType_SYSTEM: + return "SYSTEM"; + break; + case RegistryHive::eHiveType_SOFTWARE: + return "SOFTWARE"; + break; + case RegistryHive::eHiveType_SAM: + return "SAM"; + break; + case RegistryHive::eHiveType_SECURITY: + return "SECURITY"; + break; + case RegistryHive::eHiveType_NTUSER: + return "NTUSER"; + break; + default: + return "UNKNOWN"; + } +} + /* * GetNodes */ QMap RegistryHive::GetNodes(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetNodes */ QMap RegistryHive::GetNodes(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len) { hive_node_h parent_node; hive_value_h hive_key; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QByteArray(); // Get key handle hive_key=hivex_node_get_value(this->p_hive, parent_node,key.toAscii().constData()); if(hive_key==0) { this->SetError(tr("Unable to get key handle!")); *p_value_len=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len) { if(hive_key==0) { this->SetError(tr("Invalid key handle specified!")); *p_value_type=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(QString path) { hive_node_h node; // Get handle to last node in path if(!this->GetNodeHandle(path,&node)) { this->SetError(tr("Unable to get node handle!")); return 0; } // Get and return node's last modification timestamp return this->GetNodeModTime(node); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(int node) { if(node==0) { this->SetError(tr("Invalid node handle specified!")); return 0; } // Get and return key's last modification timestamp return hivex_node_timestamp(this->p_hive,node); } /* * KeyValueToString */ QString RegistryHive::KeyValueToString(QByteArray value, int value_type) { QString ret=""; int i=0; #define ToHexStr() { \ for(i=0;i0) { // Nothing to show return QString(); } // Get pointer to data at specified offset p_data=key_value.constData(); p_data+=offset; // TODO: This will fail on platforms with different endianness! #define bswap_16(value) ((((value) & 0xff) << 8) | ((value) >> 8)) #define bswap_32(value) \ (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ (uint32_t)bswap_16((uint16_t)((value) >> 16))) #define bswap_64(value) \ (((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) << 32) | \ (uint64_t)bswap_32((uint32_t)((value) >> 32))) \ // ConvertFull name if(format=="int8" && remaining_data_len>=1) { ret=QString().sprintf("%d",*(int8_t*)p_data); } else if(format=="uint8" && remaining_data_len>=1) { ret=QString().sprintf("%u",*(uint8_t*)p_data); } else if(format=="int16" && remaining_data_len>=2) { int16_t val=*(int16_t*)p_data; if(little_endian) ret=QString().sprintf("%d",val); else ret=QString().sprintf("%d",bswap_16(val)); } else if(format=="uint16" && remaining_data_len>=2) { uint16_t val=*(uint16_t*)p_data; if(little_endian) ret=QString().sprintf("%u",val); else ret=QString().sprintf("%u",bswap_16(val)); } else if(format=="int32" && remaining_data_len>=4) { int32_t val=*(int32_t*)p_data; if(little_endian) ret=QString().sprintf("%d",val); else ret=QString().sprintf("%d",bswap_32(val)); } else if(format=="uint32" && remaining_data_len>=4) { uint32_t val=*(uint32_t*)p_data; if(little_endian) ret=QString().sprintf("%u",val); else ret=QString().sprintf("%u",bswap_32(val)); } else if(format=="unixtime" && remaining_data_len>=4) { uint32_t val=*(uint32_t*)p_data; if(!little_endian) val=bswap_32(val); if(val==0) { ret="n/a"; } else { QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(val); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } } else if(format=="int64" && remaining_data_len>=8) { int64_t val=*(int64_t*)p_data; if(little_endian) ret=QString("%1").arg(val); else ret=QString("%1").arg((int64_t)bswap_64(val)); } else if(format=="uint64" && remaining_data_len>=8) { uint64_t val=*(uint64_t*)p_data; if(little_endian) ret=QString("%1").arg(val); else ret=QString("%1").arg(bswap_64(val)); /* // TODO: Check how one could implement this } else if(format=="unixtime64" && remaining_data_len>=8) { if(*(uint64_t*)p_data==0) { ret="n/a"; } else { uint64_t secs=*(uint64_t*)p_data; QDateTime date_time; date_time.setTimeSpec(Qt::UTC); // Set 32bit part of date/time date_time.setTime_t(secs&0xFFFFFFFF); // Now add high 32bit part of date/time date_time.addSecs(secs>>32); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } */ } else if(format=="filetime" && remaining_data_len>=8) { uint64_t val=*(uint64_t*)p_data; if(!little_endian) val=bswap_64(val); if(val==0) { ret="n/a"; } else { // TODO: Warn if >32bit QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(RegistryHive::FiletimeToUnixtime(val)); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } } else if(format=="ascii") { // TODO: This fails bad if the string is not null terminated!! It might be // wise checking for a null char here ret=QString().fromAscii((char*)p_data,length); } else if(format=="utf16" && remaining_data_len>=2) { ret=QString().fromUtf16((ushort*)p_data,length); } else { // Unknown variant type or another error return QString(); } return ret; } /* * KeyTypeToString */ QString RegistryHive::KeyTypeToString(int value_type) { QString ret=""; switch(value_type) { case hive_t_REG_NONE: ret="REG_NONE"; break; case hive_t_REG_SZ: ret="REG_SZ"; break; case hive_t_REG_EXPAND_SZ: ret="REG_EXPAND_SZ"; break; case hive_t_REG_BINARY: ret="REG_BINARY"; break; case hive_t_REG_DWORD: ret="REG_DWORD"; break; case hive_t_REG_DWORD_BIG_ENDIAN: ret="REG_DWORD_BIG_ENDIAN"; break; case hive_t_REG_LINK: ret="REG_LINK"; break; case hive_t_REG_MULTI_SZ: ret="REG_MULTI_SZ"; break; case hive_t_REG_RESOURCE_LIST: ret="REG_RESOURCE_LIST"; break; case hive_t_REG_FULL_RESOURCE_DESCRIPTOR: ret="REG_FULL_RESOURCE_DESC"; break; case hive_t_REG_RESOURCE_REQUIREMENTS_LIST: ret="REG_RESOURCE_REQ_LIST"; break; case hive_t_REG_QWORD: ret="REG_QWORD"; break; default: ret=QString().sprintf("0x%08X",(uint32_t)value_type); } return ret; } /* * FiletimeToUnixtime */ uint64_t RegistryHive::FiletimeToUnixtime(int64_t filetime) { return (unsigned)((filetime-EPOCH_DIFF)/10000000); } /* * SetError */ void RegistryHive::SetError(QString msg) { this->erro_msg=msg; this->is_error=true; } /* * GetNodeHandle */ bool RegistryHive::GetNodeHandle(QString &path, hive_node_h *p_node) { QStringList nodes; int i=0; // Get root node handle *p_node=hivex_root(this->p_hive); if(*p_node==0) { this->SetError(tr("Unable to get root node!")); return false; } if(path!="\\") { // If we aren't listing the root node, we have to get a handle to the // last node in the path. Split path into nodes nodes=path.split('\\',QString::SkipEmptyParts); // Iterate to the correct parent node for(i=0;ip_hive, *p_node, nodes.value(i).toAscii().constData()); if(*p_node==0) { this->SetError(tr("Unable to find node '%1'!").arg(nodes.value(i))); return false; } } } return true; } /* * GetNodesHelper */ QMap RegistryHive::GetNodesHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child nodes hive_node_h *child_nodes=hivex_node_children(this->p_hive,parent_node); if(child_nodes==NULL) { this->SetError( tr("Unable to enumerate child nodes!")); return QMap(); } // Build result keys.clear(); i=0; while(child_nodes[i]) { p_name=hivex_node_name(this->p_hive,child_nodes[i]); if(p_name==NULL) { this->SetError(tr("Unable to get node name!")); free(child_nodes); return QMap(); } keys.insert(QString(p_name),(int)child_nodes[i]); free(p_name); i++; } free(child_nodes); return keys; } /* * GetKeysHelper */ QMap RegistryHive::GetKeysHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child keys hive_value_h *p_keys=hivex_node_values(this->p_hive,parent_node); if(p_keys==NULL) { this->SetError( tr("Unable to enumerate child keys!")); return QMap(); } // Build result list keys.clear(); i=0; while(p_keys[i]) { p_name=hivex_value_key(this->p_hive,p_keys[i]); if(p_name==NULL) { this->SetError(tr("Unable to get key name!")); return QMap(); } keys.insert(QString(p_name),p_keys[i]); free(p_name); i++; } free(p_keys); return keys; } +/* + * GetKeyValueHelper + */ QByteArray RegistryHive::GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len) { QByteArray key_value; char *p_key_value; p_key_value=hivex_value_value(this->p_hive, hive_key, (hive_type*)p_value_type, p_value_len); if(p_key_value==NULL) { this->SetError(tr("Unable to get key value!")); *p_value_type=-1; return QByteArray(); } // Feed QByteArray and free p_key_value key_value=QByteArray(p_key_value,*p_value_len); free(p_key_value); return key_value; } + +/* + * PathExists + */ +bool RegistryHive::PathExists(QString path) { + bool ret; + hive_node_h node; + + ret=this->GetNodeHandle(path,&node); + if(!ret || this->Error()) { + // Clear error and return false + this->GetErrorMsg(); + return false; + } + + return true; +} diff --git a/trunk/registryhive.h b/trunk/registryhive.h index d6b65f2..e2f307f 100644 --- a/trunk/registryhive.h +++ b/trunk/registryhive.h @@ -1,83 +1,95 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 REGISTRYHIVE_H #define REGISTRYHIVE_H #include #include #include class RegistryHive : public QObject { Q_OBJECT public: + typedef enum eHiveType { + eHiveType_UNKNOWN=0, + eHiveType_SYSTEM, + eHiveType_SOFTWARE, + eHiveType_SAM, + eHiveType_SECURITY, + eHiveType_NTUSER + } teHiveType; + explicit RegistryHive(QObject *p_parent=0); ~RegistryHive(); bool Error(); QString GetErrorMsg(); bool Open(QString file, bool read_only=true); bool Close(bool commit_changes=false); QString Filename(); + teHiveType HiveType(); + QString HiveTypeToString(teHiveType hive_type); QMap GetNodes(QString path="\\"); QMap GetNodes(int parent_node=0); QMap GetKeys(QString path="\\"); QMap GetKeys(int parent_node=0); QByteArray GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len); QByteArray GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len); int64_t GetNodeModTime(QString path); int64_t GetNodeModTime(int node); static QString KeyValueToString(QByteArray value, int value_type); static QString KeyValueToString(QByteArray value, QString format, int offset=0, int length=0, bool little_endian=true); static QString KeyTypeToString(int value_type); static uint64_t FiletimeToUnixtime(int64_t filetime); private: QString erro_msg; bool is_error; QString hive_file; hive_h *p_hive; bool is_hive_open; void SetError(QString msg); bool GetNodeHandle(QString &path, hive_node_h *p_node); QMap GetNodesHelper(hive_node_h parent_node); QMap GetKeysHelper(hive_node_h parent_node); QByteArray GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len); + bool PathExists(QString path); }; #endif // REGISTRYHIVE_H diff --git a/trunk/reportengine.cpp b/trunk/reportengine.cpp index 638b60f..8784e26 100644 --- a/trunk/reportengine.cpp +++ b/trunk/reportengine.cpp @@ -1,446 +1,518 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 "reportengine.h" #include #include #include #include /******************************************************************************* * Public ******************************************************************************/ ReportEngine::ReportEngine(RegistryHive *p_hive) : QScriptEngine() { // Init vars this->p_registry_hive=p_hive; this->report_content=""; // Add our constants this->globalObject().setProperty("ENGINE_API_VERSION", FRED_REPORTENGINE_API_VERSION, QScriptValue::ReadOnly| QScriptValue::Undeletable); /* this->globalObject().setProperty("HIVE_FILE", this->p_registry_hive->Filename(), QScriptValue::ReadOnly| QScriptValue::Undeletable); */ // Add our types to engine qScriptRegisterMetaType(this, this->RegistryKeyValueToScript, this->RegistryKeyValueFromScript); this->p_type_byte_array=new ByteArray(this); this->globalObject().setProperty("ByteArray", this->p_type_byte_array->constructor()); // Add our functions // print QScriptValue func_print=this->newFunction(this->Print); this->globalObject().setProperty("print",func_print); // println QScriptValue func_println=this->newFunction(this->PrintLn); this->globalObject().setProperty("println",func_println); - // GetRegistryNodes - QScriptValue func_get_nodes=this->newFunction(this->GetRegistryNodes,1); - func_get_nodes.setData(this->newQObject(this->p_registry_hive)); - this->globalObject().setProperty("GetRegistryNodes",func_get_nodes); - // GetRegistryKeys - QScriptValue func_get_keys=this->newFunction(this->GetRegistryKeys,1); - func_get_keys.setData(this->newQObject(this->p_registry_hive)); - this->globalObject().setProperty("GetRegistryKeys",func_get_keys); - // GetRegistryKeyValue - QScriptValue func_get_key_value=this->newFunction(this->GetRegistryKeyValue, - 2); - func_get_key_value.setData(this->newQObject(this->p_registry_hive)); - this->globalObject().setProperty("GetRegistryKeyValue",func_get_key_value); - // GetRegistryNodeModTime - QScriptValue func_get_node_modt= - this->newFunction(this->GetRegistryNodeModTime,1); - func_get_node_modt.setData(this->newQObject(this->p_registry_hive)); - this->globalObject().setProperty("GetRegistryNodeModTime",func_get_node_modt); + // RegistryKeyValueToString QScriptValue func_value_to_string= this->newFunction(this->RegistryKeyValueToString,2); this->globalObject().setProperty("RegistryKeyValueToString", func_value_to_string); // RegistryKeyValueToVariant QScriptValue func_value_to_variant= this->newFunction(this->RegistryKeyValueToVariant); this->globalObject().setProperty("RegistryKeyValueToVariant", func_value_to_variant); // RegistryKeyTypeToString QScriptValue func_type_to_string= this->newFunction(this->RegistryKeyTypeToString,1); this->globalObject().setProperty("RegistryKeyTypeToString", func_type_to_string); } ReportEngine::~ReportEngine() { delete this->p_type_byte_array; } /* * GetReportTemplateInfo */ QMap ReportEngine::GetReportTemplateInfo(QString file) { - // Open report template file - QFile template_file(file); - if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + // Read template file + QString report_code; + if(!this->GetReportTemplateFileContents(file,report_code)) { QMap error_msg; - error_msg["error"]=QString("Couldn't open report template file '%1'!") - .arg(file); + error_msg["error"]=report_code; return error_msg; } - // Read template file and close it - QString report_code; - QTextStream in(&template_file); - while(!in.atEnd()) report_code.append(in.readLine()).append("\n"); - template_file.close(); - // Evaluate report template script QScriptValue report_result=this->evaluate(report_code,file); if (report_result.isError() || this->hasUncaughtException()) { QMap error_msg; error_msg["error"]=QString("File: %1\n Line: %2\nError: %3") .arg(file) .arg(report_result.property("lineNumber").toInt32()) .arg(report_result.toString()); return error_msg; } // Try to call the fred_report_info script function and return result QScriptValue fred_report_info_func= this->globalObject().property("fred_report_info"); if(!fred_report_info_func.isFunction()) { QMap error_msg; error_msg["error"]= QString("Report template '%1' does not have a fred_report_info function!") .arg(file) .arg(report_result.property("lineNumber").toInt32()) .arg(report_result.toString()); return error_msg; } QScriptValue fred_report_info_res=fred_report_info_func.call(); // TODO: Maybe do more checking on return value return fred_report_info_res.toVariant().toMap(); } +/* + * GenerateReport + */ +bool ReportEngine::GenerateReport(RegistryHive *p_hive, + QString report_file, + QString &report_result, + bool console_mode) +{ + // Clear internal buffer + this->report_content.clear(); + + // Update exported functions + this->UpdateExportedFunctions(p_hive); + + // Read template file + QString report_code; + if(!this->GetReportTemplateFileContents(report_file,report_code)) { + report_result=report_code; + return false; + } + + // Evaluate report template script + QScriptValue script_result=this->evaluate(report_code,report_file); + if (script_result.isError() || this->hasUncaughtException()) { + script_result=QString("File: %1\n Line: %2\nError: %3") + .arg(report_file) + .arg(script_result.property("lineNumber").toInt32()) + .arg(script_result.toString()); + return false; + } + + // Try to call the fred_report_html script function and return result + QScriptValue fred_report_html_func= + this->globalObject().property("fred_report_html"); + if(!fred_report_html_func.isFunction()) { + report_result= + QString("Report template '%1' does not have a fred_report_info function!") + .arg(report_file) + .arg(script_result.property("lineNumber").toInt32()) + .arg(script_result.toString()); + return false; + } + QScriptValue fred_report_html_res=fred_report_html_func.call(); + + // TODO: Maybe do more checking on return value + report_result=this->report_content; + return true; +} + /******************************************************************************* * Public Slots ******************************************************************************/ /******************************************************************************* * Private ******************************************************************************/ /* * Print */ QScriptValue ReportEngine::Print(QScriptContext *context, QScriptEngine *engine) { int i; QString content; // Append all arguments to content for(i=0;iargumentCount();++i) { //if(i>0) content.append(" "); content.append(context->argument(i).toString()); } qobject_cast(engine)->report_content.append(content); return engine->undefinedValue(); } /* * PrintLn */ QScriptValue ReportEngine::PrintLn(QScriptContext *context, QScriptEngine *engine) { int i; QString content; // Append all arguments to content for(i=0;iargumentCount();++i) { //if(i>0) content.append(" "); content.append(context->argument(i).toString()); } qobject_cast(engine)-> report_content.append(content).append("\n"); return engine->undefinedValue(); } /* * GetRegistryNodes */ QScriptValue ReportEngine::GetRegistryNodes(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QMap nodes; QScriptValue ret_nodes; int ii=0; // This function needs one argument, parent node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get nodes nodes=p_hive->GetNodes(context->argument(0).toString()); if(p_hive->Error()) { // Clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } // Build script array ret_nodes=engine->newArray(nodes.count()); QMapIterator i(nodes); while(i.hasNext()) { i.next(); ret_nodes.setProperty(ii++,QScriptValue(i.key())); } return ret_nodes; } /* * GetRegistryKeys */ QScriptValue ReportEngine::GetRegistryKeys(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QMap keys; QScriptValue ret_keys; int ii=0; // This function needs one argument, parent node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get keys keys=p_hive->GetKeys(context->argument(0).toString()); if(p_hive->Error()) { // Clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } // Build script array ret_keys=engine->newArray(keys.count()); QMapIterator i(keys); while(i.hasNext()) { i.next(); ret_keys.setProperty(ii++,QScriptValue(i.key())); } return ret_keys; } /* * RegistryKeyValueToScript */ QScriptValue ReportEngine::RegistryKeyValueToScript(QScriptEngine *engine, const s_RegistryKeyValue &s) { QScriptValue obj=engine->newObject(); obj.setProperty("type",s.type); obj.setProperty("length",s.length); ByteArray *p_byte_array=new ByteArray(engine); obj.setProperty("value",p_byte_array->newInstance(s.value)); return obj; } /* * RegistryKeyValueFromScriptValue */ void ReportEngine::RegistryKeyValueFromScript(const QScriptValue &obj, s_RegistryKeyValue &s) { s.type=obj.property("type").toInt32(); s.length=obj.property("length").toInt32(); // TODO: Don't know if this works, but it probably does ;) s.value=qvariant_cast(obj.property("value").data().toVariant()); } /* * GetRegistryKeyValue */ QScriptValue ReportEngine::GetRegistryKeyValue(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QByteArray key_value; int key_type=0; size_t key_length=0; s_RegistryKeyValue script_key_value; // This function needs two arguments, key path and key name if(context->argumentCount()!=2) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get key value key_value=p_hive->GetKeyValue(context->argument(0).toString(), context->argument(1).toString(), &key_type, &key_length); if(p_hive->Error()) { // Get error message to clear error state p_hive->GetErrorMsg(); // printf("\nError: %s\n",p_hive->GetErrorMsg().toAscii().constData()); return engine->undefinedValue(); } // Save key value to s_RegistryKeyValue struct script_key_value.type=key_type; script_key_value.length=key_length; script_key_value.value=key_value; return ReportEngine::RegistryKeyValueToScript(engine,script_key_value); } /* * RegistryKeyValueToString */ QScriptValue ReportEngine::RegistryKeyValueToString(QScriptContext *context, QScriptEngine *engine) { QByteArray key_value; QString ret=""; // This function needs two arguments, key value and value type if(context->argumentCount()!=2) return engine->undefinedValue(); // Cast ByteArray argument to QByteArray and convert key_value=qvariant_cast(context->argument(0).data().toVariant()); ret=RegistryHive::KeyValueToString(key_value, context->argument(1).toInt32()); return engine->newVariant(ret); } /* * RegistryKeyValueToVariant */ QScriptValue ReportEngine::RegistryKeyValueToVariant(QScriptContext *context, QScriptEngine *engine) { int offset=0; int length=-1; bool little_endian=true; QByteArray key_value; QString format=""; QString ret=""; // This function needs at least two arguments, key value and variant type, // and may have three optional arguments, offset, length and little_endian if(context->argumentCount()<2 || context->argumentCount()>5) { return engine->undefinedValue(); } if(context->argumentCount()==3) { offset=context->argument(2).toInt32(); } if(context->argumentCount()==4) { offset=context->argument(2).toInt32(); length=context->argument(3).toInt32(); } if(context->argumentCount()==5) { offset=context->argument(2).toInt32(); length=context->argument(3).toInt32(); little_endian=(context->argument(4).toInt32()==1); } // Cast ByteArray argument to QByteArray key_value=qvariant_cast(context->argument(0).data().toVariant()); format=context->argument(1).toString(); ret=RegistryHive::KeyValueToString(key_value,format,offset,length,little_endian); return engine->newVariant(ret); } /* * RegistryKeyTypeToString */ QScriptValue ReportEngine::RegistryKeyTypeToString(QScriptContext *context, QScriptEngine *engine) { QString ret=""; // This function needs one argument, key type if(context->argumentCount()!=1) return engine->undefinedValue(); ret=RegistryHive::KeyTypeToString(context->argument(0).toInt32()); return engine->newVariant(ret); } /* * GetRegistryNodeModTime */ QScriptValue ReportEngine::GetRegistryNodeModTime(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; int64_t mod_time=0; // This function needs one argument, node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); mod_time=p_hive->GetNodeModTime(context->argument(0).toString()); if(p_hive->Error()) { // Get error message to clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(RegistryHive::FiletimeToUnixtime(mod_time)); return engine->newVariant(date_time.toString("yyyy/MM/dd hh:mm:ss")); } + +/* + * GetReportTemplateFileContents + */ +bool ReportEngine::GetReportTemplateFileContents(QString file, + QString &contents) +{ + // Open report template file + QFile template_file(file); + if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) { + contents=QString("Couldn't open report template file '%1'!").arg(file); + return false; + } + + // Read template file and close it + contents.clear(); + QTextStream in(&template_file); + while(!in.atEnd()) contents.append(in.readLine()).append("\n"); + template_file.close(); + + return true; +} + +/* + * UpdateExportedFunctions + */ +void ReportEngine::UpdateExportedFunctions(RegistryHive *p_hive) { + this->p_registry_hive=p_hive; + // GetRegistryNodes + QScriptValue func_get_nodes=this->newFunction(this->GetRegistryNodes,1); + func_get_nodes.setData(this->newQObject(this->p_registry_hive)); + this->globalObject().setProperty("GetRegistryNodes",func_get_nodes); + // GetRegistryKeys + QScriptValue func_get_keys=this->newFunction(this->GetRegistryKeys,1); + func_get_keys.setData(this->newQObject(this->p_registry_hive)); + this->globalObject().setProperty("GetRegistryKeys",func_get_keys); + // GetRegistryKeyValue + QScriptValue func_get_key_value=this->newFunction(this->GetRegistryKeyValue, + 2); + func_get_key_value.setData(this->newQObject(this->p_registry_hive)); + this->globalObject().setProperty("GetRegistryKeyValue",func_get_key_value); + // GetRegistryNodeModTime + QScriptValue func_get_node_modt= + this->newFunction(this->GetRegistryNodeModTime,1); + func_get_node_modt.setData(this->newQObject(this->p_registry_hive)); + this->globalObject().setProperty("GetRegistryNodeModTime",func_get_node_modt); +} diff --git a/trunk/reportengine.h b/trunk/reportengine.h index b1bfd10..a66e151 100644 --- a/trunk/reportengine.h +++ b/trunk/reportengine.h @@ -1,81 +1,89 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 REPORTENGINE_H #define REPORTENGINE_H #include #include #include #include #include #include #include #include "registryhive.h" #include "qtscript_types/bytearray.h" #define FRED_REPORTENGINE_API_VERSION 2 class ReportEngine : public QScriptEngine { Q_OBJECT public: struct s_RegistryKeyValue { int type; int length; QByteArray value; }; RegistryHive *p_registry_hive; QString report_content; ReportEngine(RegistryHive *p_hive); ~ReportEngine(); + QMap GetReportTemplateInfo(QString file); + bool GenerateReport(RegistryHive *p_hive, + QString report_file, + QString &report_result, + bool console_mode=true); private: ByteArray *p_type_byte_array; static QScriptValue Print(QScriptContext *context, QScriptEngine *engine); static QScriptValue PrintLn(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryNodes(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryKeys(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToScript(QScriptEngine *engine, const s_RegistryKeyValue &s); static void RegistryKeyValueFromScript(const QScriptValue &obj, s_RegistryKeyValue &s); static QScriptValue GetRegistryKeyValue(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToString(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToVariant(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyTypeToString(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryNodeModTime(QScriptContext *context, QScriptEngine *engine); + + bool GetReportTemplateFileContents(QString file, QString &contents); + void UpdateExportedFunctions(RegistryHive *p_hive); }; Q_DECLARE_METATYPE(ReportEngine::s_RegistryKeyValue) #endif // REPORTENGINE_H diff --git a/trunk/reports.cpp b/trunk/reports.cpp index 2f673e8..15a5b43 100644 --- a/trunk/reports.cpp +++ b/trunk/reports.cpp @@ -1,161 +1,183 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 "reports.h" #include #include #include #include +/******************************************************************************* + * Public + ******************************************************************************/ + Reports::Reports() { this->p_engine=new ReportEngine(NULL); this->report_templates.clear(); } Reports::~Reports() { qDeleteAll(this->report_templates); delete this->p_engine; } void Reports::LoadReportTemplates(QString dir) { QString report_template=""; QString report_category,report_name,report_author,report_desc,report_hive; bool found; int i; ReportTemplate *p_report; // Get all template files in report_templates directory QDir report_dir(dir); QStringList found_report_templates=report_dir. entryList(QStringList()<<"*.qs"); QListIterator it(found_report_templates); while(it.hasNext()) { // Build path to template file report_template=report_dir.path(); report_template.append(QDir::separator()); report_template.append(it.next()); // Get report info QMap report_info=this->p_engine-> GetReportTemplateInfo(report_template); if(report_info.contains("error")) { // TODO: Inform user qDebug()<<"Error in report '"< FRED_REPORTENGINE_API_VERSION) { // TODO: Inform user qDebug()<<"Report '"<report_templates.count();i++) { if(this->report_templates.at(i)->Category()==report_category && this->report_templates.at(i)->Name()==report_name) { found=true; break; } } // Add to or update report template list if(!found) { // Add report to list p_report=new ReportTemplate(report_template, report_category, report_name, report_author, report_desc, report_hive); this->report_templates.append(p_report); } else { // Update report entry p_report=this->report_templates.at(i); p_report->SetFile(report_template); p_report->SetAuthor(report_author); p_report->SetDescription(report_desc); } } } QStringList Reports::GetAvailableReportCategories() { QStringList ret; QString cat; int i; 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 Reports::GetAvailableReports(QString category) { - QStringList ret; +QList Reports::GetAvailableReports(QString category) { + QList 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()); + if(cat==category) ret.append(this->report_templates.value(i)); } - ret.sort(); return ret; } -QMap Reports::GetReportInfo(QString category, QString name) { - QMap ret; - int i=0; +bool Reports::GenerateReport(RegistryHive *p_hive, + QString report_file, + QString &report_result, + bool console_mode) +{ + return this->p_engine->GenerateReport(p_hive, + report_file, + report_result, + console_mode); +} - // Search requested report - for(i=0;ireport_templates.count();i++) { - if(this->report_templates.value(i)->Category()==category && - this->report_templates.value(i)->Name()==name) - { - ret["report_author"]=this->report_templates.value(i)->Author(); - ret["report_desc"]=this->report_templates.value(i)->Description(); - break; - } +bool Reports::GenerateReport(RegistryHive *p_hive, + QList report_list, + QString &report_result, + bool console_mode) +{ + bool ret; + QString res; + + QListIterator rep_it(report_list); + while(rep_it.hasNext()) { + res=""; + ret=this->GenerateReport(p_hive, + rep_it.next()->File(), + res, + console_mode); + if(ret) report_result.append(res); + // TODO: Inform user something didn't work } - return ret; + return true; } + +/******************************************************************************* + * Private + ******************************************************************************/ diff --git a/trunk/reports.h b/trunk/reports.h index 397b89e..13fcba3 100644 --- a/trunk/reports.h +++ b/trunk/reports.h @@ -1,54 +1,53 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 REPORTS_H #define REPORTS_H #include "reporttemplate.h" #include "reportengine.h" #include -#include #include +#include class Reports { public: Reports(); ~Reports(); void LoadReportTemplates(QString dir); QStringList GetAvailableReportCategories(); - QStringList GetAvailableReports(QString category); - QMap GetReportInfo(QString category, QString name); + QList GetAvailableReports(QString category); -/* - QString GenerateReport(RegistryHive *p_hive, - QString report_category, - QString report_name); - QString GenerateReport(RegistryHive *p_hive, - QString report_template, - bool console_mode=false); -*/ + bool GenerateReport(RegistryHive *p_hive, + QString report_file, + QString &report_result, + bool console_mode=false); + bool GenerateReport(RegistryHive *p_hive, + QList report_list, + QString &report_result, + bool console_mode=false); private: QList report_templates; ReportEngine *p_engine; }; #endif // REPORTS_H diff --git a/trunk/reporttemplate.h b/trunk/reporttemplate.h index 2a3fba1..84ff695 100644 --- a/trunk/reporttemplate.h +++ b/trunk/reporttemplate.h @@ -1,58 +1,61 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 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 #include class ReportTemplate { public: ReportTemplate(QString report_template_file, QString report_category, QString report_name, QString report_author, QString report_desc, QString report_hive); void SetFile(QString new_file); void SetCategory(QString new_category); void SetName(QString new_name); void SetAuthor(QString new_author); void SetDescription(QString new_desc); void SetHive(QString new_hive); QString File(); QString Category(); QString Name(); QString Author(); QString Description(); QString Hive(); private: QString template_file; QString category; QString name; QString author; QString description; QString hive; }; +Q_DECLARE_METATYPE(ReportTemplate*) + #endif // REPORTTEMPLATE_H