forked from glmcdona/Process-Dump
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclose_watcher.cpp
174 lines (146 loc) · 4.5 KB
/
close_watcher.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "stdafx.h"
#include "close_watcher.h"
close_watcher::close_watcher(pe_hash_database* clean_db, PD_OPTIONS* options)
{
_clean_db = clean_db;
_options = options;
_monitoring_thread = NULL;
_monitor_request_stop = false;
}
bool close_watcher::start_monitor()
{
// Create the main monitoring thread
if (_monitoring_thread == NULL)
{
_monitor_request_stop = false;
_monitoring_thread = new thread(&close_watcher::_monitor_dump_on_close, this);
printf("Started monitoring for process closes.\r\n");
}
return true;
}
bool close_watcher::stop_monitor()
{
if (_monitoring_thread != NULL)
{
// Cleanly exit the main thread
_monitor_request_stop = true;
_monitoring_thread->join();
delete _monitoring_thread;
_monitoring_thread = NULL;
printf("Stopped monitoring for process closes.\r\n");
}
return true;
}
void close_watcher::_monitor_dump_on_close()
{
// List of processes hooked
unordered_set<DWORD> hooked_pids;
unordered_map<DWORD, dump_process*> hooked_processes;
// Create our threads that process the dumping of processes as they close
thread** threads = new thread*[_options->NumberOfThreads];
for (int i = 0; i < _options->NumberOfThreads; i++)
{
threads[i] = new thread(&close_watcher::_dump_process_worker_and_close, this);
}
// Hook all processes terminates
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
DWORD myPid = GetCurrentProcessId();
while (!_monitor_request_stop)
{
// Keep hooking any new processes
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (snapshot != INVALID_HANDLE_VALUE)
{
if (Process32First(snapshot, &entry) == TRUE)
{
while (Process32Next(snapshot, &entry) == TRUE)
{
if ( myPid != entry.th32ProcessID && hooked_pids.count(entry.th32ProcessID) == 0)
{
if (_wcsicmp(entry.szExeFile, L"csrss.exe") != 0) // TEMPORARY FIX TO ISSUE #10 CRASHING CSRSS.EXE
{
// Test code to only hook notepad.exe
//if (_wcsicmp(entry.szExeFile, L"notepad.exe") == 0)
//{
// New process
dump_process* dumper = new dump_process(entry.th32ProcessID, _clean_db, _options, true);
if (dumper->monitor_close_start())
{
printf("...hooked close of: pid 0x%x,%S\r\n", entry.th32ProcessID, entry.szExeFile);
hooked_processes.insert(std::pair<DWORD, dump_process*>(dumper->get_pid(), dumper));
hooked_pids.insert(dumper->get_pid());
}
else
delete dumper;
//}
}
}
}
}
CloseHandle(snapshot);
}
// Check if any processes are waiting to close
for (unordered_map<DWORD, dump_process*>::iterator it = hooked_processes.begin(); it != hooked_processes.end(); )
{
if (it->second->monitor_close_is_waiting())
{
// Dump this process by adding it to the multi-threaded dumping queue
char name[0x200];
it->second->get_process_name(name, sizeof(name));
printf("Process %s requesting to close, we are dumping it...\r\n", name);
_work_queue.push(it->second); // Will be freed when it gets processed from work queue
// Remove this process
it = hooked_processes.erase(it);
}
else
{
it++;
}
}
Sleep(10);
}
// Wait for the work queue to finish processing
while (!_work_queue.empty())
{
printf("waiting for dump commands to be pulled from work queue...\r\n");
Sleep(200);
}
// Wait for all worker threads to complete
for (int i = 0; i < _options->NumberOfThreads; i++)
{
threads[i]->join(); // blocks until each thread is finished
delete threads[i];
threads[i] = NULL;
}
delete[]threads;
// Clean up list of processes hooked
for (unordered_map<DWORD, dump_process*>::iterator it = hooked_processes.begin(); it != hooked_processes.end(); ++it)
{
delete it->second; // cleans up the hook in the destructor
}
}
void close_watcher::_dump_process_worker_and_close()
{
// Dump this process
unordered_set<unsigned __int64> new_hashes;
while (!_monitor_request_stop || !_work_queue.empty())
{
// Process the hashes for this process
dump_process* entry;
if (_work_queue.pop(entry))
{
// Process this process
// Dump this process
entry->monitor_close_dump_and_resume();
// We're done with the process
delete entry;
}
Sleep(10);
}
}
close_watcher::~close_watcher()
{
stop_monitor();
}