diff --git a/trunk/datareporter.cpp b/trunk/datareporter.cpp index a37fe85..73013bc 100644 --- a/trunk/datareporter.cpp +++ b/trunk/datareporter.cpp @@ -1,200 +1,200 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "datareporter.h" #include #include #include #include DataReporter::DataReporter() { this->report_templates.clear(); //this->p_report_engine=new DataReporterEngine(); } DataReporter::~DataReporter() { //delete this->p_report_engine; qDeleteAll(this->report_templates); } void DataReporter::LoadReportTemplates(QString dir) { QString report_template=""; int i=0; int ii=0; bool found=false; QString report_category=""; QString report_name=""; ReportTemplate *p_report; // Get all template files in report_templates directory QDir report_dir(dir); QStringList found_report_templates=report_dir. entryList(QStringList()<<"*.qs"); for(i=0;i_.qs) report_category=found_report_templates.value(i).left( found_report_templates.value(i).indexOf("_")); report_name=found_report_templates.value(i).mid( found_report_templates.value(i).indexOf("_")+1); report_name=report_name.left(report_name.lastIndexOf(".")); // Check if a report with the same category/name was already added found=false; for(ii=0;iireport_templates.count();ii++) { if(this->report_templates.at(ii)->Category()==report_category && this->report_templates.at(ii)->Name()==report_name) { found=true; break; } } if(!found) { // Add report to list p_report=new ReportTemplate(report_category, report_name, report_template); this->report_templates.append(p_report); } else { // Update report entry p_report=this->report_templates.at(ii); p_report->SetFile(report_template); } } } QStringList DataReporter::GetAvailableReportCategories() { QStringList ret; QString cat; int i=0; ret.clear(); for(i=0;ireport_templates.count();i++) { cat=this->report_templates.value(i)->Category(); if(!ret.contains(cat)) ret.append(cat); } ret.sort(); return ret; } QStringList DataReporter::GetAvailableReports(QString category) { QStringList ret; QString cat; int i=0; ret.clear(); for(i=0;ireport_templates.count();i++) { cat=this->report_templates.value(i)->Category(); if(cat==category) ret.append(this->report_templates.value(i)->Name()); } ret.sort(); return ret; } QString DataReporter::GenerateReport(RegistryHive *p_hive, QString report_category, QString report_name) { int i=0; ReportTemplate *p_report; // Search report template for(i=0;ireport_templates.count();i++) { p_report=this->report_templates.value(i); if(p_report->Category()!=report_category || p_report->Name()!=report_name) { continue; } // Report template was found, now generate report and return result return this->GenerateReport(p_hive,p_report->File()); } // Report template couldn't be found QMessageBox::critical(0, "Report engine error", QString("Unable to find report with name '%1' in category '%2'!") .arg(report_name) .arg(report_category)); return QString(); } QString DataReporter::GenerateReport(RegistryHive *p_hive, QString report_template, bool console_mode) { QString report_code; // Init data reporter engine DataReporterEngine engine(p_hive); QScriptValue hive_value=engine.newQObject(p_hive); engine.globalObject().setProperty("RegistryHive",hive_value); // Open report template QFile template_file(report_template); if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) { if(!console_mode) { QMessageBox::critical(0, "Report engine error", QString("Couldn't open report template file '%1'!") .arg(report_template)); } else { printf("ERROR: Couldn't open report template file '%s'!\n", report_template.toAscii().constData()); } return QString(); } // Read template file QTextStream in(&template_file); while(!in.atEnd()) report_code.append(in.readLine()).append("\n"); // Close report template file template_file.close(); // Execute report template script QScriptValue report_result=engine.evaluate(report_code,report_template); if (report_result.isError() || engine.hasUncaughtException()) { if(!console_mode) { QMessageBox::critical(0, "Report engine error", - QString::fromLatin1("%0:%1: %2") + QString::fromLatin1("File: %0\n Line: %1\nError: %2") .arg(report_template) .arg(report_result.property("lineNumber") .toInt32()) .arg(report_result.toString())); } else { printf("ERROR: %s:%u: %s\n", report_template.toAscii().constData(), report_result.property("lineNumber").toInt32(), report_result.toString().toAscii().constData()); } return QString(); } return engine.report_content; } diff --git a/trunk/datareporterengine.cpp b/trunk/datareporterengine.cpp index 128a962..15697fe 100644 --- a/trunk/datareporterengine.cpp +++ b/trunk/datareporterengine.cpp @@ -1,325 +1,361 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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 "datareporterengine.h" #include #include #include #include +#include #include DataReporterEngine::DataReporterEngine(RegistryHive *p_hive) : QScriptEngine() { // Init vars this->p_registry_hive=p_hive; this->report_content=""; // 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); + // GetRegistryKeyModTime + QScriptValue func_get_key_modt=this->newFunction(this->GetRegistryKeyModTime, + 2); + func_get_key_modt.setData(this->newQObject(this->p_registry_hive)); + this->globalObject().setProperty("GetRegistryKeyModTime",func_get_key_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); } 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;iargumentCount();++i) { //if(i>0) content.append(" "); content.append(context->argument(i).toString()); } //QScriptValue calleeData=context->callee().data(); //DataReporterEngine *engine= // qobject_cast(calleeData.toQObject()); qobject_cast(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;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 DataReporterEngine::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 DataReporterEngine::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 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(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(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 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(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=-1; QByteArray key_value; QString format=""; 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(); } if(context->argumentCount()==4) { offset=context->argument(2).toInt32(); length=context->argument(3).toInt32(); } // 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); 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); } + +QScriptValue DataReporterEngine::GetRegistryKeyModTime( + QScriptContext *context, + QScriptEngine *engine) +{ + QScriptValue calleeData; + RegistryHive *p_hive; + int64_t mod_time=0; + + // This function needs two argument, 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()); + + mod_time=p_hive->GetKeyModTime(context->argument(0).toString(), + context->argument(1).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")); +} diff --git a/trunk/datareporterengine.h b/trunk/datareporterengine.h index 321a84f..3891185 100644 --- a/trunk/datareporterengine.h +++ b/trunk/datareporterengine.h @@ -1,74 +1,76 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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 DATAREPORTERENGINE_H #define DATAREPORTERENGINE_H #include #include #include #include #include #include "registryhive.h" #include "qtscript_types/bytearray.h" class DataReporterEngine : public QScriptEngine { Q_OBJECT public: struct s_RegistryKeyValue { int type; int length; QByteArray value; }; RegistryHive *p_registry_hive; QString report_content; DataReporterEngine(RegistryHive *p_hive); ~DataReporterEngine(); 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 GetRegistryKeyModTime(QScriptContext *context, + QScriptEngine *engine); }; Q_DECLARE_METATYPE(DataReporterEngine::s_RegistryKeyValue) #endif // DATAREPORTERENGINE_H diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp index 843b5a8..c92e269 100644 --- a/trunk/registryhive.cpp +++ b/trunk/registryhive.cpp @@ -1,612 +1,638 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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; } QString RegistryHive::Filename() { if(this->is_hive_open) return this->hive_file; return QString(); } /* * 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::GetKeyModTime(QString path,QString key) { + hive_node_h parent_node; + hive_value_h hive_key; + + // Get handle to last node in path + if(!this->GetNodeHandle(path,&parent_node)) { + this->SetError(tr("Unable to get node handle!")); + return 0; + } + + // 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!")); + return 0; + } + + // Get and return key's last modification timestamp + return this->GetKeyModTime(hive_key); +} + /* * GetKeyModTime */ int64_t RegistryHive::GetKeyModTime(int hive_key) { - if(hive_key==0) { - this->SetError(tr("Invalid key handle specified!")); - return 0; - } + if(hive_key==0) { + this->SetError(tr("Invalid key handle specified!")); + return 0; + } - // Get and return key last modification timestamp - return hivex_node_timestamp(this->p_hive,hive_key); + // Get and return key's last modification timestamp + return hivex_node_timestamp(this->p_hive,hive_key); } /* * 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; } 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/registryhive.h b/trunk/registryhive.h index 9686d4c..2c47709 100644 --- a/trunk/registryhive.h +++ b/trunk/registryhive.h @@ -1,82 +1,83 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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: 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(); 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 GetKeyModTime(QString path,QString key); int64_t GetKeyModTime(int hive_key); 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); }; #endif // REGISTRYHIVE_H diff --git a/trunk/registrykeytable.cpp b/trunk/registrykeytable.cpp index 6c51b90..a488c3b 100644 --- a/trunk/registrykeytable.cpp +++ b/trunk/registrykeytable.cpp @@ -1,145 +1,146 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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 "registrykeytable.h" #include #include #include RegistryKeyTable::RegistryKeyTable(QWidget *p_parent) : QTableView(p_parent) { // Configure widget this->setSelectionMode(QAbstractItemView::SingleSelection); this->setSelectionBehavior(QAbstractItemView::SelectRows); this->setAutoScroll(false); this->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); this->verticalHeader()->setHidden(true); this->setTextElideMode(Qt::ElideNone); // Create context menu this->p_menu_copy=new QMenu(tr("Copy"),this); this->p_action_copy_key_name=new QAction(tr("Key name"), this->p_menu_copy); this->p_menu_copy->addAction(this->p_action_copy_key_name); this->connect(this->p_action_copy_key_name, SIGNAL(triggered()), this, SLOT(SlotCopyKeyName())); this->p_action_copy_key_value=new QAction(tr("Key value"), this->p_menu_copy); this->p_menu_copy->addAction(this->p_action_copy_key_value); this->connect(this->p_action_copy_key_value, SIGNAL(triggered()), this, SLOT(SlotCopyKeyValue())); } RegistryKeyTable::~RegistryKeyTable() { // Delete context menu delete this->p_action_copy_key_name; delete this->p_action_copy_key_value; delete this->p_menu_copy; } void RegistryKeyTable::setModel(QAbstractItemModel *p_model) { QTableView::setModel(p_model); // Resize table rows / columns to fit data this->resizeColumnsToContents(); this->resizeRowsToContents(); this->horizontalHeader()->stretchLastSection(); if(p_model!=NULL && p_model->rowCount()>0) { // Select first table item this->selectRow(0); } } /* void RegistryKeyTable::selectRow(QString key_name) { int i; this->clearSelection(); for(i=0;imodel()->rowCount();i++) { if(this->model()) } } */ int RegistryKeyTable::sizeHintForColumn(int column) const { int size_hint=-1; int i=0; int item_width=0; QFontMetrics fm(this->fontMetrics()); QModelIndex idx; if(this->model()==NULL) return -1; // Find string that needs the most amount of space idx=this->model()->index(i,column); while(idx.isValid()) { item_width=fm.width(this->model()->data(idx).toString())+10; if(item_width>size_hint) size_hint=item_width; idx=this->model()->index(++i,column); } return size_hint; } void RegistryKeyTable::contextMenuEvent(QContextMenuEvent *p_event) { // Only show context menu when a row is selected - if(this->selectedIndexes().count()!=3) return; + if(this->selectedIndexes().count()!=4) return; // Only show context menu when user clicked on selected row if(!(this->indexAt(p_event->pos())==this->selectedIndexes().at(0) || this->indexAt(p_event->pos())==this->selectedIndexes().at(1) || - this->indexAt(p_event->pos())==this->selectedIndexes().at(2))) + this->indexAt(p_event->pos())==this->selectedIndexes().at(2) || + this->indexAt(p_event->pos())==this->selectedIndexes().at(3))) { return; } // Emit a click signal emit(this->clicked(this->indexAt(p_event->pos()))); // Create context menu and add actions QMenu context_menu(this); context_menu.addMenu(this->p_menu_copy); context_menu.exec(p_event->globalPos()); } void RegistryKeyTable::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { // Call parent class's currentChanged first QTableView::currentChanged(current,previous); // Now emit our signal QModelIndex current_item=QModelIndex(current); emit(RegistryKeyTable::CurrentItemChanged(current_item)); } void RegistryKeyTable::SlotCopyKeyName() { QApplication::clipboard()-> setText(this->selectedIndexes().at(0).data().toString(), QClipboard::Clipboard); } void RegistryKeyTable::SlotCopyKeyValue() { QApplication::clipboard()-> setText(this->selectedIndexes().at(2).data().toString(), QClipboard::Clipboard); } diff --git a/trunk/registrynodetree.cpp b/trunk/registrynodetree.cpp index e05ced1..0b82d47 100644 --- a/trunk/registrynodetree.cpp +++ b/trunk/registrynodetree.cpp @@ -1,129 +1,129 @@ /******************************************************************************* * fred Copyright (c) 2011-2012 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 "registrynodetree.h" #include "registrynodetreemodel.h" #include #include #include RegistryNodeTree::RegistryNodeTree(QWidget *p_parent) : QTreeView(p_parent) { // Configure widget this->setTextElideMode(Qt::ElideNone); // Create context menu this->p_menu_copy=new QMenu(tr("Copy"),this); - this->p_action_copy_node_name=new QAction(tr("Copy node name"), + this->p_action_copy_node_name=new QAction(tr("Node name"), this->p_menu_copy); this->p_menu_copy->addAction(this->p_action_copy_node_name); this->connect(this->p_action_copy_node_name, SIGNAL(triggered()), this, SLOT(SlotCopyNodeName())); - this->p_action_copy_node_path=new QAction(tr("Copy node path"), + this->p_action_copy_node_path=new QAction(tr("Node path"), this->p_menu_copy); this->p_menu_copy->addAction(this->p_action_copy_node_path); this->connect(this->p_action_copy_node_path, SIGNAL(triggered()), this, SLOT(SlotCopyNodePath())); } RegistryNodeTree::~RegistryNodeTree() { // Delete context menu delete this->p_action_copy_node_name; delete this->p_action_copy_node_path; delete this->p_menu_copy; } void RegistryNodeTree::setModel(QAbstractItemModel *p_model) { QTreeView::setModel(p_model); this->header()->setResizeMode(0,QHeaderView::ResizeToContents); this->header()->setStretchLastSection(false); if(p_model!=NULL && p_model->index(0,0).isValid()) { // Select first tree item this->setCurrentIndex(p_model->index(0,0)); } } //int RegistryNodeTree::sizeHintForColumn(int column) const {} void RegistryNodeTree::contextMenuEvent(QContextMenuEvent *p_event) { // Only show context menu when a node is selected if(this->selectedIndexes().count()!=1) return; // Only show context menu when user clicked on selected row if(this->indexAt(p_event->pos())!=this->selectedIndexes().at(0)) return; // Emit a click signal emit(this->clicked(this->indexAt(p_event->pos()))); // Create context menu and add actions QMenu context_menu(this); context_menu.addMenu(this->p_menu_copy); context_menu.exec(p_event->globalPos()); } void RegistryNodeTree::keyPressEvent(QKeyEvent *p_event) { // Only react if a node is selected and user pressed Key_Left if(this->selectedIndexes().count()==1 && p_event->key()==Qt::Key_Left) { QModelIndex cur_index=this->selectedIndexes().at(0); if(this->model()->hasChildren(cur_index)) { // Collapse current node this->collapse(cur_index); } if(!cur_index.parent().isValid()) { // Do no try to collapse anything above root node return; } this->collapse(cur_index.parent()); this->setCurrentIndex(cur_index.parent()); return; } // If we didn't handle the key event, let our parent handle it QTreeView::keyPressEvent(p_event); } void RegistryNodeTree::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { // Call parent class's currentChanged first QTreeView::currentChanged(current,previous); // Now emit our signal QModelIndex current_item=QModelIndex(current); emit(RegistryNodeTree::CurrentItemChanged(current_item)); } void RegistryNodeTree::SlotCopyNodeName() { QApplication::clipboard()-> setText(this->selectedIndexes().at(0).data().toString(), QClipboard::Clipboard); } void RegistryNodeTree::SlotCopyNodePath() { QString path=((RegistryNodeTreeModel*)(this->model()))-> GetNodePath(this->selectedIndexes().at(0)); QApplication::clipboard()->setText(path,QClipboard::Clipboard); } diff --git a/trunk/report_templates/NTUSER_RecentDocs.qs b/trunk/report_templates/NTUSER_RecentDocs.qs index a0f9127..02c8223 100644 --- a/trunk/report_templates/NTUSER_RecentDocs.qs +++ b/trunk/report_templates/NTUSER_RecentDocs.qs @@ -1,23 +1,37 @@ +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + println(""); println(" Recent Documents"); println(" "); println("

Recent documents

"); -println("

"); -println(" "); // Get list of recent docs var recent_docs=GetRegistryKeyValue("\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs","MRUListEx"); +if(IsValid(recent_docs)) { + println("

"); + println("

"); + println(" "); + + // Iterate over all recent docs + var i=0; + var runlist=RegistryKeyValueToVariant(recent_docs.value,"uint32",i); + while(Number(runlist)!=0xffffffff) { + var entry=GetRegistryKeyValue("\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs",runlist.toString(10)); + var mod_time=GetRegistryKeyModTime("\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs",runlist.toString(10)); + println(" "); + i+=4; + runlist=RegistryKeyValueToVariant(recent_docs.value,"uint32",i); + } -// Iterate over all recent docs -var i=0; -var runlist=RegistryKeyValueToVariant(recent_docs.value,"uint32",i); -while(Number(runlist)!=0xffffffff) { - var entry=GetRegistryKeyValue("\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs",runlist.toString(10)); - println(" "); - i+=4; - runlist=RegistryKeyValueToVariant(recent_docs.value,"uint32",i); + println("
Document  Last modified
",RegistryKeyValueToVariant(entry.value,"utf16",0),"  ",mod_time,"
",RegistryKeyValueToVariant(entry.value,"utf16",0),"
"); + println("

"); +} else { + println("

"); + println(" This registry hive does not contain a list of recent documents!"); + println("

"); } -println(" "); -println("

"); println(""); diff --git a/trunk/report_templates/NTUSER_TypedUrls.qs b/trunk/report_templates/NTUSER_TypedUrls.qs index 29ecb94..ec0d2b3 100644 --- a/trunk/report_templates/NTUSER_TypedUrls.qs +++ b/trunk/report_templates/NTUSER_TypedUrls.qs @@ -1,17 +1,32 @@ +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + println(""); println(" Typed Urls"); println(" "); println("

Typed urls

"); -println("

"); -println(" "); // Iterate over all typed urls var typed_urls=GetRegistryKeys("\\Software\\Microsoft\\Internet Explorer\\TypedURLs"); -for(var i=0;i"); +if(IsValid(typed_urls)) { + println("

"); + println("

",RegistryKeyValueToString(val.value,val.type),"
"); + println(" "); + + for(var i=0;i"); + } + + println("
Url  Last modified
",RegistryKeyValueToString(val.value,val.type),"  ",mod_time,"
"); + println("

"); +} else { + println("

"); + println(" This registry hive does not contain a list of typed urls!"); + println("

"); } -println(" "); -println("

"); println(""); diff --git a/trunk/report_templates/NTUSER_WindowsLiveAccounts.qs b/trunk/report_templates/NTUSER_WindowsLiveAccounts.qs index 8345c36..0a78998 100644 --- a/trunk/report_templates/NTUSER_WindowsLiveAccounts.qs +++ b/trunk/report_templates/NTUSER_WindowsLiveAccounts.qs @@ -1,22 +1,35 @@ +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + println(""); println(" Windows Live Accounts"); println(" "); println("

Windows live accounts

"); -println("

"); -println(" "); // Iterate over all contacts var accounts=GetRegistryKeys("\\Software\\Microsoft\\Windows Live Contacts\\Database"); -for(var i=0;i"); -} -accounts=GetRegistryKeys("\\Software\\Microsoft\\Windows Live Contacts\\Me"); -for(var i=0;i"); +if(IsValid(accounts)) { + println("

"); + println("

",accounts[i],"",RegistryKeyValueToString(val.value,val.type),"
",accounts[i],"",RegistryKeyValueToString(val.value,val.type),"
"); + + for(var i=0;i"); + } + accounts=GetRegistryKeys("\\Software\\Microsoft\\Windows Live Contacts\\Me"); + for(var i=0;i"); + } + + println("
",accounts[i],"",RegistryKeyValueToString(val.value,val.type),"
",accounts[i],"",RegistryKeyValueToString(val.value,val.type),"
"); + println("

"); +} else { + println("

"); + println(" This registry hive does not contain a list of Windows Live Accounts!"); + println("

"); } -println(" "); -println("

"); println(""); diff --git a/trunk/report_templates/SAM_UserAccounts.qs b/trunk/report_templates/SAM_UserAccounts.qs index 08c8a3a..9ba427f 100644 --- a/trunk/report_templates/SAM_UserAccounts.qs +++ b/trunk/report_templates/SAM_UserAccounts.qs @@ -1,85 +1,97 @@ // See http://windowsir.blogspot.com/2006/08/getting-user-info-from-image.html +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function print_v_info(v_key_value,info_name,str_off) { var offset=Number(RegistryKeyValueToVariant(v_key_value,"uint16",str_off))+0x0cc; var len=Number(RegistryKeyValueToVariant(v_key_value,"uint16",str_off+4))/2; if(len>0) print_table_row(info_name,RegistryKeyValueToVariant(v_key_value,"utf16",offset,len)); } println(""); println(" User Accounts"); println(" "); println("

User accounts

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

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

"); + } +} else { + println("

"); + println(" Unable to enumerate users!
"); + println(" Are you sure you are running this report against the correct registry hive?"); + println("

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

Windows version info

"); -println("

"); -println(" "); // Windows version sp and build info var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","ProductName"); -print(" "); -// Build string -var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","BuildLab"); -print_table_row("Build string:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); -// Extended build string -var val=GetRegistryKeyValue("\\Microsoft\\Windows NT\\CurrentVersion","BuildLabEx"); -print_table_row("Extended build string:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); +if(IsValid(val)) { + println("

"); + println("

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

"); +} else { + println("

"); + println(" Unable to get product name!
"); + println(" Are you sure you are running this report against the correct registry hive?"); + println("

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

"); println(""); diff --git a/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs b/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs index 08014c8..d646494 100644 --- a/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs +++ b/trunk/report_templates/SYSTEM_CurrentNetworkSettings.qs @@ -1,97 +1,109 @@ +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function ZeroPad(number,padlen) { var ret=number.toString(10); if(!padlen || ret.length>=padlen) return ret; return Math.pow(10,padlen-ret.length).toString().slice(1)+ret; } // Global vars var val; -// Get current controlset -var cur_controlset=GetRegistryKeyValue("\\Select","Current"); -cur_controlset=RegistryKeyValueToString(cur_controlset.value,cur_controlset.type); -// Current holds a DWORD value, thus we get a string like 0x00000000, but -// control sets are referenced by its decimal representation. -cur_controlset="ControlSet"+ZeroPad(parseInt(String(cur_controlset).substr(2,8),16),3) - println(""); println(" Current Network Settings (Tcp/Ip)"); println(" "); println("

Current network settings (Tcp/Ip)

"); -println("

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

"); +} else { + println("

"); + println(" Unable to determine current control set!
"); + println(" Are you sure you are running this report against the correct registry hive?"); + println("

"); } -println("

"); println(""); diff --git a/trunk/report_templates/SYSTEM_SystemTimeInfo.qs b/trunk/report_templates/SYSTEM_SystemTimeInfo.qs index 9367040..e1dbd96 100644 --- a/trunk/report_templates/SYSTEM_SystemTimeInfo.qs +++ b/trunk/report_templates/SYSTEM_SystemTimeInfo.qs @@ -1,96 +1,110 @@ +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function ToUTC(num) { var retnum=new Number(num); if(retnum&0x80000000) { retnum=((0xFFFFFFFF-retnum)+1)/60; return "UTC+"+Number(retnum).toString(10); } else { retnum=retnum/60; if(retnum!=0) return "UTC-"+Number(retnum).toString(10); else return "UTC+"+Number(retnum).toString(10); } } function ZeroPad(number,padlen) { var ret=number.toString(10); if(!padlen || ret.length>=padlen) return ret; return Math.pow(10,padlen-ret.length).toString().slice(1)+ret; } // Global vars var val; -// Get current controlset -var cur_controlset=GetRegistryKeyValue("\\Select","Current"); -cur_controlset=RegistryKeyValueToString(cur_controlset.value,cur_controlset.type); -// Current holds a DWORD value, thus we get a string like 0x00000000, but -// control sets are referenced by its decimal representation. -cur_controlset="ControlSet"+ZeroPad(parseInt(String(cur_controlset).substr(2,8),16),3) - println(""); println(" System Time Info"); println(" "); println("

System time info (",cur_controlset,")

"); -println("

"); -println(" Time zone info"); -println(" "); -// Active time bias -val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","ActiveTimeBias"); -print_table_row("Active time bias:",(typeof val !== 'undefined') ? ToUTC(RegistryKeyValueToString(val.value,val.type)) : "n/a"); +// Get current controlset +var cur_controlset=GetRegistryKeyValue("\\Select","Current"); +if(IsValid(cur_controlset)) { + cur_controlset=RegistryKeyValueToString(cur_controlset.value,cur_controlset.type); + // Current holds a DWORD value, thus we get a string like 0x00000000, but + // control sets are referenced by its decimal representation. + cur_controlset="ControlSet"+ZeroPad(parseInt(String(cur_controlset).substr(2,8),16),3) -// Std. tz name and bias -val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","StandardName"); -print_table_row("Std. time zone name:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : "n/a"); -val=GetRegistryKeyValue(cur_controlset+"\\Control\\TimeZoneInformation","StandardBias"); -print_table_row("Std. time bias:",(typeof val !== 'undefined') ? ToUTC(RegistryKeyValueToString(val.value,val.type)) : "n/a"); + println("

"); + println(" Time zone info"); + println("

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

"); +} else { + println("

"); + println(" Unable to determine current control set!
"); + println(" Are you sure you are running this report against the correct registry hive?"); + println("

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

"); println(""); diff --git a/trunk/report_templates/SYSTEM_UsbStorageDevices.qs b/trunk/report_templates/SYSTEM_UsbStorageDevices.qs index 343c8e2..9cd16f3 100644 --- a/trunk/report_templates/SYSTEM_UsbStorageDevices.qs +++ b/trunk/report_templates/SYSTEM_UsbStorageDevices.qs @@ -1,92 +1,139 @@ // TODO: There is more here. Check http://www.forensicswiki.org/wiki/USB_History_Viewing +function IsValid(val) { + if(typeof val !== 'undefined') return true; + else return false; +} + function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function ZeroPad(number,padlen) { var ret=number.toString(10); if(!padlen || ret.length>=padlen) return ret; return Math.pow(10,padlen-ret.length).toString().slice(1)+ret; } // Global vars var val; +println(""); +println(" USB Storage Devices"); +println(" "); +println("

USB storage devices

"); + // Preload MountedDevices to possibly identify mount points of USB storage devices var mnt_keys=GetRegistryKeys("\\MountedDevices"); var mnt_values=new Array(); -for(var i=0;i"); -println(" USB Storage Devices"); -println(" "); -println("

USB storage devices

"); -println("

"); + println("

"); + println(" Settings
"); + println(" "); -var storage_roots=GetRegistryNodes(cur_controlset+"\\Enum\\USBSTOR"); -for(var i=0;i",storage_roots[i],"
"); - var storage_subroots=GetRegistryNodes(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]); - for(ii=0;ii"); - // If the second character of the unique instance ID is a '&', then the ID was - // generated by the system, as the device did not have a serial number. - if(String(storage_subroots[ii]).charAt(1)=="&") print_table_row("Unique ID:",storage_subroots[ii]+" (Generated by system)"); - else print_table_row("Unique ID:",storage_subroots[ii]); + // Are USB storage devices enabled? + // http://www.forensicmag.com/article/windows-7-registry-forensics-part-5 + // Is this true for WinXP etc.. ??? + var val=GetRegistryKeyValue(cur_controlset+"\\services\\USBSTOR","Start"); + if(IsValid(val)) { + val=RegistryKeyValueToString(val.value,val.type); + val=parseInt(String(val).substr(2,8),10); + switch(val) { + case 3: + print_table_row("Storage driver enabled:","Yes"); + break; + case 4: + print_table_row("Storage driver enabled:","No"); + break; + default: + print_table_row("Storage driver enabled:","Unknown"); + } + } else { + print_table_row("Storage driver enabled:","Unknown"); + } - val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"Class"); - print_table_row("Class:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); - val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"DeviceDesc"); - print_table_row("Device description:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); - val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"FriendlyName"); - print_table_row("Friendly name:",(typeof val !== 'undefined') ? RegistryKeyValueToString(val.value,val.type) : ""); - val=GetRegistryKeyValue(cur_controlset+"\\Enum\\USBSTOR\\"+storage_roots[i]+"\\"+storage_subroots[ii],"ParentIdPrefix"); - if(typeof val !== 'undefined') { - // Windows XP used the ParentId to link to MountedDevices - var parent_id=RegistryKeyValueToString(val.value,val.type); - print_table_row("Parent ID prefix:",parent_id); - // Find mount point(s) - print("
"); - } else { - // Since Vista, Unique ID is used - // Find mount point(s) - print("
Mount point(s):"); - var br=0; - for(var iii=0;iii"); - else br=1; - print(mnt_keys[iii]); - } - } - if(br==0) print("n/a"); - println("
Mount point(s):"); - var br=0; - for(var iii=0;iii"); - else br=1; - print(mnt_keys[iii]); + println("
"); + println("

"); + println("

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

"); +} else { + println("

"); + println(" Unable to determine current control set!
"); + println(" Are you sure you are running this report against the correct registry hive?"); + println("

"); } -println("

"); println("");