diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp index a11abea..639f092 100644 --- a/trunk/registryhive.cpp +++ b/trunk/registryhive.cpp @@ -1,701 +1,735 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "registryhive.h" #include #include #include #include // TODO: __WORDSIZE is not defined under mingw and I currently have no idea how // to identify a 64bit windows #ifndef __WORDSIZE #define __WORDSIZE 32 #endif #if __WORDSIZE == 64 #define EPOCH_DIFF 0x19DB1DED53E8000 #else #define EPOCH_DIFF 0x19DB1DED53E8000LL #endif +/******************************************************************************* + * Public + ******************************************************************************/ + /* * RegistryHive */ RegistryHive::RegistryHive(QObject *p_parent) : QObject(p_parent) { this->erro_msg=""; this->is_error=false; this->hive_file=""; this->p_hive=NULL; this->is_hive_open=false; } /* * ~RegistryHive */ RegistryHive::~RegistryHive() { if(this->is_hive_open) this->Close(); } /* * Error */ bool RegistryHive::Error() { return this->is_error; } /* * GetErrorMsg */ QString RegistryHive::GetErrorMsg() { QString msg=this->erro_msg; this->erro_msg=""; this->is_error=false; return msg; } /* * Open */ bool RegistryHive::Open(QString file, bool read_only) { if(this->is_hive_open) return false; // Open hive file this->p_hive=hivex_open(file.toAscii().constData(), read_only ? 0 : HIVEX_OPEN_WRITE); if(this->p_hive==NULL) return false; // Set local vars this->hive_file=file; this->is_hive_open=true; return true; } /* * Close */ bool RegistryHive::Close(bool commit_changes) { if(this->is_hive_open) { if(commit_changes) { // Commit changes before closing hive. // TODO: Maybe it would be more secure to commit changes to a new file and // then move it over the original one. hivex_commit(this->p_hive,NULL,0); } // As hivex_close will _ALWAYS_ free the handle, we don't need the following // values anymore this->hive_file=""; this->is_hive_open=false; // Close hive if(hivex_close(this->p_hive)!=0) return false; } return true; } /* * Filename */ QString RegistryHive::Filename() { if(this->is_hive_open) return this->hive_file; return QString(); } /* * HiveType */ RegistryHive::teHiveType RegistryHive::HiveType() { // Check for SYSTEM hive if(this->PathExists("\\Select") && this->PathExists("\\MountedDevices")) return RegistryHive::eHiveType_SYSTEM; // Check for SOFTWARE hive if(this->PathExists("\\Microsoft\\Windows\\CurrentVersion") && this->PathExists("\\Microsoft\\Windows NT\\CurrentVersion")) return RegistryHive::eHiveType_SOFTWARE; // Check for SAM if(this->PathExists("SAM\\Domains\\Account\\Users")) return RegistryHive::eHiveType_SAM; // Check for SECURITY if(this->PathExists("\\Policy\\Accounts") && this->PathExists("\\Policy\\PolAdtEv")) return RegistryHive::eHiveType_SECURITY; // Check for NTUSER.DAT if(this->PathExists("\\Software\\Microsoft\\Windows\\CurrentVersion")) return RegistryHive::eHiveType_NTUSER; // Unknown hive return RegistryHive::eHiveType_UNKNOWN; } /* * HiveTypeToString */ QString RegistryHive::HiveTypeToString(teHiveType hive_type) { switch(hive_type) { case RegistryHive::eHiveType_SYSTEM: return "SYSTEM"; break; case RegistryHive::eHiveType_SOFTWARE: return "SOFTWARE"; break; case RegistryHive::eHiveType_SAM: return "SAM"; break; case RegistryHive::eHiveType_SECURITY: return "SECURITY"; break; case RegistryHive::eHiveType_NTUSER: return "NTUSER"; break; default: return "UNKNOWN"; } } /* * GetNodes */ QMap RegistryHive::GetNodes(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetNodes */ QMap RegistryHive::GetNodes(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len) { hive_node_h parent_node; hive_value_h hive_key; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QByteArray(); // Get key handle hive_key=hivex_node_get_value(this->p_hive, parent_node,key.toAscii().constData()); if(hive_key==0) { this->SetError(tr("Unable to get key handle!")); *p_value_len=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len) { if(hive_key==0) { this->SetError(tr("Invalid key handle specified!")); *p_value_type=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(QString path) { hive_node_h node; // Get handle to last node in path if(!this->GetNodeHandle(path,&node)) { this->SetError(tr("Unable to get node handle!")); return 0; } // Get and return node's last modification timestamp return this->GetNodeModTime(node); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(int node) { if(node==0) { this->SetError(tr("Invalid node handle specified!")); return 0; } // Get and return key's last modification timestamp return hivex_node_timestamp(this->p_hive,node); } /* * KeyValueToString */ QString RegistryHive::KeyValueToString(QByteArray value, int value_type) { QString ret=""; int i=0; #define ToHexStr() { \ for(i=0;i0) { // Nothing to show return QString(); } // Get pointer to data at specified offset p_data=key_value.constData(); p_data+=offset; // TODO: This will fail on platforms with different endianness! #define bswap_16(value) ((((value) & 0xff) << 8) | ((value) >> 8)) #define bswap_32(value) \ (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ (uint32_t)bswap_16((uint16_t)((value) >> 16))) #define bswap_64(value) \ (((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) << 32) | \ (uint64_t)bswap_32((uint32_t)((value) >> 32))) \ - // ConvertFull name + // Convert full 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; } +/* + * KeyValueToStringList + */ +QStringList RegistryHive::KeyValueToStringList(QByteArray value, int value_type) { + QStringList result; + int last_pos=0,cur_pos=0; + + // Only supported on REG_MULTI_SZ values!! + if(value_type!=hive_t_REG_MULTI_SZ) return QStringList(); + + while(last_poserro_msg=msg; this->is_error=true; } /* * GetNodeHandle */ bool RegistryHive::GetNodeHandle(QString &path, hive_node_h *p_node) { QStringList nodes; int i=0; // Get root node handle *p_node=hivex_root(this->p_hive); if(*p_node==0) { this->SetError(tr("Unable to get root node!")); return false; } if(path!="\\") { // If we aren't listing the root node, we have to get a handle to the // last node in the path. Split path into nodes nodes=path.split('\\',QString::SkipEmptyParts); // Iterate to the correct parent node for(i=0;ip_hive, *p_node, nodes.value(i).toAscii().constData()); if(*p_node==0) { this->SetError(tr("Unable to find node '%1'!").arg(nodes.value(i))); return false; } } } return true; } /* * GetNodesHelper */ QMap RegistryHive::GetNodesHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child nodes hive_node_h *child_nodes=hivex_node_children(this->p_hive,parent_node); if(child_nodes==NULL) { this->SetError( tr("Unable to enumerate child nodes!")); return QMap(); } // Build result keys.clear(); i=0; while(child_nodes[i]) { p_name=hivex_node_name(this->p_hive,child_nodes[i]); if(p_name==NULL) { this->SetError(tr("Unable to get node name!")); free(child_nodes); return QMap(); } keys.insert(QString(p_name),(int)child_nodes[i]); free(p_name); i++; } free(child_nodes); return keys; } /* * GetKeysHelper */ QMap RegistryHive::GetKeysHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child keys hive_value_h *p_keys=hivex_node_values(this->p_hive,parent_node); if(p_keys==NULL) { this->SetError( tr("Unable to enumerate child keys!")); return QMap(); } // Build result list keys.clear(); i=0; while(p_keys[i]) { p_name=hivex_value_key(this->p_hive,p_keys[i]); if(p_name==NULL) { this->SetError(tr("Unable to get key name!")); return QMap(); } keys.insert(QString(p_name),p_keys[i]); free(p_name); i++; } free(p_keys); return keys; } /* * GetKeyValueHelper */ QByteArray RegistryHive::GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len) { QByteArray key_value; char *p_key_value; p_key_value=hivex_value_value(this->p_hive, hive_key, (hive_type*)p_value_type, p_value_len); if(p_key_value==NULL) { this->SetError(tr("Unable to get key value!")); *p_value_type=-1; return QByteArray(); } // Feed QByteArray and free p_key_value key_value=QByteArray(p_key_value,*p_value_len); free(p_key_value); return key_value; } /* * PathExists */ bool RegistryHive::PathExists(QString path) { bool ret; hive_node_h node; ret=this->GetNodeHandle(path,&node); if(!ret || this->Error()) { // Clear error and return false this->GetErrorMsg(); return false; } return true; } diff --git a/trunk/registryhive.h b/trunk/registryhive.h index e2f307f..1924384 100644 --- a/trunk/registryhive.h +++ b/trunk/registryhive.h @@ -1,95 +1,96 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef REGISTRYHIVE_H #define REGISTRYHIVE_H #include #include #include class RegistryHive : public QObject { Q_OBJECT public: typedef enum eHiveType { eHiveType_UNKNOWN=0, eHiveType_SYSTEM, eHiveType_SOFTWARE, eHiveType_SAM, eHiveType_SECURITY, eHiveType_NTUSER } teHiveType; explicit RegistryHive(QObject *p_parent=0); ~RegistryHive(); bool Error(); QString GetErrorMsg(); bool Open(QString file, bool read_only=true); bool Close(bool commit_changes=false); QString Filename(); teHiveType HiveType(); QString HiveTypeToString(teHiveType hive_type); QMap GetNodes(QString path="\\"); QMap GetNodes(int parent_node=0); QMap GetKeys(QString path="\\"); QMap GetKeys(int parent_node=0); QByteArray GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len); QByteArray GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len); int64_t GetNodeModTime(QString path); int64_t GetNodeModTime(int node); static QString KeyValueToString(QByteArray value, int value_type); static QString KeyValueToString(QByteArray value, QString format, int offset=0, int length=0, bool little_endian=true); + static QStringList KeyValueToStringList(QByteArray value, int value_type); static QString KeyTypeToString(int value_type); static uint64_t FiletimeToUnixtime(int64_t filetime); private: QString erro_msg; bool is_error; QString hive_file; hive_h *p_hive; bool is_hive_open; void SetError(QString msg); bool GetNodeHandle(QString &path, hive_node_h *p_node); QMap GetNodesHelper(hive_node_h parent_node); QMap GetKeysHelper(hive_node_h parent_node); QByteArray GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len); bool PathExists(QString path); }; #endif // REGISTRYHIVE_H diff --git a/trunk/report_templates/SYSTEM_BackupRestore.qs b/trunk/report_templates/SYSTEM_BackupRestore.qs index 9501ff2..a1a59df 100644 --- a/trunk/report_templates/SYSTEM_BackupRestore.qs +++ b/trunk/report_templates/SYSTEM_BackupRestore.qs @@ -1,65 +1,74 @@ function fred_report_info() { var info={report_cat : "SYSTEM", report_name : "Backup / Restore settings", report_author : "Gillen Daniel", report_desc : "Dump files / directories not to snapshot / backup and registry keys not to restore", fred_api : 2, hive : "SYSTEM" }; return info; } function IsValid(val) { if(typeof val !== 'undefined') return true; else return false; } function print_table_row(cell01,cell02) { println(" ",cell01,"",cell02,""); } function ListValues(root_key) { var values=GetRegistryKeys(root_key); if(IsValid(values)) { println("

"); println(" "); for(var i=0;i"); + println(" "); + println(" "); + println(" "); } } println("
",values[i],""); + var strings=RegistryKeyValueToStringList(value.val,value.type); + if(IsValid(strings) { + for(var i=0;i"); + } + } + println("
"); println("

"); } else { println(" None"); } } function fred_report_html() { var val; println("

Backup / Restore settings

"); // 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 only with the last 3 digits. cur_controlset="ControlSet"+String(cur_controlset).substr(7,3); println(" Directories / files not to back up in Volume Shadow Copies"); ListValues(cur_controlset+"\\Control\\BackupRestore\\FilesNotToSnapshot"); println(" Directories / files not to back up or restore by backup apps"); ListValues(cur_controlset+"\\Control\\BackupRestore\\FilesNotToBackup"); println(" Registry nodes or values not to restore by backup apps"); ListValues(cur_controlset+"\\Control\\BackupRestore\\KeysNotToRestore"); } else { println("

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

"); } } diff --git a/trunk/reportengine.cpp b/trunk/reportengine.cpp index 8784e26..97f76c0 100644 --- a/trunk/reportengine.cpp +++ b/trunk/reportengine.cpp @@ -1,518 +1,554 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "reportengine.h" #include #include #include +#include #include /******************************************************************************* * Public ******************************************************************************/ ReportEngine::ReportEngine(RegistryHive *p_hive) : QScriptEngine() { // Init vars this->p_registry_hive=p_hive; this->report_content=""; // Add our constants this->globalObject().setProperty("ENGINE_API_VERSION", FRED_REPORTENGINE_API_VERSION, QScriptValue::ReadOnly| QScriptValue::Undeletable); /* this->globalObject().setProperty("HIVE_FILE", this->p_registry_hive->Filename(), QScriptValue::ReadOnly| QScriptValue::Undeletable); */ // Add our types to engine qScriptRegisterMetaType(this, this->RegistryKeyValueToScript, this->RegistryKeyValueFromScript); this->p_type_byte_array=new ByteArray(this); this->globalObject().setProperty("ByteArray", this->p_type_byte_array->constructor()); // Add our functions // print QScriptValue func_print=this->newFunction(this->Print); this->globalObject().setProperty("print",func_print); // println QScriptValue func_println=this->newFunction(this->PrintLn); this->globalObject().setProperty("println",func_println); // 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); + // RegistryKeyValueToStringList + QScriptValue func_value_to_string_list= + this->newFunction(this->RegistryKeyValueToStringList); + this->globalObject().setProperty("RegistryKeyValueToStringList", + func_value_to_string_list); // RegistryKeyTypeToString QScriptValue func_type_to_string= this->newFunction(this->RegistryKeyTypeToString,1); this->globalObject().setProperty("RegistryKeyTypeToString", func_type_to_string); } ReportEngine::~ReportEngine() { delete this->p_type_byte_array; } /* * GetReportTemplateInfo */ QMap ReportEngine::GetReportTemplateInfo(QString file) { // Read template file QString report_code; if(!this->GetReportTemplateFileContents(file,report_code)) { QMap error_msg; error_msg["error"]=report_code; return error_msg; } // Evaluate report template script QScriptValue report_result=this->evaluate(report_code,file); if (report_result.isError() || this->hasUncaughtException()) { QMap error_msg; error_msg["error"]=QString("File: %1\n Line: %2\nError: %3") .arg(file) .arg(report_result.property("lineNumber").toInt32()) .arg(report_result.toString()); return error_msg; } // Try to call the fred_report_info script function and return result QScriptValue fred_report_info_func= this->globalObject().property("fred_report_info"); if(!fred_report_info_func.isFunction()) { QMap error_msg; error_msg["error"]= QString("Report template '%1' does not have a fred_report_info function!") .arg(file) .arg(report_result.property("lineNumber").toInt32()) .arg(report_result.toString()); return error_msg; } QScriptValue fred_report_info_res=fred_report_info_func.call(); // TODO: Maybe do more checking on return value return fred_report_info_res.toVariant().toMap(); } /* * GenerateReport */ bool ReportEngine::GenerateReport(RegistryHive *p_hive, QString report_file, QString &report_result, bool console_mode) { // Clear internal buffer this->report_content.clear(); // Update exported functions this->UpdateExportedFunctions(p_hive); // Read template file QString report_code; if(!this->GetReportTemplateFileContents(report_file,report_code)) { report_result=report_code; return false; } // Evaluate report template script QScriptValue script_result=this->evaluate(report_code,report_file); if (script_result.isError() || this->hasUncaughtException()) { script_result=QString("File: %1\n Line: %2\nError: %3") .arg(report_file) .arg(script_result.property("lineNumber").toInt32()) .arg(script_result.toString()); return false; } // Try to call the fred_report_html script function and return result QScriptValue fred_report_html_func= this->globalObject().property("fred_report_html"); if(!fred_report_html_func.isFunction()) { report_result= QString("Report template '%1' does not have a fred_report_info function!") .arg(report_file) .arg(script_result.property("lineNumber").toInt32()) .arg(script_result.toString()); return false; } QScriptValue fred_report_html_res=fred_report_html_func.call(); // TODO: Maybe do more checking on return value report_result=this->report_content; return true; } /******************************************************************************* * Public Slots ******************************************************************************/ /******************************************************************************* * Private ******************************************************************************/ /* * Print */ QScriptValue ReportEngine::Print(QScriptContext *context, QScriptEngine *engine) { int i; QString content; // Append all arguments to content for(i=0;iargumentCount();++i) { //if(i>0) content.append(" "); content.append(context->argument(i).toString()); } qobject_cast(engine)->report_content.append(content); return engine->undefinedValue(); } /* * PrintLn */ QScriptValue ReportEngine::PrintLn(QScriptContext *context, QScriptEngine *engine) { int i; QString content; // Append all arguments to content for(i=0;iargumentCount();++i) { //if(i>0) content.append(" "); content.append(context->argument(i).toString()); } qobject_cast(engine)-> report_content.append(content).append("\n"); return engine->undefinedValue(); } /* * GetRegistryNodes */ QScriptValue ReportEngine::GetRegistryNodes(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QMap nodes; QScriptValue ret_nodes; int ii=0; // This function needs one argument, parent node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get nodes nodes=p_hive->GetNodes(context->argument(0).toString()); if(p_hive->Error()) { // Clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } // Build script array ret_nodes=engine->newArray(nodes.count()); QMapIterator i(nodes); while(i.hasNext()) { i.next(); ret_nodes.setProperty(ii++,QScriptValue(i.key())); } return ret_nodes; } /* * GetRegistryKeys */ QScriptValue ReportEngine::GetRegistryKeys(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QMap keys; QScriptValue ret_keys; int ii=0; // This function needs one argument, parent node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get keys keys=p_hive->GetKeys(context->argument(0).toString()); if(p_hive->Error()) { // Clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } // Build script array ret_keys=engine->newArray(keys.count()); QMapIterator i(keys); while(i.hasNext()) { i.next(); ret_keys.setProperty(ii++,QScriptValue(i.key())); } return ret_keys; } /* * RegistryKeyValueToScript */ QScriptValue ReportEngine::RegistryKeyValueToScript(QScriptEngine *engine, const s_RegistryKeyValue &s) { QScriptValue obj=engine->newObject(); obj.setProperty("type",s.type); obj.setProperty("length",s.length); ByteArray *p_byte_array=new ByteArray(engine); obj.setProperty("value",p_byte_array->newInstance(s.value)); return obj; } /* * RegistryKeyValueFromScriptValue */ void ReportEngine::RegistryKeyValueFromScript(const QScriptValue &obj, s_RegistryKeyValue &s) { s.type=obj.property("type").toInt32(); s.length=obj.property("length").toInt32(); // TODO: Don't know if this works, but it probably does ;) s.value=qvariant_cast(obj.property("value").data().toVariant()); } /* * GetRegistryKeyValue */ QScriptValue ReportEngine::GetRegistryKeyValue(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; QByteArray key_value; int key_type=0; size_t key_length=0; s_RegistryKeyValue script_key_value; // This function needs two arguments, key path and key name if(context->argumentCount()!=2) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); // Get key value key_value=p_hive->GetKeyValue(context->argument(0).toString(), context->argument(1).toString(), &key_type, &key_length); if(p_hive->Error()) { // Get error message to clear error state p_hive->GetErrorMsg(); // printf("\nError: %s\n",p_hive->GetErrorMsg().toAscii().constData()); return engine->undefinedValue(); } // Save key value to s_RegistryKeyValue struct script_key_value.type=key_type; script_key_value.length=key_length; script_key_value.value=key_value; return ReportEngine::RegistryKeyValueToScript(engine,script_key_value); } /* * RegistryKeyValueToString */ QScriptValue ReportEngine::RegistryKeyValueToString(QScriptContext *context, QScriptEngine *engine) { QByteArray key_value; QString ret=""; // This function needs two arguments, key value and value type if(context->argumentCount()!=2) return engine->undefinedValue(); // Cast ByteArray argument to QByteArray and convert key_value=qvariant_cast(context->argument(0).data().toVariant()); ret=RegistryHive::KeyValueToString(key_value, context->argument(1).toInt32()); return engine->newVariant(ret); } /* * RegistryKeyValueToVariant */ QScriptValue ReportEngine::RegistryKeyValueToVariant(QScriptContext *context, QScriptEngine *engine) { int offset=0; int length=-1; bool little_endian=true; QByteArray key_value; QString format=""; QString ret=""; // This function needs at least two arguments, key value and variant type, // and may have three optional arguments, offset, length and little_endian if(context->argumentCount()<2 || context->argumentCount()>5) { return engine->undefinedValue(); } if(context->argumentCount()==3) { offset=context->argument(2).toInt32(); } if(context->argumentCount()==4) { offset=context->argument(2).toInt32(); length=context->argument(3).toInt32(); } if(context->argumentCount()==5) { offset=context->argument(2).toInt32(); length=context->argument(3).toInt32(); little_endian=(context->argument(4).toInt32()==1); } // Cast ByteArray argument to QByteArray key_value=qvariant_cast(context->argument(0).data().toVariant()); format=context->argument(1).toString(); ret=RegistryHive::KeyValueToString(key_value,format,offset,length,little_endian); return engine->newVariant(ret); } +/* + * RegistryKeyValueToStringList + */ +QScriptValue ReportEngine::RegistryKeyValueToStringList(QScriptContext *context, + QScriptEngine *engine) +{ + QByteArray value; + QStringList strings; + QScriptValue ret; + int i=0; + + // This function needs two arguments, key value and key type + if(context->argumentCount()!=2) return engine->undefinedValue(); + + // Cast ByteArray argument to QByteArray and convert + value=qvariant_cast(context->argument(0).data().toVariant()); + strings=RegistryHive::KeyValueToStringList(value, + context->argument(1) + .toInt32()); + + // Build script array + ret=engine->newArray(strings.count()); + QListIterator str_it(strings); + while(str_it.hasNext()) { + ret.setProperty(i++,QScriptValue(str_it.next())); + } + + return ret; +} + /* * RegistryKeyTypeToString */ QScriptValue ReportEngine::RegistryKeyTypeToString(QScriptContext *context, QScriptEngine *engine) { QString ret=""; // This function needs one argument, key type if(context->argumentCount()!=1) return engine->undefinedValue(); ret=RegistryHive::KeyTypeToString(context->argument(0).toInt32()); return engine->newVariant(ret); } /* * GetRegistryNodeModTime */ QScriptValue ReportEngine::GetRegistryNodeModTime(QScriptContext *context, QScriptEngine *engine) { QScriptValue calleeData; RegistryHive *p_hive; int64_t mod_time=0; // This function needs one argument, node path if(context->argumentCount()!=1) return engine->undefinedValue(); // Get calle data (Pointer to RegistryHive class) calleeData=context->callee().data(); p_hive=qobject_cast(calleeData.toQObject()); mod_time=p_hive->GetNodeModTime(context->argument(0).toString()); if(p_hive->Error()) { // Get error message to clear error state p_hive->GetErrorMsg(); return engine->undefinedValue(); } QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(RegistryHive::FiletimeToUnixtime(mod_time)); return engine->newVariant(date_time.toString("yyyy/MM/dd hh:mm:ss")); } /* * GetReportTemplateFileContents */ bool ReportEngine::GetReportTemplateFileContents(QString file, QString &contents) { // Open report template file QFile template_file(file); if(!template_file.open(QIODevice::ReadOnly | QIODevice::Text)) { contents=QString("Couldn't open report template file '%1'!").arg(file); return false; } // Read template file and close it contents.clear(); QTextStream in(&template_file); while(!in.atEnd()) contents.append(in.readLine()).append("\n"); template_file.close(); return true; } /* * UpdateExportedFunctions */ void ReportEngine::UpdateExportedFunctions(RegistryHive *p_hive) { this->p_registry_hive=p_hive; // GetRegistryNodes QScriptValue func_get_nodes=this->newFunction(this->GetRegistryNodes,1); func_get_nodes.setData(this->newQObject(this->p_registry_hive)); this->globalObject().setProperty("GetRegistryNodes",func_get_nodes); // GetRegistryKeys QScriptValue func_get_keys=this->newFunction(this->GetRegistryKeys,1); func_get_keys.setData(this->newQObject(this->p_registry_hive)); this->globalObject().setProperty("GetRegistryKeys",func_get_keys); // GetRegistryKeyValue QScriptValue func_get_key_value=this->newFunction(this->GetRegistryKeyValue, 2); func_get_key_value.setData(this->newQObject(this->p_registry_hive)); this->globalObject().setProperty("GetRegistryKeyValue",func_get_key_value); // GetRegistryNodeModTime QScriptValue func_get_node_modt= this->newFunction(this->GetRegistryNodeModTime,1); func_get_node_modt.setData(this->newQObject(this->p_registry_hive)); this->globalObject().setProperty("GetRegistryNodeModTime",func_get_node_modt); } diff --git a/trunk/reportengine.h b/trunk/reportengine.h index a66e151..df4f376 100644 --- a/trunk/reportengine.h +++ b/trunk/reportengine.h @@ -1,89 +1,91 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef REPORTENGINE_H #define REPORTENGINE_H #include #include #include #include #include #include #include #include "registryhive.h" #include "qtscript_types/bytearray.h" #define FRED_REPORTENGINE_API_VERSION 2 class ReportEngine : public QScriptEngine { Q_OBJECT public: struct s_RegistryKeyValue { int type; int length; QByteArray value; }; RegistryHive *p_registry_hive; QString report_content; ReportEngine(RegistryHive *p_hive); ~ReportEngine(); QMap GetReportTemplateInfo(QString file); bool GenerateReport(RegistryHive *p_hive, QString report_file, QString &report_result, bool console_mode=true); private: ByteArray *p_type_byte_array; static QScriptValue Print(QScriptContext *context, QScriptEngine *engine); static QScriptValue PrintLn(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryNodes(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryKeys(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToScript(QScriptEngine *engine, const s_RegistryKeyValue &s); static void RegistryKeyValueFromScript(const QScriptValue &obj, s_RegistryKeyValue &s); static QScriptValue GetRegistryKeyValue(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToString(QScriptContext *context, QScriptEngine *engine); static QScriptValue RegistryKeyValueToVariant(QScriptContext *context, QScriptEngine *engine); + static QScriptValue RegistryKeyValueToStringList(QScriptContext *context, + QScriptEngine *engine); static QScriptValue RegistryKeyTypeToString(QScriptContext *context, QScriptEngine *engine); static QScriptValue GetRegistryNodeModTime(QScriptContext *context, QScriptEngine *engine); bool GetReportTemplateFileContents(QString file, QString &contents); void UpdateExportedFunctions(RegistryHive *p_hive); }; Q_DECLARE_METATYPE(ReportEngine::s_RegistryKeyValue) #endif // REPORTENGINE_H