Skip to content

Commit b1b169c

Browse files
committed
[FEATURE] Added a new parameter, regulating what type of results should be reported
1 parent 2b05630 commit b1b169c

14 files changed

+192
-59
lines changed

include/pe_sieve_types.h

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ namespace pesieve {
2727
OUT_FILTERS_COUNT
2828
} t_output_filter;
2929

30+
typedef enum {
31+
SHOW_NONE = 0,
32+
SHOW_ERRORS = 1,
33+
SHOW_NOT_SUSPICIOUS = 2,
34+
SHOW_SUSPICIOUS = 4,
35+
SHOW_SUSPICIOUS_AND_ERRORS = SHOW_ERRORS | SHOW_SUSPICIOUS,
36+
SHOW_SUCCESSFUL_ONLY = SHOW_NOT_SUSPICIOUS | SHOW_SUSPICIOUS,
37+
SHOW_ALL = SHOW_ERRORS | SHOW_NOT_SUSPICIOUS | SHOW_SUSPICIOUS,
38+
SHOW_FILTERS_COUNT
39+
} t_results_filter;
40+
3041
typedef enum {
3142
SHELLC_NONE = 0, ///< do not detect shellcode
3243
SHELLC_PATTERNS, ///< detect shellcodes by patterns
@@ -128,6 +139,7 @@ namespace pesieve {
128139
bool make_reflection; ///< operate on a process reflection rather than on the live process (this allows i.e. to force-read inaccessible pages)
129140
bool use_cache; ///< enable cache for the scanned modules
130141
t_json_level json_lvl; ///< level of the details of the JSON report
142+
t_results_filter results_filter; ///< what type of results should be included in the report
131143
char output_dir[MAX_PATH + 1]; ///< the root directory where the output should be saved (default: current directory)
132144
PARAM_STRING modules_ignored; ///< a list of modules that will not be scanned, separated by PARAM_LIST_SEPARATOR
133145
PARAM_STRING pattern_file; ///< a file with additional patterns for code recognition

main.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void print_report(const pesieve::ReportEx& report, const t_params args)
2828

2929
std::string report_str;
3030
if (args.json_output) {
31-
report_str = report_to_json(report, pesieve::REPORT_ALL, ProcessScanReport::REPORT_SUSPICIOUS_AND_ERRORS, args.json_lvl);
31+
report_str = report_to_json(report, pesieve::REPORT_ALL, args.results_filter, args.json_lvl);
3232
} else {
3333
report_str = scan_report_to_string(*report.scan_report);
3434
}
@@ -48,6 +48,7 @@ void free_params(t_params &args)
4848
int main(int argc, char *argv[])
4949
{
5050
t_params args = { 0 };
51+
args.results_filter = SHOW_SUSPICIOUS;
5152

5253
PEsieveParams uParams(PESIEVE_VERSION_STR);
5354
if (argc < 2) {
@@ -81,10 +82,11 @@ int main(int argc, char *argv[])
8182
t_pesieve_res res = PESIEVE_ERROR;
8283
if (report != nullptr) {
8384
print_report(*report, args);
84-
85-
pesieve::t_report summary = report->scan_report->generateSummary();
86-
if (summary.scanned > 0) {
87-
res = (summary.suspicious > 0) ? PESIEVE_DETECTED : PESIEVE_NOT_DETECTED;
85+
if (report->scan_report) {
86+
pesieve::t_report summary = report->scan_report->generateSummary();
87+
if (summary.scanned > 0) {
88+
res = (summary.suspicious > 0) ? PESIEVE_DETECTED : PESIEVE_NOT_DETECTED;
89+
}
8890
}
8991
delete report;
9092
report = nullptr;

params.h

+15
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ using namespace pesieve;
2525
#define PARAM_DUMP_MODE "dmode"
2626
//output options:
2727
#define PARAM_OUT_FILTER "ofilter"
28+
#define PARAM_RESULTS_FILTER "report"
2829
#define PARAM_QUIET "quiet"
2930
#define PARAM_JSON "json"
3031
#define PARAM_JSON_LVL "jlvl"
@@ -82,6 +83,18 @@ class PEsieveParams : public Params
8283
}
8384
}
8485

86+
enumParam = new EnumParam(PARAM_RESULTS_FILTER, "result_type", false);
87+
if (enumParam) {
88+
this->addParam(enumParam);
89+
this->setInfo(PARAM_RESULTS_FILTER, "Define what type of results are reported.");
90+
for (size_t i = SHOW_SUSPICIOUS; i < SHOW_FILTERS_COUNT; i++) {
91+
t_results_filter mode = (t_results_filter)(i);
92+
std::string info = translate_results_filter(mode);
93+
if (info.empty()) continue;
94+
enumParam->addEnumValue(mode, results_filter_to_id(i), info);
95+
}
96+
}
97+
8598
this->addParam(new StringListParam(PARAM_MODULES_IGNORE, false, PARAM_LIST_SEPARATOR));
8699
{
87100
std::stringstream ss1;
@@ -202,6 +215,7 @@ class PEsieveParams : public Params
202215
this->addParamToGroup(PARAM_JSON, str_group);
203216
this->addParamToGroup(PARAM_JSON_LVL, str_group);
204217
this->addParamToGroup(PARAM_OUT_FILTER, str_group);
218+
this->addParamToGroup(PARAM_RESULTS_FILTER, str_group);
205219

206220
str_group = "1. scanner settings";
207221
this->addGroup(new ParamGroup(str_group));
@@ -253,6 +267,7 @@ class PEsieveParams : public Params
253267
copyVal<IntParam>(PARAM_PID, ps.pid);
254268
copyVal<EnumParam>(PARAM_IMP_REC, ps.imprec_mode);
255269
copyVal<EnumParam>(PARAM_OUT_FILTER, ps.out_filter);
270+
copyVal<EnumParam>(PARAM_RESULTS_FILTER, ps.results_filter);
256271

257272
fillStringParam(PARAM_MODULES_IGNORE, ps.modules_ignored);
258273

params_info/pe_sieve_params_info.cpp

+35-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ std::string pesieve::translate_dump_mode(const DWORD dump_mode)
1616
case pesieve::PE_DUMP_REALIGN:
1717
return "realigned raw (converted raw format to be the same as virtual)";
1818
}
19-
return "undefined";
19+
return "";
2020
}
2121

2222
std::string pesieve::dump_mode_to_id(const DWORD dump_mode)
@@ -44,7 +44,33 @@ std::string pesieve::translate_out_filter(const pesieve::t_output_filter o_filte
4444
case pesieve::OUT_NO_DIR:
4545
return "don't dump any files";
4646
}
47-
return "undefined";
47+
return "";
48+
}
49+
50+
std::string pesieve::translate_results_filter(const pesieve::t_results_filter r_filter)
51+
{
52+
switch (r_filter) {
53+
case pesieve::SHOW_SUSPICIOUS:
54+
return "only suspicious (default)";
55+
case pesieve::SHOW_SUSPICIOUS_AND_ERRORS:
56+
return "suspicious and errors";
57+
case pesieve::SHOW_ALL:
58+
return "all scanned";
59+
}
60+
return "";
61+
}
62+
63+
std::string pesieve::results_filter_to_id(const DWORD r_filter)
64+
{
65+
switch (r_filter) {
66+
case pesieve::SHOW_SUSPICIOUS:
67+
return "S";
68+
case pesieve::SHOW_SUSPICIOUS_AND_ERRORS:
69+
return "SE";
70+
case pesieve::SHOW_ALL:
71+
return "L";
72+
}
73+
return "";
4874
}
4975

5076
std::string pesieve::translate_imprec_mode(const pesieve::t_imprec_mode imprec_mode)
@@ -63,7 +89,7 @@ std::string pesieve::translate_imprec_mode(const pesieve::t_imprec_mode imprec_m
6389
case pesieve::PE_IMPREC_REBUILD2:
6490
return "build the ImportTable from scratch, basing on the found IATs:\n\t use all found blocks (aggressive mode)";
6591
}
66-
return "undefined";
92+
return "";
6793
}
6894

6995

@@ -101,7 +127,7 @@ std::string pesieve::translate_dotnet_policy(const pesieve::t_dotnet_policy &mod
101127
case pesieve::PE_DNET_SKIP_ALL:
102128
return "skip all the above (mapping, shellcodes, hooks)";
103129
}
104-
return "undefined";
130+
return "";
105131
}
106132

107133
std::string pesieve::translate_data_mode(const pesieve::t_data_scan_mode &mode)
@@ -120,7 +146,7 @@ std::string pesieve::translate_data_mode(const pesieve::t_data_scan_mode &mode)
120146
case pesieve::PE_DATA_SCAN_INACCESSIBLE_ONLY:
121147
return "scan inaccessible pages, but exclude other non-executable;\n\t works in reflection mode (/refl) only";
122148
}
123-
return "undefined";
149+
return "";
124150
}
125151

126152
std::string pesieve::translate_json_level(const pesieve::t_json_level &mode)
@@ -133,7 +159,7 @@ std::string pesieve::translate_json_level(const pesieve::t_json_level &mode)
133159
case pesieve::JSON_DETAILS2:
134160
return "details #2 (list patches: extended)";
135161
}
136-
return "undefined";
162+
return "";
137163
}
138164

139165
std::string pesieve::shellc_mode_mode_to_id(const pesieve::t_shellc_mode& mode)
@@ -165,7 +191,7 @@ std::string pesieve::translate_shellc_mode(const pesieve::t_shellc_mode& mode)
165191
case pesieve::SHELLC_PATTERNS_AND_STATS:
166192
return "detect shellcodes by patterns and stats (both match)";
167193
}
168-
return "undefined";
194+
return "";
169195
}
170196

171197
std::string pesieve::translate_obfusc_mode(const pesieve::t_obfusc_mode& mode)
@@ -180,7 +206,7 @@ std::string pesieve::translate_obfusc_mode(const pesieve::t_obfusc_mode& mode)
180206
case pesieve::OBFUSC_ANY:
181207
return "detect any: possible strong or weak encryption";
182208
}
183-
return "undefined";
209+
return "";
184210
}
185211

186212
std::string pesieve::obfusc_mode_mode_to_id(const pesieve::t_obfusc_mode& mode)
@@ -209,5 +235,5 @@ std::string pesieve::translate_iat_scan_mode(const pesieve::t_iat_scan_mode mode
209235
case pesieve::PE_IATS_UNFILTERED:
210236
return "unfiltered: scan for IAT Hooks, report all";
211237
}
212-
return "undefined";
238+
return "";
213239
}

params_info/pe_sieve_params_info.h

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
namespace pesieve {
77
std::string translate_dump_mode(const DWORD dump_mode);
88
std::string translate_out_filter(const pesieve::t_output_filter o_filter);
9+
std::string translate_results_filter(const pesieve::t_results_filter r_filter);
10+
std::string results_filter_to_id(const DWORD r_filter);
911
std::string translate_data_mode(const pesieve::t_data_scan_mode &mode);
1012
std::string translate_imprec_mode(const pesieve::t_imprec_mode imprec_mode);
1113
std::string translate_dotnet_policy(const pesieve::t_dotnet_policy &mode);

pe_sieve.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pesieve::PatternMatcher g_Matcher;
2424
pesieve::SyscallTable g_SyscallTable;
2525

2626
namespace pesieve {
27+
2728
void check_access_denied(DWORD processID)
2829
{
2930
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processID);
@@ -126,7 +127,7 @@ namespace pesieve {
126127
ProcessDumpReport* dumpReport = nullptr;
127128
ResultsDumper dumper(expand_path(args.output_dir), args.quiet);
128129

129-
if (dumper.dumpJsonReport(process_report, ProcessScanReport::REPORT_SUSPICIOUS_AND_ERRORS, args.json_lvl) && !args.quiet) {
130+
if (dumper.dumpJsonReport(process_report, args.results_filter, args.json_lvl) && !args.quiet) {
130131
std::cout << "[+] Report dumped to: " << dumper.getOutputDir() << std::endl;
131132
}
132133

@@ -248,19 +249,20 @@ pesieve::ReportEx* pesieve::scan_and_dump(IN const pesieve::t_params args)
248249
const bool is_reflection = (cloned_proc) ? true : false;
249250
ProcessScanner scanner(target_proc, is_reflection, args);
250251
report->scan_report = scanner.scanRemote();
251-
252252
if (report->scan_report) {
253253
// dump elements from the process:
254254
report->dump_report = make_dump(target_proc, is_reflection, args, *report->scan_report);
255255
}
256256
}
257257
catch (std::exception &e) {
258-
delete report;
259-
report = nullptr;
260-
258+
report->error_report = new ErrorReport(args.pid, e.what());
261259
if (!args.quiet) {
262260
util::print_in_color(ERROR_COLOR, std::string("[ERROR] ") + e.what() + "\n", true);
263261
}
262+
ResultsDumper dumper(expand_path(args.output_dir), args.quiet);
263+
if (dumper.dumpJsonReport(*report->error_report, args.results_filter) && !args.quiet) {
264+
std::cout << "[+] Report dumped to: " << dumper.getOutputDir() << std::endl;
265+
}
264266
}
265267
if (cloned_proc) {
266268
release_process_reflection(&cloned_proc);

pe_sieve_api.cpp

+11-9
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ using namespace pesieve;
1313

1414
size_t print_report(const pesieve::ReportEx& report, const pesieve::t_params args, const t_report_type rtype, char* json_buf, size_t json_buf_size)
1515
{
16-
if (!report.scan_report || rtype == REPORT_NONE) return 0;
17-
16+
if (rtype == REPORT_NONE) return 0;
17+
1818
size_t level = 1;
19-
std::string report_str = report_to_json(report, rtype, ProcessScanReport::REPORT_SUSPICIOUS_AND_ERRORS, args.json_lvl, level);
19+
std::string report_str = report_to_json(report, rtype, args.report_filter, args.json_lvl, level);
2020
const size_t report_len = report_str.length();
2121

2222
if (json_buf && json_buf_size) {
@@ -35,13 +35,15 @@ PEsieve_report PESIEVE_API_FUNC PESieve_scan_ex(IN const PEsieve_params &args, I
3535
return empty;
3636
}
3737
const pesieve::ReportEx* report = pesieve::scan_and_dump(args);
38-
if (report == nullptr) {
39-
pesieve::t_report nullrep = { 0 };
40-
nullrep.pid = args.pid;
41-
nullrep.errors = pesieve::ERROR_SCAN_FAILURE;
42-
return nullrep;
38+
pesieve::t_report summary = { 0 };
39+
summary.pid = args.pid;
40+
summary.errors = pesieve::ERROR_SCAN_FAILURE;
41+
if (!report) {
42+
return summary;
43+
}
44+
if (report->scan_report) {
45+
summary = report->scan_report->generateSummary();
4346
}
44-
pesieve::t_report summary = report->scan_report->generateSummary();
4547
//check the pointers:
4648
if (json_buf) {
4749
if (!json_buf_size || IsBadWritePtr(json_buf, json_buf_size)) {

pe_sieve_report.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,36 @@
1313

1414
namespace pesieve {
1515

16+
class ErrorReport
17+
{
18+
public:
19+
ErrorReport(DWORD _pid, const std::string &_message)
20+
: pid(_pid), message(_message)
21+
{
22+
}
23+
24+
const DWORD pid;
25+
const std::string message;
26+
};
27+
1628
//! The final report about the actions performed on the process: scanning and dumping
1729
class ReportEx {
1830
public:
1931
ReportEx() :
20-
scan_report(nullptr), dump_report(nullptr)
32+
scan_report(nullptr), dump_report(nullptr), error_report(nullptr)
2133
{
2234
}
2335

2436
~ReportEx()
2537
{
2638
delete scan_report;
2739
delete dump_report;
40+
delete error_report;
2841
}
2942

3043
ProcessScanReport* scan_report; ///< the report aggregating the results of the performed scans
3144
ProcessDumpReport* dump_report; ///< the report aggregating the results of the performed dumps
45+
ErrorReport* error_report; ///< the report detailing on possible errors that prevented the scan
3246
};
3347

3448
};

postprocessors/report_formatter.cpp

+40-4
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,37 @@ std::string pesieve::scan_report_to_string(const ProcessScanReport &process_repo
3636
return stream.str();
3737
}
3838

39+
std::string pesieve::err_report_to_json(const pesieve::ErrorReport& err_report,
40+
t_results_filter filter,
41+
size_t start_level
42+
)
43+
{
44+
if ((filter & SHOW_ERRORS) == 0) {
45+
return "";
46+
}
47+
//summary:
48+
std::stringstream stream;
49+
50+
size_t level = start_level + 1;
51+
OUT_PADDED(stream, start_level, "{\n"); // beginning of the report
52+
53+
OUT_PADDED(stream, level, "\"pid\" : ");
54+
stream << std::dec << err_report.pid << ",\n";
55+
OUT_PADDED(stream, level, "\"err_message\" : ");
56+
stream << "\"" << err_report.message << "\"\n";
57+
OUT_PADDED(stream, start_level, "}\n"); // end of the report
58+
59+
std::string report_all = stream.str();
60+
if (report_all.length() == 0) {
61+
return "";
62+
}
63+
return report_all;
64+
}
65+
66+
3967
std::string pesieve::scan_report_to_json(
4068
const ProcessScanReport &process_report,
41-
ProcessScanReport::t_report_filter filter,
69+
t_results_filter filter,
4270
const pesieve::t_json_level &jdetails,
4371
size_t start_level
4472
)
@@ -75,15 +103,23 @@ std::string pesieve::dump_report_to_json(
75103
return report_all;
76104
}
77105

78-
std::string pesieve::report_to_json(const pesieve::ReportEx& report, const t_report_type rtype, ProcessScanReport::t_report_filter filter, const pesieve::t_json_level& jdetails, size_t start_level)
106+
std::string pesieve::report_to_json(const pesieve::ReportEx& report, const t_report_type rtype, t_results_filter filter, const pesieve::t_json_level& jdetails, size_t start_level)
79107
{
80-
if (!report.scan_report || rtype == REPORT_NONE) return 0;
108+
if (rtype == REPORT_NONE) return 0;
81109

82110
size_t level = 1;
83111
std::stringstream stream;
112+
113+
if (report.error_report && (filter & SHOW_ERRORS)) {
114+
stream << "{\n";
115+
OUT_PADDED(stream, level, "\"error_report\" :\n");
116+
stream << err_report_to_json(*report.error_report, filter, level);
117+
stream << "}\n";
118+
return stream.str();
119+
}
84120
const bool has_dumps = (report.dump_report && report.dump_report->countDumped() > 0) ? true : false;
85121
stream << "{\n";
86-
if (rtype == REPORT_ALL || rtype == REPORT_SCANNED) {
122+
if (report.scan_report && (rtype == REPORT_ALL || rtype == REPORT_SCANNED)) {
87123
OUT_PADDED(stream, level, "\"scan_report\" :\n");
88124
stream << scan_report_to_json(*report.scan_report, filter, jdetails, level);
89125
if (rtype == REPORT_ALL && has_dumps) {

0 commit comments

Comments
 (0)