From fe5f81b1656f89e1dc338f7a6af1b2028fb034d1 Mon Sep 17 00:00:00 2001 From: hasherezade Date: Fri, 1 Nov 2024 14:54:19 -0700 Subject: [PATCH] [FEATURE] Added new argument: rebase to regulate if the dumped module should be rebased to its original base --- include/pe_sieve_types.h | 7 ++++--- params.h | 9 +++++++-- pe_sieve.cpp | 2 +- postprocessors/results_dumper.cpp | 10 +++++++--- postprocessors/results_dumper.h | 11 ++++++++++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/pe_sieve_types.h b/include/pe_sieve_types.h index 5ec19e84a..349096ebc 100644 --- a/include/pe_sieve_types.h +++ b/include/pe_sieve_types.h @@ -56,9 +56,9 @@ namespace pesieve { } t_obfusc_mode; typedef enum { - PE_IMPREC_NONE = 0, ///< do not try to recover imports - PE_IMPREC_AUTO, ///< try to autodetect the most suitable mode - PE_IMPREC_UNERASE, ///< recover erased parts of the partialy damaged import table + PE_IMPREC_NONE = 0, ///< do not try to recover imports + PE_IMPREC_AUTO, ///< try to autodetect the most suitable mode + PE_IMPREC_UNERASE, ///< recover erased parts of the partialy damaged import table PE_IMPREC_REBUILD0, ///< build the import table from the scratch, basing on the found IAT(s): use only terminated blocks (restrictive mode) PE_IMPREC_REBUILD1, ///< build the import table from the scratch, basing on the found IAT(s): use terminated blocks, or blocks with more than 1 thunk PE_IMPREC_REBUILD2, ///< build the import table from the scratch, basing on the found IAT(s): use all found blocks (aggressive mode) @@ -134,6 +134,7 @@ namespace pesieve { t_iat_scan_mode iat; ///< detect IAT hooking t_data_scan_mode data; ///< should scan non-executable pages? bool minidump; ///< make minidump of full process + bool rebase; ///< rebase the module to its original base (if known) t_dump_mode dump_mode; ///< in which mode the detected PE implants should be dumped bool json_output; ///< display the final summary as the JSON report bool make_reflection; ///< operate on a process reflection rather than on the live process (this allows i.e. to force-read inaccessible pages) diff --git a/params.h b/params.h index 997ba80d8..eb2a25237 100644 --- a/params.h +++ b/params.h @@ -23,6 +23,7 @@ using namespace pesieve; //dump options: #define PARAM_IMP_REC "imp" #define PARAM_DUMP_MODE "dmode" +#define PARAM_REBASE "rebase" //output options: #define PARAM_OUT_FILTER "ofilter" #define PARAM_RESULTS_FILTER "report" @@ -103,7 +104,10 @@ class PEsieveParams : public Params ss2 << INFO_SPACER << "Example: kernel32.dll" << PARAM_LIST_SEPARATOR << "user32.dll"; this->setInfo(PARAM_MODULES_IGNORE, ss1.str(), ss2.str()); } - + + this->addParam(new BoolParam(PARAM_REBASE, false)); + this->setInfo(PARAM_REBASE, "Rebase the module to its original base (if known)."); + this->addParam(new BoolParam(PARAM_QUIET, false)); this->setInfo(PARAM_QUIET, "Print only the summary. Do not log on stdout during the scan."); @@ -236,6 +240,7 @@ class PEsieveParams : public Params this->addParamToGroup(PARAM_MINIDUMP, str_group); this->addParamToGroup(PARAM_IMP_REC, str_group); this->addParamToGroup(PARAM_DUMP_MODE, str_group); + this->addParamToGroup(PARAM_REBASE, str_group); str_group = "2. scan exclusions"; this->addGroup(new ParamGroup(str_group)); @@ -270,7 +275,7 @@ class PEsieveParams : public Params copyVal(PARAM_RESULTS_FILTER, ps.results_filter); fillStringParam(PARAM_MODULES_IGNORE, ps.modules_ignored); - + copyVal(PARAM_REBASE, ps.rebase); copyVal(PARAM_QUIET, ps.quiet); copyVal(PARAM_JSON, ps.json_output); diff --git a/pe_sieve.cpp b/pe_sieve.cpp index 051a1e177..9e074ea6f 100644 --- a/pe_sieve.cpp +++ b/pe_sieve.cpp @@ -137,7 +137,7 @@ namespace pesieve { dump_mode = pesieve::t_dump_mode(args.dump_mode); } size_t dumped_modules = 0; - dumpReport = dumper.dumpDetectedModules(hProcess, isRefl, process_report, dump_mode, args.imprec_mode); + dumpReport = dumper.dumpDetectedModules(hProcess, isRefl, process_report, dump_mode, args.imprec_mode, args.rebase); if (dumpReport && dumpReport->countDumped()) { dumped_modules = dumpReport->countDumped(); } diff --git a/postprocessors/results_dumper.cpp b/postprocessors/results_dumper.cpp index fc60c70a8..de56f9c82 100644 --- a/postprocessors/results_dumper.cpp +++ b/postprocessors/results_dumper.cpp @@ -206,7 +206,8 @@ pesieve::ProcessDumpReport* pesieve::ResultsDumper::dumpDetectedModules( bool isRefl, ProcessScanReport &process_report, const pesieve::t_dump_mode dump_mode, - const t_imprec_mode imprec_mode) + const t_imprec_mode imprec_mode, + const bool rebase) { if (processHandle == nullptr) { return nullptr; @@ -222,6 +223,7 @@ pesieve::ProcessDumpReport* pesieve::ResultsDumper::dumpDetectedModules( if (mod->status != SCAN_SUSPICIOUS) { continue; } + ULONGLONG out_base = rebase ? mod->origBase : 0; dumpModule(processHandle, isRefl, process_report.modulesInfo, @@ -229,6 +231,7 @@ pesieve::ProcessDumpReport* pesieve::ResultsDumper::dumpDetectedModules( process_report.exportsMap, dump_mode, imprec_mode, + out_base, *dumpReport ); } @@ -260,6 +263,7 @@ bool pesieve::ResultsDumper::dumpModule(IN HANDLE processHandle, IN const peconv::ExportsMapper *exportsMap, IN const pesieve::t_dump_mode dump_mode, IN const t_imprec_mode imprec_mode, + IN ULONGLONG out_base, OUT ProcessDumpReport &dumpReport ) { @@ -321,8 +325,8 @@ bool pesieve::ResultsDumper::dumpModule(IN HANDLE processHandle, modDumpReport->impRecMode = get_imprec_res_name(imprec_res); module_buf.setRelocBase(mod->getRelocBase()); - if (mod->origBase) { - module_buf.setRelocBase(mod->origBase); + if (out_base) { + module_buf.setRelocBase(out_base); } if (imprec_mode == pesieve::PE_IMPREC_NONE) { modDumpReport->isDumped = module_buf.dumpPeToFile(modDumpReport->dumpFileName, curr_dump_mode); diff --git a/postprocessors/results_dumper.h b/postprocessors/results_dumper.h index 7a035842f..99b7ce953 100644 --- a/postprocessors/results_dumper.h +++ b/postprocessors/results_dumper.h @@ -18,7 +18,14 @@ namespace pesieve { } // dump all modules detected as suspicious during the process scan - ProcessDumpReport* dumpDetectedModules(HANDLE hProcess, bool isRefl, ProcessScanReport &process_report, const pesieve::t_dump_mode dump_mode, const pesieve::t_imprec_mode imprec_mode); + ProcessDumpReport* dumpDetectedModules( + HANDLE hProcess, + bool isRefl, + ProcessScanReport &process_report, + const pesieve::t_dump_mode dump_mode, + const t_imprec_mode imprec_mode, + const bool rebase + ); // dump JSON report from the process scan bool dumpJsonReport(ProcessScanReport &process_report, const t_results_filter &filter, const pesieve::t_json_level &jdetails); @@ -42,6 +49,7 @@ namespace pesieve { \param modReport : ModuleScanReport defining artefacts to be dumped \param exportsMap : mapping of all the exported APIs available within the process (for imports reconstruction) \param imprec_mode : mode in which imports reconstruction will be attempted + \param out_base : the base to which the output module should be rebased, 0 if default \param dumpReport : ProcessDumpReport to which reports from the current dump will be appended */ bool dumpModule( @@ -52,6 +60,7 @@ namespace pesieve { IN const peconv::ExportsMapper *exportsMap, IN const pesieve::t_dump_mode dump_mode, IN const pesieve::t_imprec_mode imprec_mode, + IN ULONGLONG out_base, OUT ProcessDumpReport &dumpReport );