Skip to content

Commit 5fa5008

Browse files
committed
Merge branch 'watch_file'
2 parents 7729772 + afc89a5 commit 5fa5008

13 files changed

+296
-67
lines changed

driver_comm.cpp

+25-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
#include <iostream>
44

55
struct ProcessData {
6-
unsigned long Id;
6+
DWORD Id;
7+
};
8+
9+
struct ProcessDataEx {
10+
DWORD Id;
11+
LONGLONG fileId;
712
};
813

914
#define DRIVER_PATH L"\\\\.\\MalUnpackCompanion"
@@ -124,9 +129,26 @@ bool driver::fetch_watched_files(DWORD startPID, LONGLONG out_buffer[], size_t o
124129
}
125130

126131

127-
bool driver::watch_pid(DWORD pid)
132+
bool driver::watch_pid(DWORD pid, ULONGLONG fileId)
128133
{
129-
return driver::request_action_on_pid(IOCTL_MUNPACK_COMPANION_ADD_TO_WATCHED, pid);
134+
if (!pid) {
135+
return false;
136+
}
137+
HANDLE hDevice = CreateFileW(DRIVER_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
138+
if (hDevice == INVALID_HANDLE_VALUE) {
139+
std::cerr << "Failed to open device" << std::endl;
140+
return false;
141+
}
142+
143+
ProcessDataEx data = { 0 };
144+
data.Id = pid;
145+
data.fileId = fileId;
146+
147+
BOOL success = FALSE;
148+
DWORD returned = 0;
149+
success = DeviceIoControl(hDevice, IOCTL_MUNPACK_COMPANION_ADD_TO_WATCHED, &data, sizeof(data), nullptr, 0, &returned, nullptr);
150+
CloseHandle(hDevice);
151+
return success == TRUE ? true : false;
130152
}
131153

132154
bool driver::kill_watched_pid(DWORD pid)

driver_comm.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace driver {
66

77
bool is_ready();
88

9-
bool watch_pid(DWORD pid);
9+
bool watch_pid(DWORD pid, ULONGLONG fileId);
1010

1111
bool kill_watched_pid(DWORD pid);
1212

file_util.cpp

+70
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,79 @@ namespace file_util {
5353
return (got_len != 0) ? true: false;
5454
}
5555

56+
NTSTATUS FetchFileId(HANDLE hFile, LONGLONG& FileId)
57+
{
58+
FileId = FILE_INVALID_FILE_ID;
59+
60+
if (!hFile) {
61+
return STATUS_INVALID_PARAMETER;
62+
}
63+
64+
NTSTATUS status = STATUS_UNSUCCESSFUL;
65+
__try
66+
{
67+
IO_STATUS_BLOCK ioStatusBlock;
68+
FILE_INTERNAL_INFORMATION fileIdInfo;
69+
status = ZwQueryInformationFile(
70+
hFile,
71+
&ioStatusBlock,
72+
&fileIdInfo,
73+
sizeof(fileIdInfo),
74+
FileInternalInformation
75+
);
76+
if (NT_SUCCESS(status)) {
77+
FileId = fileIdInfo.IndexNumber.QuadPart;
78+
}
79+
}
80+
__except (EXCEPTION_EXECUTE_HANDLER)
81+
{
82+
status = STATUS_UNSUCCESSFUL;
83+
}
84+
return status;
85+
}
5686
};
5787

5888

89+
std::wstring file_util::get_file_path(const char* file_name)
90+
{
91+
wchar_t full_path[MAX_PATH] = { 0 };
92+
93+
HANDLE hFile = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
94+
DWORD got_len = GetFinalPathNameByHandleW(hFile, full_path, MAX_PATH, VOLUME_NAME_DOS);
95+
CloseHandle(hFile);
96+
97+
if (!got_len) {
98+
return L"";
99+
}
100+
101+
wchar_t* prefix = L"\\\\?\\";
102+
size_t prefix_len = wcslen(prefix);
103+
104+
if (got_len < prefix_len) {
105+
return full_path;
106+
}
107+
if (wcsncmp(prefix, full_path, prefix_len) == 0) {
108+
// skip the prefix
109+
return full_path + prefix_len;
110+
}
111+
return full_path;
112+
}
113+
114+
ULONGLONG file_util::get_file_id(const char* img_path)
115+
{
116+
HANDLE file = CreateFileA(img_path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
117+
118+
LONGLONG FileId = FILE_INVALID_FILE_ID;
119+
NTSTATUS status = FetchFileId(file, FileId);
120+
121+
CloseHandle(file);
122+
123+
if (NT_SUCCESS(status)) {
124+
return FileId;
125+
}
126+
return FILE_INVALID_FILE_ID;
127+
}
128+
59129
size_t file_util::file_ids_to_names(std::set<LONGLONG>& filesIds, std::set<std::wstring>& names)
60130
{
61131
FILE_ID_DESCRIPTOR FileDesc = { 0 };

file_util.h

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
namespace file_util {
99

10+
std::wstring get_file_path(const char* filename);
11+
12+
ULONGLONG get_file_id(const char* img_path);
13+
1014
size_t file_ids_to_names(std::set<LONGLONG>& filesIds, std::set<std::wstring> &names);
1115

1216
size_t delete_dropped_files(std::set<std::wstring>& names);

main.cpp

+36-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "process_util.h"
1818
#include "util.h"
1919
#include "version.h"
20+
#include "file_util.h"
2021

2122
#define WAIT_FOR_PROCESS_TIMEOUT 5000
2223

@@ -46,6 +47,30 @@ void init_defaults(t_params_struct &params)
4647
#endif
4748
}
4849

50+
bool get_watched_file_id(const t_params_struct& params, ULONGLONG &file_id)
51+
{
52+
bool is_diffrent = false;
53+
file_id = FILE_INVALID_FILE_ID;
54+
55+
if (strnlen(params.img_path, MAX_PATH) > 0
56+
&& strncmp(params.img_path, params.exe_path, MAX_PATH) != 0)
57+
{
58+
file_id = file_util::get_file_id(params.img_path);
59+
is_diffrent = true;
60+
}
61+
if (file_id == FILE_INVALID_FILE_ID) {
62+
file_id = file_util::get_file_id(params.exe_path);
63+
is_diffrent = false;
64+
}
65+
if (is_diffrent) {
66+
std::cout << "[*] Watch respawns from the IMG: " << params.img_path << "\n";
67+
}
68+
else {
69+
std::cout << "[*] Watch respawns from main EXE file: " << params.exe_path << "\n";
70+
}
71+
return is_diffrent;
72+
}
73+
4974
int main(int argc, char* argv[])
5075
{
5176
UnpackParams uParams(VERSION);
@@ -66,10 +91,10 @@ int main(int argc, char* argv[])
6691
}
6792
uParams.fillStruct(params);
6893
if (params.hh_args.pesieve_args.use_cache) {
69-
std::cerr << "[*] Cache is Enabled!" << std::endl;
94+
std::cout << "[*] Cache is Enabled!" << std::endl;
7095
}
7196
else {
72-
std::cerr << "[*] Cache is Disabled!" << std::endl;
97+
std::cout << "[*] Cache is Disabled!" << std::endl;
7398
}
7499
params.hh_args.kill_suspicious = true;
75100
// if the timeout was chosen as the trigger, don't interfere in the process:
@@ -86,7 +111,7 @@ int main(int argc, char* argv[])
86111
std::cout << "Starting the process: " << params.exe_path << std::endl;
87112
std::cout << "With commandline: \"" << params.exe_cmd << "\"" << std::endl;
88113

89-
char* file_name = get_file_name(params.exe_path);
114+
const char* file_name = get_file_name(params.exe_path);
90115
std::cout << "Exe name: " << file_name << std::endl;
91116

92117
DWORD timeout = params.timeout;
@@ -98,13 +123,17 @@ int main(int argc, char* argv[])
98123

99124
t_pesieve_res ret_code = PESIEVE_ERROR;
100125
const DWORD flags = DETACHED_PROCESS | CREATE_NO_WINDOW;
101-
HANDLE proc = make_new_process(params.exe_path, params.exe_cmd, flags);
126+
127+
ULONGLONG file_id;
128+
bool is_img_diff = get_watched_file_id(params, file_id);
129+
HANDLE proc = make_new_process(params.exe_path, params.exe_cmd, flags, file_id);
102130
if (!proc) {
103131
std::cerr << "Could not start the process!" << std::endl;
104132
return ret_code;
105133
}
106-
107-
params.hh_args.pname = file_name;
134+
params.hh_args.is_main_module = is_img_diff ? false : true;
135+
params.hh_args.module_path = (is_img_diff) ? file_util::get_file_path(params.img_path) : file_util::get_file_path(params.exe_path);
136+
std::wcout << "Module Path retrieved: " << params.hh_args.module_path << "\n";
108137
params.hh_args.start_pid = GetProcessId(proc);
109138

110139
std::string out_dir = make_dir_name(root_dir, time(NULL));
@@ -150,7 +179,7 @@ int main(int argc, char* argv[])
150179
finalStats.scanTime = GetTickCount64() - start_tick;
151180

152181
//this works only with the companion driver:
153-
if (scanner.collectDroppedFiles()) {
182+
if (scanner.collectDroppedFiles(file_id)) {
154183
std::cout << "The process dropped some files!\n";
155184
}
156185

params.h

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using namespace paramkit;
99
#define DEFAULT_TIMEOUT 1000
1010

1111
#define PARAM_EXE "exe"
12+
#define PARAM_IMG "img"
1213
#define PARAM_CMD "cmd"
1314
#define PARAM_TIMEOUT "timeout"
1415
#define PARAM_OUT_DIR "dir"
@@ -32,6 +33,7 @@ typedef struct {
3233
char exe_path[MAX_PATH];
3334
char exe_cmd[MAX_PATH];
3435
char out_dir[MAX_PATH];
36+
char img_path[MAX_PATH];
3537
DWORD timeout;
3638
t_term_trigger trigger;
3739
UnpackScanner::t_unp_params hh_args;
@@ -94,6 +96,10 @@ class UnpackParams : public Params
9496
this->addParam(new StringParam(PARAM_EXE, true));
9597
this->setInfo(PARAM_EXE, "Input exe (to be run)");
9698

99+
this->addParam(new StringParam(PARAM_IMG, false));
100+
this->setInfo(PARAM_IMG, "Path to the image from which the malware was run (may be a DLL or EXE).\n\t DEFAULT: same as /exe",
101+
"\t This allows to follow processes respawned from the given image.");
102+
97103
this->addParam(new StringParam(PARAM_CMD, false));
98104
this->setInfo(PARAM_CMD, "Commandline arguments for the input exe");
99105

@@ -197,6 +203,7 @@ class UnpackParams : public Params
197203
void fillStruct(t_params_struct &ps)
198204
{
199205
copyCStr<StringParam>(PARAM_EXE, ps.exe_path, sizeof(ps.exe_path));
206+
copyCStr<StringParam>(PARAM_IMG, ps.img_path, sizeof(ps.img_path));
200207
copyCStr<StringParam>(PARAM_CMD, ps.exe_cmd, sizeof(ps.exe_cmd));
201208
copyCStr<StringParam>(PARAM_OUT_DIR, ps.out_dir, sizeof(ps.out_dir));
202209

0 commit comments

Comments
 (0)