Skip to content

Commit

Permalink
Major update to Process Dump v2. Changes:
Browse files Browse the repository at this point in the history
 - Added new flag '-closemon' which runs Process Dump in a monitoring
   mode. It will pause and dump any process just as it closes. This is designed
   to work well with malware analysis sandboxes, to be sure to dump
   malware from memory beofre the malicious process closes.
 - Upgraded Process Dump to be multi-threaded. Commands that dump or get
   hashes from multiple processes will run separate threads per operation.
   Default number of threads is 16, which speeds up the general Process
   Dump dumping processing significantly.
 - Upgraded Process Dump to dump unattached code chunks found in memory.
   These are identified as executable regions in memory which are not
   attached to a module and do not have a PE header. It also requires that
   the codechunk refer to at least 2 imports to be considered valid in
   order to reduce noise. When dumped, a PE header is recreated along with
   an import table. Code chunks are fully supported by the clean hash database.
 - Added flags to control the filepath to the clean hash database as well
   as the output folder for dumped files.
 - Fix to generating clean hash database from user path that was causing a
   crash.
 - Fix to the flag '-g' that forces generation of PE headers. Before even
   if this flag was set, system dumps (-system), would ignore this flag
   when dumping a process.
 - Various performance improvements.
  • Loading branch information
glmcdona committed Sep 19, 2016
1 parent 14fa4ab commit e8f7ba8
Show file tree
Hide file tree
Showing 27 changed files with 4,179 additions and 537 deletions.
8 changes: 5 additions & 3 deletions pd.sln
@@ -1,7 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pd", "pd\pd.vcproj", "{49B0E81A-D38E-426E-AB76-CC8463EC0003}"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pd", "pd\pd.vcxproj", "{49B0E81A-D38E-426E-AB76-CC8463EC0003}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
170 changes: 170 additions & 0 deletions pd/close_watcher.cpp
@@ -0,0 +1,170 @@
#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);

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 (hooked_pids.count(entry.th32ProcessID) == 0)
{
// 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();
}
27 changes: 27 additions & 0 deletions pd/close_watcher.h
@@ -0,0 +1,27 @@
#pragma once
#include "work_queue.h"
#include <thread>
#include "pe_hash_database.h"
#include "dump_process.h"
#include "windows.h"

class close_watcher
{
pe_hash_database* _clean_db;
PD_OPTIONS* _options;

Queue<dump_process*> _work_queue;

thread* _monitoring_thread;
bool _monitor_request_stop;

void _monitor_dump_on_close();
void _dump_process_worker_and_close();

public:
close_watcher(pe_hash_database* clean_db, PD_OPTIONS* options);
bool start_monitor();
bool stop_monitor();
~close_watcher();
};

0 comments on commit e8f7ba8

Please sign in to comment.