Page MenuHomePhabricator

No OneTemporary

Size
64 KB
Referenced Files
None
Subscribers
None
diff --git a/trunk/datareporterengine.cpp b/trunk/datareporterengine.cpp
index b3e785a..4b43e68 100644
--- a/trunk/datareporterengine.cpp
+++ b/trunk/datareporterengine.cpp
@@ -1,383 +1,383 @@
/*******************************************************************************
* fred Copyright (c) 2011 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "datareporterengine.h"
#include <QString>
#include <QMap>
#include <QMapIterator>
#include <QStringList>
#include <QDateTime>
DataReporterEngine::DataReporterEngine(RegistryHive *p_hive) : QScriptEngine() {
// Init vars
this->p_registry_hive=p_hive;
this->report_content="";
// Add our types to engine
qScriptRegisterMetaType<s_RegistryKeyValue>(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);
// 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);
/*
// Add RegistryHive object
QScriptValue obj_registry_hive=this->newQObject(this->p_registry_hive);
this->globalObject().setProperty("RegistryHive",obj_registry_hive);
*/
}
DataReporterEngine::~DataReporterEngine() {
delete this->p_type_byte_array;
}
QScriptValue DataReporterEngine::Print(QScriptContext *context,
QScriptEngine *engine)
{
int i;
QString content;
// Append all arguments to content
for(i=0;i<context->argumentCount();++i) {
//if(i>0) content.append(" ");
content.append(context->argument(i).toString());
}
//QScriptValue calleeData=context->callee().data();
//DataReporterEngine *engine=
// qobject_cast<DataReporterEngine*>(calleeData.toQObject());
qobject_cast<DataReporterEngine*>(engine)->report_content.append(content);
return engine->undefinedValue();
}
QScriptValue DataReporterEngine::PrintLn(QScriptContext *context,
QScriptEngine *engine)
{
int i;
QString content;
// Append all arguments to content
for(i=0;i<context->argumentCount();++i) {
//if(i>0) content.append(" ");
content.append(context->argument(i).toString());
}
qobject_cast<DataReporterEngine*>(engine)->
report_content.append(content).append("\n");
return engine->undefinedValue();
}
/*
* GetRegistryNodes
*/
QScriptValue DataReporterEngine::GetRegistryNodes(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
QMap<QString,int> 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<RegistryHive*>(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<QString,int> i(nodes);
while(i.hasNext()) {
i.next();
ret_nodes.setProperty(ii++,QScriptValue(i.key()));
}
return ret_nodes;
}
/*
* GetRegistryKeys
*/
QScriptValue DataReporterEngine::GetRegistryKeys(QScriptContext *context,
QScriptEngine *engine)
{
QScriptValue calleeData;
RegistryHive *p_hive;
QMap<QString,int> 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<RegistryHive*>(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<QString,int> i(keys);
while(i.hasNext()) {
i.next();
ret_keys.setProperty(ii++,QScriptValue(i.key()));
}
return ret_keys;
}
/*
* RegistryKeyValueToScript
*/
QScriptValue DataReporterEngine::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 DataReporterEngine::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<QByteArray>(obj.property("value").data().toVariant());
}
QScriptValue DataReporterEngine::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<RegistryHive*>(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() || key_length==-1) {
- // Get error message ro clear error state
+ if(p_hive->Error()) {
+ // Get error message to clear error state
p_hive->GetErrorMsg();
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 DataReporterEngine::RegistryKeyValueToScript(engine,script_key_value);
}
QScriptValue DataReporterEngine::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<QByteArray>(context->argument(0).data().toVariant());
ret=RegistryHive::KeyValueToString(key_value,
context->argument(1).toInt32());
return engine->newVariant(ret);
}
QScriptValue DataReporterEngine::RegistryKeyValueToVariant(
QScriptContext *context,
QScriptEngine *engine)
{
int offset=0;
int length=0;
QByteArray key_value;
QString variant_type;
int remaining_data_len;
const char *p_data;
QString ret="";
// This function needs at least two arguments, key value and variant type,
// and may have two optional arguments, offset and length
if(context->argumentCount()<2 || context->argumentCount()>4) {
return engine->undefinedValue();
}
if(context->argumentCount()==3) {
offset=context->argument(2).toInt32();
length=-1;
}
if(context->argumentCount()==4) {
offset=context->argument(2).toInt32();
length=context->argument(3).toInt32();
}
// Cast ByteArray argument to QByteArray
key_value=qvariant_cast<QByteArray>(context->argument(0).data().toVariant());
variant_type=context->argument(1).toString();
// Calculate how many bytes are remainig after specified offset
remaining_data_len=key_value.size()-offset;
if(!remaining_data_len>0) {
// Nothing to show
return engine->undefinedValue();
}
// Get pointer to data at specified offset
p_data=key_value.constData();
p_data+=offset;
// ConvertFull name
if(variant_type=="int8" && remaining_data_len>=1) {
ret=QString().sprintf("%d",*(int8_t*)p_data);
} else if(variant_type=="uint8" && remaining_data_len>=1) {
ret=QString().sprintf("%u",*(uint8_t*)p_data);
} else if(variant_type=="int16" && remaining_data_len>=2) {
ret=QString().sprintf("%d",*(int16_t*)p_data);
} else if(variant_type=="uint16" && remaining_data_len>=2) {
ret=QString().sprintf("%u",*(uint16_t*)p_data);
} else if(variant_type=="int32" && remaining_data_len>=4) {
ret=QString().sprintf("%d",*(int32_t*)p_data);
} else if(variant_type=="uint32" && remaining_data_len>=4) {
ret=QString().sprintf("%u",*(uint32_t*)p_data);
} else if(variant_type=="unixtime" && remaining_data_len>=4) {
if(*(uint32_t*)p_data==0) {
ret="n/a";
} else {
QDateTime date_time;
date_time.setTime_t(*(uint32_t*)p_data);
ret=date_time.toString("yyyy/MM/dd hh:mm:ss");
}
} else if(variant_type=="filetime" && remaining_data_len>=8) {
if(*(uint64_t*)p_data==0) {
ret="n/a";
} else {
// TODO: Warn if >32bit
QDateTime date_time;
date_time.setTime_t((*(uint64_t*)p_data-116444736000000000)/10000000);
ret=date_time.toString("yyyy/MM/dd hh:mm:ss");
}
} else if(variant_type=="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(variant_type=="utf16" && remaining_data_len>=2) {
ret=QString().fromUtf16((ushort*)p_data,length);
} else {
// Unknown variant type or another error
return engine->undefinedValue();
}
return engine->newVariant(ret);
}
QScriptValue DataReporterEngine::RegistryKeyTypeToString(
QScriptContext *context,
QScriptEngine *engine)
{
QString ret="";
// This function needs one arguments, key type
if(context->argumentCount()!=1) return engine->undefinedValue();
ret=RegistryHive::KeyTypeToString(context->argument(0).toInt32());
return engine->newVariant(ret);
}
diff --git a/trunk/mainwindow.cpp b/trunk/mainwindow.cpp
index 4858079..7454487 100644
--- a/trunk/mainwindow.cpp
+++ b/trunk/mainwindow.cpp
@@ -1,522 +1,532 @@
/*******************************************************************************
* fred Copyright (c) 2011 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#ifndef FRED_REPORT_TEMPLATE_DIR
#define FRED_REPORT_TEMPLATE_DIR "/usr/share/fred/report_templates/"
#endif
#include <QFileDialog>
#include <QMessageBox>
#include <QStringList>
#include <QDesktopWidget>
#include <QDir>
#include <QSplitter>
#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->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_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) {
delete this->p_reg_node_tree_model;
this->p_reg_node_tree_model=NULL;
}
if(this->p_reg_key_table_model!=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) {
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) {
// 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:",
QString().sprintf("%d",
*(int8_t*)p_data));
this->p_data_interpreter->AddValue("uint8:",
QString().sprintf("%u",
*(uint8_t*)p_data));
}
if(remaining_data_len>=2) {
this->p_data_interpreter->AddValue("int16:",
QString().sprintf("%d",
*(int16_t*)p_data));
this->p_data_interpreter->AddValue("uint16:",
QString().sprintf("%u",
*(uint16_t*)p_data));
}
if(remaining_data_len>=4) {
this->p_data_interpreter->AddValue("int32:",
QString().sprintf("%d",
*(int32_t*)p_data));
this->p_data_interpreter->AddValue("uint32:",
QString().sprintf("%u",
*(uint32_t*)p_data));
date_time.setTime_t(*(uint32_t*)p_data);
this->p_data_interpreter->AddValue("Unixtime:",
date_time.
toString("yyyy/MM/dd hh:mm:ss"));
}
if(remaining_data_len>=8) {
+#if __WORDSIZE == 64
this->p_data_interpreter->AddValue("int64:",
- QString().sprintf("%d",
+ QString().sprintf("%ld",
*(int64_t*)p_data));
this->p_data_interpreter->AddValue("uint64:",
- QString().sprintf("%u",
+ QString().sprintf("%lu",
*(uint64_t*)p_data));
+#else
+ this->p_data_interpreter->AddValue("int64:",
+ QString().sprintf("%lld",
+ *(int64_t*)p_data));
+ this->p_data_interpreter->AddValue("uint64:",
+ QString().sprintf("%llu",
+ *(uint64_t*)p_data));
+#endif
date_time.setTime_t((*(uint64_t*)p_data-116444736000000000)/10000000);
this->p_data_interpreter->AddValue("Win64time:",
date_time.
toString("yyyy/MM/dd hh:mm:ss"));
}
//#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;i<categories.count();i++) {
// First create category submenu
p_category_entry=this->ui->MenuReports->addMenu(categories.value(i));
// Now add category reports
reports=this->p_data_reporter->GetAvailableReports(categories.value(i));
for(ii=0;ii<reports.count();ii++) {
p_report_entry=new QAction(reports.value(ii),p_category_entry);
p_category_entry->addAction(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(args.count()==2) {
// Try to open specified hive file
this->OpenHive(args.at(1));
}
}
diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp
index 65b806c..256d1fd 100644
--- a/trunk/registryhive.cpp
+++ b/trunk/registryhive.cpp
@@ -1,459 +1,462 @@
/*******************************************************************************
* fred Copyright (c) 2011 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "registryhive.h"
#include <QStringList>
#include <stdlib.h>
/*
* 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;
}
/*
* GetNodes
*/
QMap<QString,int> RegistryHive::GetNodes(QString path) {
hive_node_h parent_node;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&parent_node)) return QMap<QString,int>();
// Get and return nodes
return this->GetNodesHelper(parent_node);
}
/*
* GetNodes
*/
QMap<QString,int> RegistryHive::GetNodes(int parent_node) {
if(parent_node==0) {
this->SetError(tr("Invalid parent node handle specified!"));
return QMap<QString,int>();
}
// Get and return nodes
return this->GetNodesHelper(parent_node);
}
/*
* GetKeys
*/
QMap<QString,int> RegistryHive::GetKeys(QString path) {
hive_node_h parent_node;
// Get handle to last node in path
if(!this->GetNodeHandle(path,&parent_node)) return QMap<QString,int>();
// Get and return keys
return this->GetKeysHelper(parent_node);
}
/*
* GetKeys
*/
QMap<QString,int> RegistryHive::GetKeys(int parent_node) {
if(parent_node==0) {
this->SetError(tr("Invalid parent node handle specified!"));
return QMap<QString,int>();
}
// 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);
}
/*
* KeyValueToString
*/
QString RegistryHive::KeyValueToString(QByteArray value, int value_type) {
QString ret="";
int i=0;
#define ToHexStr() { \
for(i=0;i<value.size();i++) { \
ret.append(QString().sprintf("%02X ",(uint8_t)(value.constData()[i]))); \
} \
ret.chop(1); \
}
switch(value_type) {
case hive_t_REG_NONE:
// Just a key without a value, but to be certain...
ToHexStr();
break;
case hive_t_REG_SZ:
// A Windows string (encoding is unknown, but often UTF16-LE)
// TODO: What happens if encoding is not UTF16-LE ??? Thx Billy!!!
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_EXPAND_SZ:
// A Windows string that contains %env% (environment variable expansion)
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_BINARY:
// A blob of binary
ToHexStr();
break;
case hive_t_REG_DWORD:
// DWORD (32 bit integer), little endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
//ret=QString().sprintf("0x%08X",value.toUInt());
break;
case hive_t_REG_DWORD_BIG_ENDIAN:
// DWORD (32 bit integer), big endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
//ret=QString().sprintf("0x%08X",value.toUInt());
break;
case hive_t_REG_LINK:
// Symbolic link to another part of the registry tree
ToHexStr();
break;
case hive_t_REG_MULTI_SZ:
// Multiple Windows strings.
// See http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx
ToHexStr();
break;
case hive_t_REG_RESOURCE_LIST:
// Resource list
ToHexStr();
break;
case hive_t_REG_FULL_RESOURCE_DESCRIPTOR:
// Resource descriptor
ToHexStr();
break;
case hive_t_REG_RESOURCE_REQUIREMENTS_LIST:
// Resouce requirements list
ToHexStr();
break;
case hive_t_REG_QWORD:
// QWORD (64 bit integer). Usually little endian.
- ret=QString().sprintf("0x%016X",*(uint64_t*)value.constData());
- //ret=QString().sprintf("0x%08X",value.toULongLong());
+#if __WORDSIZE == 64
+ ret=QString().sprintf("0x%016lX",*(uint64_t*)value.constData());
+#else
+ ret=QString().sprintf("0x%016llX",*(uint64_t*)value.constData());
+#endif
break;
default:
ToHexStr();
}
#undef ToHexStr
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;
}
/*
* 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;i<nodes.count();i++) {
*p_node=hivex_node_get_child(this->p_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<QString,int> RegistryHive::GetNodesHelper(hive_node_h parent_node) {
QMap<QString,int> 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<QString,int>();
}
// 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<QString,int>();
}
keys.insert(QString(p_name),(int)child_nodes[i]);
free(p_name);
i++;
}
free(child_nodes);
return keys;
}
/*
* GetKeysHelper
*/
QMap<QString,int> RegistryHive::GetKeysHelper(hive_node_h parent_node) {
QMap<QString,int> 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<QString,int>();
}
// 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<QString,int>();
}
keys.insert(QString(p_name),p_keys[i]);
free(p_name);
i++;
}
free(p_keys);
return keys;
}
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;
}
diff --git a/trunk/registrykeytablemodel.cpp b/trunk/registrykeytablemodel.cpp
index 107af1e..6bbb483 100644
--- a/trunk/registrykeytablemodel.cpp
+++ b/trunk/registrykeytablemodel.cpp
@@ -1,293 +1,297 @@
/*******************************************************************************
* fred Copyright (c) 2011 by Gillen Daniel <gillen.dan@pinguin.lu> *
* *
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************/
#include "registrykeytablemodel.h"
#include <stdlib.h>
RegistryKeyTableModel::RegistryKeyTableModel(RegistryHive *p_hive,
QString node_path,
QObject *p_parent)
: QAbstractTableModel(p_parent)
{
// Create the "root" key. It's values will be used for as header values.
this->p_keys=new RegistryKey(QList<QVariant>()<<
tr("Key")<<tr("Type")<<tr("Value"));
// Build key list
this->SetupModelData(p_hive,node_path);
}
RegistryKeyTableModel::~RegistryKeyTableModel() {
delete this->p_keys;
}
QVariant RegistryKeyTableModel::data(const QModelIndex &index, int role) const {
bool ok;
if(!index.isValid()) return QVariant();
RegistryKey *p_key=static_cast<RegistryKey*>(index.internalPointer());
switch(role) {
case Qt::DisplayRole: {
switch(index.column()) {
case RegistryKeyTableModel::ColumnContent_KeyName: {
return p_key->Data(index.column());
break;
}
case RegistryKeyTableModel::ColumnContent_KeyType: {
int value_type=p_key->Data(index.column()).toInt(&ok);
if(!ok) return QVariant();
return this->TypeToString(value_type);
break;
}
case RegistryKeyTableModel::ColumnContent_KeyValue: {
// Get index to value type
QModelIndex type_index=this->index(index.row(),
RegistryKeyTableModel::
ColumnContent_KeyType);
// Get value type
int value_type=this->data(type_index,
RegistryKeyTableModel::
AdditionalRoles_GetRawData).toInt(&ok);
if(!ok) return QVariant();
// Return value converted to human readeable string
QByteArray value_array=p_key->Data(index.column()).toByteArray();
return this->ValueToString(value_array,value_type);
break;
}
default:
return QVariant();
}
break;
}
case RegistryKeyTableModel::AdditionalRoles_GetRawData: {
return p_key->Data(index.column());
break;
}
default:
return QVariant();
}
+ return QVariant();
}
Qt::ItemFlags RegistryKeyTableModel::flags(const QModelIndex &index) const {
if(!index.isValid()) return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant RegistryKeyTableModel::headerData(int section,
Qt::Orientation orientation,
int role) const
{
// Only horizontal header is supported
if(orientation!=Qt::Horizontal) return QVariant();
switch(role) {
case Qt::TextAlignmentRole:
// Handle text alignment
if(section==2) return Qt::AlignLeft;
else return Qt::AlignCenter;
break;
case Qt::DisplayRole:
// Header text
return this->p_keys->Data(section);
break;
default:
return QVariant();
}
}
QModelIndex RegistryKeyTableModel::index(int row,
int column,
const QModelIndex &parent) const
{
if(!this->hasIndex(row,column,parent)) return QModelIndex();
RegistryKey *p_key=this->p_keys->Key(row);
return this->createIndex(row,column,p_key);
}
int RegistryKeyTableModel::rowCount(const QModelIndex &parent) const {
// According to Qt doc, when parent in TableModel is valid, we should return 0
if(parent.isValid()) return 0;
// Get and return row count from the keys list
return this->p_keys->RowCount();
}
int RegistryKeyTableModel::columnCount(const QModelIndex &parent) const {
// According to Qt doc, when parent in TableModel is valid, we should return 0
if(parent.isValid()) return 0;
// There are always 3 columns
return 3;
}
void RegistryKeyTableModel::SetupModelData(RegistryHive *p_hive,
QString &node_path)
{
QMap<QString,int> node_keys;
RegistryKey *p_key;
QByteArray key_value;
int key_value_type;
size_t key_value_len;
// Get all keys for current node
node_keys=p_hive->GetKeys(node_path);
if(node_keys.isEmpty()) return;
// Add all keys to list
QMapIterator<QString,int> i(node_keys);
while(i.hasNext()) {
i.next();
key_value=p_hive->GetKeyValue(i.value(),
&key_value_type,
&key_value_len);
if(p_hive->GetErrorMsg()!="") continue;
p_key=new RegistryKey(QList<QVariant>()<<
QString(i.key().length() ? i.key() : "(default)")<<
QVariant(key_value_type)<<
key_value);
this->p_keys->Append(p_key);
}
}
QString RegistryKeyTableModel::ValueToString(QByteArray &value,
int value_type) const
{
QString ret="";
int i=0;
#define ToHexStr() { \
for(i=0;i<value.size();i++) { \
ret.append(QString().sprintf("%02X ",(uint8_t)(value.constData()[i]))); \
} \
ret.chop(1); \
}
switch(value_type) {
case hive_t_REG_NONE:
// Just a key without a value, but to be certain...
ToHexStr();
break;
case hive_t_REG_SZ:
// A Windows string (encoding is unknown, but often UTF16-LE)
// TODO: What happens if encoding is not UTF16-LE ??? Thx Billy!!!
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_EXPAND_SZ:
// A Windows string that contains %env% (environment variable expansion)
ret=value.size() ? QString().fromUtf16((ushort*)(value.constData())) : "";
break;
case hive_t_REG_BINARY:
// A blob of binary
ToHexStr();
break;
case hive_t_REG_DWORD:
// DWORD (32 bit integer), little endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
//ret=QString().sprintf("0x%08X",value.toUInt());
break;
case hive_t_REG_DWORD_BIG_ENDIAN:
// DWORD (32 bit integer), big endian
ret=QString().sprintf("0x%08X",*(uint32_t*)value.constData());
//ret=QString().sprintf("0x%08X",value.toUInt());
break;
case hive_t_REG_LINK:
// Symbolic link to another part of the registry tree
ToHexStr();
break;
case hive_t_REG_MULTI_SZ:
// Multiple Windows strings.
// See http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx
ToHexStr();
break;
case hive_t_REG_RESOURCE_LIST:
// Resource list
ToHexStr();
break;
case hive_t_REG_FULL_RESOURCE_DESCRIPTOR:
// Resource descriptor
ToHexStr();
break;
case hive_t_REG_RESOURCE_REQUIREMENTS_LIST:
// Resouce requirements list
ToHexStr();
break;
case hive_t_REG_QWORD:
// QWORD (64 bit integer). Usually little endian.
- ret=QString().sprintf("0x%016X",*(uint64_t*)value.constData());
- //ret=QString().sprintf("0x%08X",value.toULongLong());
+#if __WORDSIZE == 64
+ ret=QString().sprintf("0x%016lX",*(uint64_t*)value.constData());
+#else
+ ret=QString().sprintf("0x%016llX",*(uint64_t*)value.constData());
+#endif
break;
default:
ToHexStr();
}
#undef ToHexStr
return ret;
}
QString RegistryKeyTableModel::TypeToString(int value_type) const {
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;
}
diff --git a/trunk/report_templates/SAM_UserAccounts.qs b/trunk/report_templates/SAM_UserAccounts.qs
index 0f77c9c..7ab402c 100644
--- a/trunk/report_templates/SAM_UserAccounts.qs
+++ b/trunk/report_templates/SAM_UserAccounts.qs
@@ -1,75 +1,81 @@
// See http://windowsir.blogspot.com/2006/08/getting-user-info-from-image.html
function print_table_row(cell01,cell02) {
println(" <tr><td>",cell01,"</td><td>",cell02,"</td></tr>");
}
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("<html>");
println(" <head><title>User Accounts</title></head>");
-println(" <body>");
+println(" <body style=\"font-size:12\">");
println(" <h2>User accounts</h2>");
// Iterate over all user names
var user_names=GetRegistryNodes("\\SAM\\Domains\\Account\\Users\\Names");
for(var i=0;i<user_names.length;i++) {
- println(" <p>");
+ println(" <p style=\"font-size:12\">");
// Print user name
- println(" ",user_names[i],"<br />");
+ println(" <u>",user_names[i],"</u><br />");
- println(" <table style=\"margin-left:20px\">");
+ println(" <table style=\"margin-left:20px; font-size:12\">");
// 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(" <tr><td>RID:</td><td>",Number(user_rid).toString(10)," (",user_rid,")","</td></tr>");
// 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(" <tr><td>Account flags:</td><td>");
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("</td></tr>");
+ // 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(" </table>");
println(" </p>");
}
println("</html>");
diff --git a/trunk/report_templates/SOFTWARE_WindowsVersion.qs b/trunk/report_templates/SOFTWARE_WindowsVersion.qs
index ec564a9..661f89f 100644
--- a/trunk/report_templates/SOFTWARE_WindowsVersion.qs
+++ b/trunk/report_templates/SOFTWARE_WindowsVersion.qs
@@ -1,22 +1,75 @@
+function print_table_row(cell01,cell02) {
+ println(" <tr><td>",cell01,"</td><td>",cell02,"</td></tr>");
+}
+
+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("<html>");
println(" <head><title>Windows version info</title></head>");
-println(" <body>");
+println(" <body style=\"font-size:12\">");
println(" <h2>Windows version info</h2>");
-println(" <p>");
+println(" <p style=\"font-size:12\">");
+println(" <table style=\"margin-left:20px; font-size:12\">");
-// Windows version
+// Windows version sp and build info
var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","ProductName");
-println("Windows version: ",RegistryKeyValueToString(val.value,1),"<br />");
+print(" <tr><td>Windows version:</td><td>",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("</td></tr>");
+// Build string
+var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","BuildLab");
+print_table_row("Build string:",RegistryKeyValueToString(val.value,val.type));
// Install date
var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","InstallDate");
-println("Install date: ",RegistryKeyValueToVariant(val.value,"unixtime"),"<br />");
+print_table_row("Install date:",RegistryKeyValueToVariant(val.value,"unixtime"));
// Owner and Organization info
var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","RegisteredOwner");
-println("Registered owner: ",RegistryKeyValueToString(val.value,1),"<br />");
+print_table_row("Registered owner:",RegistryKeyValueToString(val.value,val.type));
var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","RegisteredOrganization");
-println("Registered organization: ",RegistryKeyValueToString(val.value,1),"<br />");
+print_table_row("Registered organization:",RegistryKeyValueToString(val.value,val.type));
+
+// Windows ID / Key
+var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","ProductId");
+print_table_row("Product ID:",RegistryKeyValueToString(val.value,val.type));
+var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","DigitalProductId");
+print_table_row("Product Key:",DecodeProductKey(val.value));
+
+// Install directory / Source directory
+var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","PathName");
+print_table_row("Install path:",RegistryKeyValueToString(val.value,val.type));
+var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","SourcePath");
+print_table_row("Source path:",RegistryKeyValueToString(val.value,val.type));
+println(" </table>");
println(" </p>");
println("</html>");

File Metadata

Mime Type
text/x-diff
Expires
Sun, Aug 24, 10:04 AM (12 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1310163
Default Alt Text
(64 KB)

Event Timeline