deleting temp files

This commit is contained in:
jakani24
2024-05-10 15:12:05 +02:00
parent 2ee71320ac
commit 2585b4646d
31 changed files with 0 additions and 7837 deletions

View File

@@ -1,373 +0,0 @@
#ifndef CHECK_DIR_CPP
#define CHECK_DIR_CPP
#include "check_dir.h"
#include "well_known.h"
#include "log.h"
#include "md5hash.h"
#include "scan.h"
#include "app_ctrl.h"
#include "virus_ctrl.h"
#include "scan.h"
#include "settings.h"
/* old implementation. used up a lot of resource and did not work properly.
void add_to_temp_db(const char*hash) {
//PERIODIC_FOLDER_SCAN_TEMP_DB
FILE*fp;
if (fopen_s(&fp, PERIODIC_FOLDER_SCAN_TEMP_DB, "a") != 0) {
log(LOGLEVEL::ERR, "[add_to_temp_db()]: Error opening temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
return;
}
else {
//log(LOGLEVEL::INFO, "[add_to_temp_db()]: Adding hash: ", hash, " to temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
fprintf_s(fp, "%s\n", hash);
fclose(fp);
}
}
void scan_folder_recursive(const std::string& directory, int thread_id,const std::string&db_file) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "Error opening directory: " << directory << std::endl;
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error opening directory: ", directory ," while scanning folder for new files");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder_recursive(full_path, thread_id,db_file);
}
else {
// If it's a file, check if it is in db, else scan it and add it to db
char*hash = new char[300];
md5_file(full_path.c_str(), hash);
//now find hash in db
if (scan_hash(db_file.c_str(), hash)==1) {
//file is allready in db, skipping
//in order to not keep hashes that are not present anymore in the db, we have to write this hash into a temp dir, which is at the end copied into the main db
add_to_temp_db(hash);
}
else {
//scan the file and add it to db
//scan for virus
switch (scan_hash(hash)) {
case 1:
//virus found
//log it
log(LOGLEVEL::VIRUS, "[scan_folder_recursive()]: Virus found in file: ", full_path, " while scanning ", directory, " for new files");
//virus_ctrl_store(full_path.c_str(), hash, "fs");
break;
case 2:
//error
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error while scanning file: ", full_path, " while scanning ", directory, " for new files");
break;
default:
//not a virus
add_to_temp_db(hash);
break;
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int check_scan_dir(char*dirpath,char*dirname) {
if (can_scan_folder()) {
scan_folder_init();
//FOLDER_DATABASE_DIR <= the folder where the database for folder checking is stored
//the database is stored in the following format:
/* a file per folder (and its subfolders)
in this db file the hashes of all the files in the folder (and its subfolders) are stored
If a file is detected, which hash is not known, it gets scanned and added to the db. if a hash is inside the db, which is not present in the folder, the hash is rempved from the db
*/
/*
FILE* fp;
char* path = new char[300];
path[0] = '\0';
//build up the path for the db file.
strcpy_s(path, 295, FOLDER_DATABASE_DIR);
strcat_s(path, 295, "\\");
strcat_s(path, 295, dirname);
strcat_s(path, 295, ".jdbf");
//check if the file exists. else we cannot scan the folder
if ((fopen_s(&fp, path, "r")) != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error opening database: ", path, " while scanning folder for new files; aborting");
//try to create the file
if (fopen_s(&fp, path, "w") != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error creating new database: ", path, " while scanning folder for new files; aborting");
}
else {
fprintf_s(fp, "%s\n", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");//write A 32 times A into the file. So the algorithm ha ssomething to map into memory. else it might throw an error
fclose(fp);
}
scan_folder_shutdown();
return 1;
}
else {
fclose(fp);
//process the files of the folder.
//first: calculate hash of file
//second: check if hash is in db
//if not, scan file and add it to db (only add it if it is not detected as a virus)
scan_folder_recursive(dirpath, 0,path);
//process the found viruses
virus_ctrl_process("fs");
}
delete[] path;
scan_folder_shutdown();
return 0;
}
else {
//there is already a folder scan happening
}
}
*/
bool is_directory(const std::string& path) {
DWORD attributes = GetFileAttributes(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) {
// Handle the error, e.g., by printing an error message
return false;
}
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) {
// Allocate a buffer for the file name and copy the content
std::wstring fileName(pInfo->FileName, pInfo->FileNameLength / sizeof(wchar_t));
//convert wstring to string
std::string filename_str(fileName.begin(), fileName.end());
filename_str = "c:\\" + filename_str;
//scan the file and send it to virus_ctrl if it is a virus and then process it
std::transform(filename_str.begin(), filename_str.end(), filename_str.begin(), ::tolower);
if (!is_folder_included(filename_str.c_str()) or is_directory(filename_str.c_str()) or is_folder_excluded(filename_str.c_str())) {
//dont scan excluded files or folders
return;
}
else {
std::thread scan_thread(scan_file_t, filename_str);
scan_thread.detach();
}
//log(LOGLEVEL::INFO, "[process_changes()]: File change: ", filename_str.c_str(), " while monitoring directory for changes");
}
/* this was the old algorithm. it was slower and used up more resources, because it used a database to track which files have been modified instead of using the windows internal functions
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
//print_exclusions();
// Wait for changes
while (true) {
DWORD bytesReturned;
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, TRUE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
DWORD error = GetLastError();
if (error != ERROR_IO_PENDING) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", error, " while monitoring directory for changes");
break;
}
}
// Wait for the event to be signaled (infinite timeout)
WaitForSingleObject(overlapped.hEvent, INFINITE);
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
*/
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
memset(buffer, 0, bufferSize);
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
// Wait for changes
while (!app_stop()) {
DWORD bytesReturned;
DWORD waitStatus = WaitForSingleObject(overlapped.hEvent, INFINITE);
if (waitStatus == WAIT_OBJECT_0) {
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
memset(buffer, 0, bufferSize);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: GetOverlappedResult failed: ", GetLastError());
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: WaitForSingleObject failed: ", GetLastError());
break;
}
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
void folder_scanner() {
//we are in a completely seperate thread then the main thread; unlimited resources wuhuii
FILE*fp;
char* path = new char[300];
char* foldername = new char[300];
//start the watch dir function used to monitor the dir for new files
monitor_directory("C:\\");
delete[] path;
delete[] foldername;
}
#endif // !CHECK_DIR_CPP

View File

@@ -1,373 +0,0 @@
#ifndef CHECK_DIR_CPP
#define CHECK_DIR_CPP
#include "check_dir.h"
#include "well_known.h"
#include "log.h"
#include "md5hash.h"
#include "scan.h"
#include "app_ctrl.h"
#include "virus_ctrl.h"
#include "scan.h"
#include "settings.h"
/* old implementation. used up a lot of resource and did not work properly.
void add_to_temp_db(const char*hash) {
//PERIODIC_FOLDER_SCAN_TEMP_DB
FILE*fp;
if (fopen_s(&fp, PERIODIC_FOLDER_SCAN_TEMP_DB, "a") != 0) {
log(LOGLEVEL::ERR, "[add_to_temp_db()]: Error opening temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
return;
}
else {
//log(LOGLEVEL::INFO, "[add_to_temp_db()]: Adding hash: ", hash, " to temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
fprintf_s(fp, "%s\n", hash);
fclose(fp);
}
}
void scan_folder_recursive(const std::string& directory, int thread_id,const std::string&db_file) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "Error opening directory: " << directory << std::endl;
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error opening directory: ", directory ," while scanning folder for new files");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder_recursive(full_path, thread_id,db_file);
}
else {
// If it's a file, check if it is in db, else scan it and add it to db
char*hash = new char[300];
md5_file(full_path.c_str(), hash);
//now find hash in db
if (scan_hash(db_file.c_str(), hash)==1) {
//file is allready in db, skipping
//in order to not keep hashes that are not present anymore in the db, we have to write this hash into a temp dir, which is at the end copied into the main db
add_to_temp_db(hash);
}
else {
//scan the file and add it to db
//scan for virus
switch (scan_hash(hash)) {
case 1:
//virus found
//log it
log(LOGLEVEL::VIRUS, "[scan_folder_recursive()]: Virus found in file: ", full_path, " while scanning ", directory, " for new files");
//virus_ctrl_store(full_path.c_str(), hash, "fs");
break;
case 2:
//error
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error while scanning file: ", full_path, " while scanning ", directory, " for new files");
break;
default:
//not a virus
add_to_temp_db(hash);
break;
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int check_scan_dir(char*dirpath,char*dirname) {
if (can_scan_folder()) {
scan_folder_init();
//FOLDER_DATABASE_DIR <= the folder where the database for folder checking is stored
//the database is stored in the following format:
/* a file per folder (and its subfolders)
in this db file the hashes of all the files in the folder (and its subfolders) are stored
If a file is detected, which hash is not known, it gets scanned and added to the db. if a hash is inside the db, which is not present in the folder, the hash is rempved from the db
*/
/*
FILE* fp;
char* path = new char[300];
path[0] = '\0';
//build up the path for the db file.
strcpy_s(path, 295, FOLDER_DATABASE_DIR);
strcat_s(path, 295, "\\");
strcat_s(path, 295, dirname);
strcat_s(path, 295, ".jdbf");
//check if the file exists. else we cannot scan the folder
if ((fopen_s(&fp, path, "r")) != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error opening database: ", path, " while scanning folder for new files; aborting");
//try to create the file
if (fopen_s(&fp, path, "w") != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error creating new database: ", path, " while scanning folder for new files; aborting");
}
else {
fprintf_s(fp, "%s\n", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");//write A 32 times A into the file. So the algorithm ha ssomething to map into memory. else it might throw an error
fclose(fp);
}
scan_folder_shutdown();
return 1;
}
else {
fclose(fp);
//process the files of the folder.
//first: calculate hash of file
//second: check if hash is in db
//if not, scan file and add it to db (only add it if it is not detected as a virus)
scan_folder_recursive(dirpath, 0,path);
//process the found viruses
virus_ctrl_process("fs");
}
delete[] path;
scan_folder_shutdown();
return 0;
}
else {
//there is already a folder scan happening
}
}
*/
bool is_directory(const std::string& path) {
DWORD attributes = GetFileAttributes(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) {
// Handle the error, e.g., by printing an error message
return false;
}
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) {
// Allocate a buffer for the file name and copy the content
std::wstring fileName(pInfo->FileName, pInfo->FileNameLength / sizeof(wchar_t));
//convert wstring to string
std::string filename_str(fileName.begin(), fileName.end());
filename_str = "c:\\" + filename_str;
//scan the file and send it to virus_ctrl if it is a virus and then process it
std::transform(filename_str.begin(), filename_str.end(), filename_str.begin(), ::tolower);
if (!is_folder_included(filename_str.c_str()) or is_directory(filename_str.c_str()) or is_folder_excluded(filename_str.c_str())) {
//dont scan excluded files or folders
return;
}
else {
std::thread scan_thread(scan_file_t, filename_str);
scan_thread.detach();
}
//log(LOGLEVEL::INFO, "[process_changes()]: File change: ", filename_str.c_str(), " while monitoring directory for changes");
}
/* this was the old algorithm. it was slower and used up more resources, because it used a database to track which files have been modified instead of using the windows internal functions
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
//print_exclusions();
// Wait for changes
while (true) {
DWORD bytesReturned;
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, TRUE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
DWORD error = GetLastError();
if (error != ERROR_IO_PENDING) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", error, " while monitoring directory for changes");
break;
}
}
// Wait for the event to be signaled (infinite timeout)
WaitForSingleObject(overlapped.hEvent, INFINITE);
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
*/
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
memset(buffer, 0, bufferSize);
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
// Wait for changes
while (!app_stop()) {
DWORD bytesReturned;
DWORD waitStatus = WaitForSingleObject(overlapped.hEvent, INFINITE);
if (waitStatus == WAIT_OBJECT_0) {
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
memset(buffer, 0, bufferSize);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: GetOverlappedResult failed: ", GetLastError());
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: WaitForSingleObject failed: ", GetLastError());
break;
}
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
void folder_scanner() {
//we are in a completely seperate thread then the main thread; unlimited resources wuhuii
FILE*fp;
char* path = new char[300];
char* foldername = new char[300];
//start the watch dir function used to monitor the dir for new files
monitor_directory("C:\\");
delete[] path;
delete[] foldername;
}
#endif // !CHECK_DIR_CPP

View File

@@ -1,157 +0,0 @@
#ifndef CHECK_DIR_CPP
#define CHECK_DIR_CPP
#include "check_dir.h"
#include "well_known.h"
#include "log.h"
#include "md5hash.h"
#include "scan.h"
#include "app_ctrl.h"
#include "virus_ctrl.h"
#include "settings.h"
#include <mutex> // Include the mutex header
#include <algorithm> // Include the algorithm header
#include <string> // Include the string header
#include <iostream> // Include the iostream header
// Define a mutex for thread synchronization
std::mutex monitorMutex;
bool is_directory(const std::string& path) {
DWORD attributes = GetFileAttributes(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) {
// Handle the error, e.g., by printing an error message
return false;
}
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) {
// Allocate a buffer for the file name and copy the content
std::wstring fileName(pInfo->FileName, pInfo->FileNameLength / sizeof(wchar_t));
// Convert wstring to string
std::string filename_str(fileName.begin(), fileName.end());
filename_str = "c:\\" + filename_str;
// Scan the file and send it to virus_ctrl if it is a virus and then process it
if (is_valid_path(filename_str)) { //filter out invalid paths and paths with weird characters
std::transform(filename_str.begin(), filename_str.end(), filename_str.begin(), ::tolower);
if (!is_folder_included(filename_str.c_str()) || is_directory(filename_str) || is_folder_excluded(filename_str.c_str())) {
// Don't scan excluded files or folders
return;
}
else {
//log(LOGLEVEL::INFO_NOSEND, "[process_changes()]: File ", filename_str, " has been changed. Scanning it for viruses");
std::thread scan_thread(scan_file_t, filename_str);
scan_thread.detach();
}
}
}
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
memset(buffer, 0, bufferSize);
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
// Wait for changes
while (!app_stop()) {
DWORD bytesReturned;
DWORD waitStatus = WaitForSingleObject(overlapped.hEvent, INFINITE);
if (waitStatus == WAIT_OBJECT_0) {
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
memset(buffer, 0, bufferSize);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: GetOverlappedResult failed: ", GetLastError());
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: WaitForSingleObject failed: ", GetLastError());
break;
}
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
void folder_scanner() {
// Lock access to the monitor function
std::lock_guard<std::mutex> lock(monitorMutex);
// We are in a completely separate thread than the main thread; unlimited resources wuhuii
// Start the watch dir function used to monitor the dir for new files
monitor_directory("C:\\");
}
#endif // !CHECK_DIR_CPP

View File

@@ -1,370 +0,0 @@
#ifndef CHECK_DIR_CPP
#define CHECK_DIR_CPP
#include "check_dir.h"
#include "well_known.h"
#include "log.h"
#include "md5hash.h"
#include "scan.h"
#include "app_ctrl.h"
#include "virus_ctrl.h"
#include "scan.h"
#include "settings.h"
/* old implementation. used up a lot of resource and did not work properly.
void add_to_temp_db(const char*hash) {
//PERIODIC_FOLDER_SCAN_TEMP_DB
FILE*fp;
if (fopen_s(&fp, PERIODIC_FOLDER_SCAN_TEMP_DB, "a") != 0) {
log(LOGLEVEL::ERR, "[add_to_temp_db()]: Error opening temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
return;
}
else {
//log(LOGLEVEL::INFO, "[add_to_temp_db()]: Adding hash: ", hash, " to temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
fprintf_s(fp, "%s\n", hash);
fclose(fp);
}
}
void scan_folder_recursive(const std::string& directory, int thread_id,const std::string&db_file) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "Error opening directory: " << directory << std::endl;
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error opening directory: ", directory ," while scanning folder for new files");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder_recursive(full_path, thread_id,db_file);
}
else {
// If it's a file, check if it is in db, else scan it and add it to db
char*hash = new char[300];
md5_file(full_path.c_str(), hash);
//now find hash in db
if (scan_hash(db_file.c_str(), hash)==1) {
//file is allready in db, skipping
//in order to not keep hashes that are not present anymore in the db, we have to write this hash into a temp dir, which is at the end copied into the main db
add_to_temp_db(hash);
}
else {
//scan the file and add it to db
//scan for virus
switch (scan_hash(hash)) {
case 1:
//virus found
//log it
log(LOGLEVEL::VIRUS, "[scan_folder_recursive()]: Virus found in file: ", full_path, " while scanning ", directory, " for new files");
//virus_ctrl_store(full_path.c_str(), hash, "fs");
break;
case 2:
//error
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error while scanning file: ", full_path, " while scanning ", directory, " for new files");
break;
default:
//not a virus
add_to_temp_db(hash);
break;
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int check_scan_dir(char*dirpath,char*dirname) {
if (can_scan_folder()) {
scan_folder_init();
//FOLDER_DATABASE_DIR <= the folder where the database for folder checking is stored
//the database is stored in the following format:
/* a file per folder (and its subfolders)
in this db file the hashes of all the files in the folder (and its subfolders) are stored
If a file is detected, which hash is not known, it gets scanned and added to the db. if a hash is inside the db, which is not present in the folder, the hash is rempved from the db
*/
/*
FILE* fp;
char* path = new char[300];
path[0] = '\0';
//build up the path for the db file.
strcpy_s(path, 295, FOLDER_DATABASE_DIR);
strcat_s(path, 295, "\\");
strcat_s(path, 295, dirname);
strcat_s(path, 295, ".jdbf");
//check if the file exists. else we cannot scan the folder
if ((fopen_s(&fp, path, "r")) != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error opening database: ", path, " while scanning folder for new files; aborting");
//try to create the file
if (fopen_s(&fp, path, "w") != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error creating new database: ", path, " while scanning folder for new files; aborting");
}
else {
fprintf_s(fp, "%s\n", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");//write A 32 times A into the file. So the algorithm ha ssomething to map into memory. else it might throw an error
fclose(fp);
}
scan_folder_shutdown();
return 1;
}
else {
fclose(fp);
//process the files of the folder.
//first: calculate hash of file
//second: check if hash is in db
//if not, scan file and add it to db (only add it if it is not detected as a virus)
scan_folder_recursive(dirpath, 0,path);
//process the found viruses
virus_ctrl_process("fs");
}
delete[] path;
scan_folder_shutdown();
return 0;
}
else {
//there is already a folder scan happening
}
}
*/
bool is_directory(const std::string& path) {
DWORD attributes = GetFileAttributes(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) {
// Handle the error, e.g., by printing an error message
return false;
}
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) {
// Allocate a buffer for the file name and copy the content
std::wstring fileName(pInfo->FileName, pInfo->FileNameLength / sizeof(wchar_t));
//convert wstring to string
std::string filename_str(fileName.begin(), fileName.end());
filename_str = "c:\\" + filename_str;
//scan the file and send it to virus_ctrl if it is a virus and then process it
std::transform(filename_str.begin(), filename_str.end(), filename_str.begin(), ::tolower);
if (is_folder_excluded(filename_str.c_str()) or is_directory(filename_str.c_str())) {
//dont scan excluded files
return;
}else
action_scanfile(filename_str.c_str());
log(LOGLEVEL::INFO, "[process_changes()]: File change: ", filename_str.c_str(), " while monitoring directory for changes");
}
/*
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
//print_exclusions();
// Wait for changes
while (true) {
DWORD bytesReturned;
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, TRUE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
DWORD error = GetLastError();
if (error != ERROR_IO_PENDING) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", error, " while monitoring directory for changes");
break;
}
}
// Wait for the event to be signaled (infinite timeout)
WaitForSingleObject(overlapped.hEvent, INFINITE);
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
*/
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
memset(buffer, 0, bufferSize);
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
std::cout << "[monitor_directory()]: Monitoring directory: " << directory << " for changes" << std::endl;
// Wait for changes
while (!app_stop()) {
DWORD bytesReturned;
DWORD waitStatus = WaitForSingleObject(overlapped.hEvent, INFINITE);
if (waitStatus == WAIT_OBJECT_0) {
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
memset(buffer, 0, bufferSize);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: GetOverlappedResult failed: ", GetLastError());
break;
}
}
else {
log(LOGLEVEL::ERR, "[monitor_directory()]: WaitForSingleObject failed: ", GetLastError());
break;
}
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
void folder_scanner() {
//we are in a completely seperate thread then the main thread; unlimited resources wuhuii
FILE*fp;
char* path = new char[300];
char* foldername = new char[300];
//start the watch dir function used to monitor the dir for new files
monitor_directory("C:\\");
delete[] path;
delete[] foldername;
}
#endif // !CHECK_DIR_CPP

View File

@@ -1,360 +0,0 @@
#ifndef CHECK_DIR_CPP
#define CHECK_DIR_CPP
#include "check_dir.h"
#include "well_known.h"
#include "log.h"
#include "md5hash.h"
#include "scan.h"
#include "app_ctrl.h"
#include "virus_ctrl.h"
#include "scan.h"
#include "settings.h"
/* old implementation. used up a lot of resource and did not work properly.
void add_to_temp_db(const char*hash) {
//PERIODIC_FOLDER_SCAN_TEMP_DB
FILE*fp;
if (fopen_s(&fp, PERIODIC_FOLDER_SCAN_TEMP_DB, "a") != 0) {
log(LOGLEVEL::ERR, "[add_to_temp_db()]: Error opening temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
return;
}
else {
//log(LOGLEVEL::INFO, "[add_to_temp_db()]: Adding hash: ", hash, " to temp db: ", PERIODIC_FOLDER_SCAN_TEMP_DB);
fprintf_s(fp, "%s\n", hash);
fclose(fp);
}
}
void scan_folder_recursive(const std::string& directory, int thread_id,const std::string&db_file) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "Error opening directory: " << directory << std::endl;
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error opening directory: ", directory ," while scanning folder for new files");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder_recursive(full_path, thread_id,db_file);
}
else {
// If it's a file, check if it is in db, else scan it and add it to db
char*hash = new char[300];
md5_file(full_path.c_str(), hash);
//now find hash in db
if (scan_hash(db_file.c_str(), hash)==1) {
//file is allready in db, skipping
//in order to not keep hashes that are not present anymore in the db, we have to write this hash into a temp dir, which is at the end copied into the main db
add_to_temp_db(hash);
}
else {
//scan the file and add it to db
//scan for virus
switch (scan_hash(hash)) {
case 1:
//virus found
//log it
log(LOGLEVEL::VIRUS, "[scan_folder_recursive()]: Virus found in file: ", full_path, " while scanning ", directory, " for new files");
//virus_ctrl_store(full_path.c_str(), hash, "fs");
break;
case 2:
//error
log(LOGLEVEL::ERR, "[scan_folder_recursive()]: Error while scanning file: ", full_path, " while scanning ", directory, " for new files");
break;
default:
//not a virus
add_to_temp_db(hash);
break;
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int check_scan_dir(char*dirpath,char*dirname) {
if (can_scan_folder()) {
scan_folder_init();
//FOLDER_DATABASE_DIR <= the folder where the database for folder checking is stored
//the database is stored in the following format:
/* a file per folder (and its subfolders)
in this db file the hashes of all the files in the folder (and its subfolders) are stored
If a file is detected, which hash is not known, it gets scanned and added to the db. if a hash is inside the db, which is not present in the folder, the hash is rempved from the db
*/
/*
FILE* fp;
char* path = new char[300];
path[0] = '\0';
//build up the path for the db file.
strcpy_s(path, 295, FOLDER_DATABASE_DIR);
strcat_s(path, 295, "\\");
strcat_s(path, 295, dirname);
strcat_s(path, 295, ".jdbf");
//check if the file exists. else we cannot scan the folder
if ((fopen_s(&fp, path, "r")) != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error opening database: ", path, " while scanning folder for new files; aborting");
//try to create the file
if (fopen_s(&fp, path, "w") != 0) {
log(LOGLEVEL::ERR, "[check_scan_dir()]: Error creating new database: ", path, " while scanning folder for new files; aborting");
}
else {
fprintf_s(fp, "%s\n", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");//write A 32 times A into the file. So the algorithm ha ssomething to map into memory. else it might throw an error
fclose(fp);
}
scan_folder_shutdown();
return 1;
}
else {
fclose(fp);
//process the files of the folder.
//first: calculate hash of file
//second: check if hash is in db
//if not, scan file and add it to db (only add it if it is not detected as a virus)
scan_folder_recursive(dirpath, 0,path);
//process the found viruses
virus_ctrl_process("fs");
}
delete[] path;
scan_folder_shutdown();
return 0;
}
else {
//there is already a folder scan happening
}
}
*/
void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) {
// Allocate a buffer for the file name and copy the content
std::wstring fileName(pInfo->FileName, pInfo->FileNameLength / sizeof(wchar_t));
// Print information about the changed file or directory
//convert wstring to string
std::string filename_str(fileName.begin(), fileName.end());
filename_str = "c:\\" + filename_str;
//scan the file and send it to virus_ctrl if it is a virus and then process it
std::transform(filename_str.begin(), filename_str.end(), filename_str.begin(), ::tolower);
if (is_folder_excluded(filename_str.c_str())) {
//dont scan excluded files
return;
}else
action_scanfile(filename_str.c_str());
log(LOGLEVEL::INFO, "[process_changes()]: File change: ", filename_str.c_str(), " while monitoring directory for changes");
}
/*
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error opening directory: ", directory, " while monitoring directory for changes");
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
CloseHandle(hDir);
return;
}
log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes");
//print_exclusions();
// Wait for changes
while (true) {
DWORD bytesReturned;
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, TRUE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", GetLastError(), " while monitoring directory for changes");
break;
}
}
else {
DWORD error = GetLastError();
if (error != ERROR_IO_PENDING) {
log(LOGLEVEL::ERR, "[monitor_directory()]: Error reading directory changes: ", error, " while monitoring directory for changes");
break;
}
}
// Wait for the event to be signaled (infinite timeout)
WaitForSingleObject(overlapped.hEvent, INFINITE);
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
*/
void monitor_directory(LPCSTR directory) {
// Open the directory for monitoring
HANDLE hDir = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
if (hDir == INVALID_HANDLE_VALUE) {
std::cerr << "[monitor_directory()]: Error opening directory: " << directory << " while monitoring directory for changes" << std::endl;
return;
}
// Create a buffer for file change notifications
constexpr DWORD bufferSize = 4096;
BYTE buffer[bufferSize];
// Monitor the directory for changes
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
NULL,
&overlapped,
NULL) == 0) {
std::cerr << "[monitor_directory()]: Error reading directory changes: " << GetLastError() << " while monitoring directory for changes" << std::endl;
CloseHandle(hDir);
return;
}
std::cout << "[monitor_directory()]: Monitoring directory: " << directory << " for changes" << std::endl;
// Wait for changes
while (!app_stop()) {
DWORD bytesReturned;
DWORD waitStatus = WaitForSingleObject(overlapped.hEvent, INFINITE);
if (waitStatus == WAIT_OBJECT_0) {
if (GetOverlappedResult(hDir, &overlapped, &bytesReturned, FALSE)) {
// Process the changes in the buffer
FILE_NOTIFY_INFORMATION* pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
do {
process_changes(pInfo);
pInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(
reinterpret_cast<BYTE*>(pInfo) + pInfo->NextEntryOffset);
} while (pInfo->NextEntryOffset != 0);
// Reset the event for the next wait
ResetEvent(overlapped.hEvent);
// Continue monitoring
if (ReadDirectoryChangesW(
hDir,
buffer,
bufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL) == 0) {
std::cerr << "[monitor_directory()]: Error reading directory changes: " << GetLastError() << " while monitoring directory for changes" << std::endl;
break;
}
}
else {
std::cerr << "[monitor_directory()]: Error reading directory changes: " << GetLastError() << " while monitoring directory for changes" << std::endl;
break;
}
}
else {
std::cerr << "[monitor_directory()]: WaitForSingleObject failed: " << GetLastError() << std::endl;
break;
}
}
// Cleanup
CloseHandle(overlapped.hEvent);
CloseHandle(hDir);
}
void folder_scanner() {
//we are in a completely seperate thread then the main thread; unlimited resources wuhuii
FILE*fp;
char* path = new char[300];
char* foldername = new char[300];
//start the watch dir function used to monitor the dir for new files
monitor_directory("C:\\");
delete[] path;
delete[] foldername;
}
#endif // !CHECK_DIR_CPP

View File

@@ -1,76 +0,0 @@
#include "check_process.h"
#include "log.h"
#include "well_known.h"
#include "scan.h"
#include "app_ctrl.h"
#include "settings.h"
#include "scan.h"
void monitor_processes() {
static DWORD previousProcessIds[1024] = { 0 }; // Previous snapshot of process IDs
DWORD processIds[1024];
DWORD bytesReturned;
// Get the list of process IDs
if (EnumProcesses(processIds, sizeof(processIds), &bytesReturned)) {
// Calculate how many process IDs were returned
DWORD numProcesses = bytesReturned / sizeof(DWORD);
// Check for new processes
log(LOGLEVEL::INFO_NOSEND, "[monitor_processes()]: Checking for new processes; having ",numProcesses, " currently running");
for (DWORD i = 0; i < numProcesses; ++i) {
DWORD processId = processIds[i];
BOOL isNewProcess = TRUE;
// Check if the process is new
for (DWORD j = 0; j < 1024; ++j) {
if (processId == previousProcessIds[j]) {
isNewProcess = FALSE;
break;
}
}
// If the process is new, get its executable path and print it
if (isNewProcess) {
// Open the process
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (hProcess != NULL) {
// Get the full path of the executable
TCHAR exePath[MAX_PATH];
char path[MAX_PATH+1];
if (GetModuleFileNameEx(hProcess, NULL, exePath, MAX_PATH) > 0) {
// Print the full path of the executable
strcpy_s(path, MAX_PATH, exePath);
//convert to lower case
for(int z=0;z<strlen(path);z++)
path[z] = tolower(path[z]);
//scan the file
if (!is_folder_included(path) or is_folder_excluded(path)) {
//dont scan excluded files or folders
}
else {
//log(LOGLEVEL::INFO, "[monitor_processes()]: New Process to scan: ", path, " while monitoring processes");
std::thread scan_thread(scan_process_t, path);
scan_thread.detach();
}
}
// Close the process handle
CloseHandle(hProcess);
}
}
}
// Update the previous snapshot of process IDs
memcpy(previousProcessIds, processIds, sizeof(DWORD) * 1024);
}
else {
log(LOGLEVEL::ERR, "[monitor_processes()]: Error enumerating processes");
}
}
void process_scanner() {
//we are in a thread so we can do this, unlimited resources wuhuiii
while (!app_stop()) {
monitor_processes();
Sleep(1000); // Sleep for 1 second
}
}

View File

@@ -1,106 +0,0 @@
#pragma warning(disable:4996)
#include <iostream>
#include <thread>
#include <curl/curl.h>
#include <openssl/md5.h>
//#include <yara.h>
#include "app_ctrl.h"
#include "md5hash.h"
#include "connect.h"
#include "scan.h"
#include "queue_ctrl.h"
#include "well_known.h"
#include "local_com.h"
#include "local_schedule.h"
#include "log.h"
#include "thread_ctrl.h"
#include "settings.h"
#include "check_dir.h"
#include "virus_ctrl.h"
int main() {
log(LOGLEVEL::INFO, "[main()]:Starting main thread.");
printf("welcome to the jakach security tool main thread\n");
load_settings();
initialize(DB_DIR);
//start a second thread which will scan for new files
if (get_setting("rtp:status") == 1) {
log(LOGLEVEL::INFO, "[main()]:Starting real time protection.");
std::thread folder_scannner_thread(folder_scanner);
folder_scannner_thread.detach();
}
//main thread:
/* watches for notifications on bus
* start threads (scans etc); only one at a time may run
* updates settings etc
* start scheduled tasks
*/
while (!app_stop()) {
//run all the tasks described above
//check for tasks in com
//check for scheduled tasks
//execute tasks
//call_srv("8.8.8.8","","");
auto start = std::chrono::high_resolution_clock::now();
// printf("check_from_com:%d\n",check_for_com_tasks(MAIN_COM, MAIN_COM_PATH));
check_for_com_tasks(MAIN_COM, MAIN_COM_PATH);
check_for_sched_tasks(SCHED, SCHED_PATH);
// printf("check_from_task:%d\n", check_for_sched_tasks(SCHED,SCHED_PATH));
//unlock_task("tsk1"); else it will only be executed once. but this function has to be called at the end of the task. else it will nvr be executed again. this would be bad :(
//start a thread that executes check_scan_dir to scan folders for new files. this thread then should start a ock so only one scanfolder thread runs at a time
//Sleep(1000);
if (can_run_thread()) {
int queue_size = get_queue_size();
for (int i = 0; i < queue_size; i++) {
char* queue_entry = new char[300 * 2 + 5];
queue_entry[0] = '\0';
queue_pop(queue_entry);
//execute the function which starts the threads
// printf("%s\n", queue_entry);
start_thread(queue_entry);
delete[] queue_entry;
}
}
//to ensure that the loop takes at least 1 second else it will run too fast nd destroy you CPU :)
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
if (duration.count() < 1000)
Sleep(1000 - duration.count());
// printf("\n\n\n");
}
//ListFilesRecursive("C:\\", 0);
/*char md5Hash[2 * MD5_DIGEST_LENGTH + 1]; // +1 for null-terminator
printf("Hash of the executable: ");
md5_file("C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\x64\\Debug\\client_backend.exe", md5Hash);
printf("%s", md5Hash);
char a_[2000];
printf("\nerror:%d\n",connect_to_srv("https://self-signed.badssl.com/", a_, 2000,1)); //error 60: self signed => option f<>r self-signed ignorieren aktivieren (bool ignore_invalid=true)
printf("%s", a_); //error 6: not reachable
download_file_from_srv("https://jakach.duckdns.org/php/login/v3/login.php", "c:\\programdata\\jakach\\out12.txt");
/*
const int numThreads = 12;
std::thread threads[numThreads];
for (int i = 0; i < numThreads; ++i) {
threads[i] = std::thread(ListFilesRecursive, "C:\\Users\\janis\\Documents\\ma_av_tests",i);
}
// Join threads to wait for them to finish
for (int i = 0; i < numThreads; ++i) {
threads[i].join();
}
std::cout << "All threads have finished." << std::endl;
*/
//printf("code:%d",scan_hash("C:\\Users\\janis\\Documents\\ma_av_tests\\OutputFile.txt", "1fddc13c02a79442c911a44b02ee0f58"));
return 0;
}

View File

@@ -1,101 +0,0 @@
#pragma warning(disable:4996)
#include <iostream>
#include <thread>
#include <curl/curl.h>
#include <openssl/md5.h>
//#include <yara.h>
#include "app_ctrl.h"
#include "md5hash.h"
#include "connect.h"
#include "scan.h"
#include "queue_ctrl.h"
#include "well_known.h"
#include "local_com.h"
#include "local_schedule.h"
#include "log.h"
#include "thread_ctrl.h"
#include "settings.h"
#include "check_dir.h"
int main() {
printf("welcome to the jakach security tool main thread\n");
load_settings();
//start a second thread which will scan for new files
std::thread folder_scannner_thread(folder_scanner);
//
//
//main thread:
/* watches for notifications on bus
* start threads (scans etc); only one at a time may run
* updates settings etc
* start scheduled tasks
*/
while (!app_stop()) {
//run all the tasks described above
//check for tasks in com
//check for scheduled tasks
//execute tasks
//call_srv("8.8.8.8","","");
auto start = std::chrono::high_resolution_clock::now();
// printf("check_from_com:%d\n",check_for_com_tasks(MAIN_COM, MAIN_COM_PATH));
// printf("check_from_task:%d\n", check_for_sched_tasks(SCHED,SCHED_PATH));
//unlock_task("tsk1"); else it will only be executed once. but this function has to be called at the end of the task. else it will nvr be executed again. this would be bad :(
//start a thread that executes check_scan_dir to scan folders for new files. this thread then should start a ock so only one scanfolder thread runs at a time
//Sleep(1000);
if (can_run_thread()) {
int queue_size = get_queue_size();
for (int i = 0; i < queue_size; i++) {
char* queue_entry = new char[300 * 2 + 5];
queue_entry[0] = '\0';
queue_pop(queue_entry);
//execute the function which starts the threads
// printf("%s\n", queue_entry);
start_thread(queue_entry);
delete[] queue_entry;
}
}
//to ensure that the loop takes at least 1 second else it will run too fast nd destroy you CPU :)
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
if (duration.count() < 1000)
Sleep(1000 - duration.count());
// printf("\n\n\n");
}
//ListFilesRecursive("C:\\", 0);
/*char md5Hash[2 * MD5_DIGEST_LENGTH + 1]; // +1 for null-terminator
printf("Hash of the executable: ");
md5_file("C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\x64\\Debug\\client_backend.exe", md5Hash);
printf("%s", md5Hash);
char a_[2000];
printf("\nerror:%d\n",connect_to_srv("https://self-signed.badssl.com/", a_, 2000,1)); //error 60: self signed => option f<>r self-signed ignorieren aktivieren (bool ignore_invalid=true)
printf("%s", a_); //error 6: not reachable
download_file_from_srv("https://jakach.duckdns.org/php/login/v3/login.php", "c:\\programdata\\jakach\\out12.txt");
/*
const int numThreads = 12;
std::thread threads[numThreads];
for (int i = 0; i < numThreads; ++i) {
threads[i] = std::thread(ListFilesRecursive, "C:\\Users\\janis\\Documents\\ma_av_tests",i);
}
// Join threads to wait for them to finish
for (int i = 0; i < numThreads; ++i) {
threads[i].join();
}
std::cout << "All threads have finished." << std::endl;
*/
//printf("code:%d",scan_hash("C:\\Users\\janis\\Documents\\ma_av_tests\\OutputFile.txt", "1fddc13c02a79442c911a44b02ee0f58"));
return 0;
}

View File

@@ -1,116 +0,0 @@
#pragma warning(disable:4996)
#include <iostream>
#include <thread>
#include <curl/curl.h>
#include <openssl/md5.h>
//#include <yara.h>
#include "app_ctrl.h"
#include "md5hash.h"
#include "connect.h"
#include "scan.h"
#include "queue_ctrl.h"
#include "well_known.h"
#include "local_com.h"
#include "local_schedule.h"
#include "log.h"
#include "thread_ctrl.h"
#include "settings.h"
#include "check_dir.h"
#include "virus_ctrl.h"
#include "update.h"
#include "check_process.h"
int main() {
//log(LOGLEVEL::INFO, "[main()]:Starting main thread.");
//return 0;
log(LOGLEVEL::INFO_NOSEND, "[main()]:Starting main thread.");
int err = 0;
printf("welcome to the jakach security tool main thread\n");
if (load_settings() == 0) {//load the settings from the settings file
if (update_settings("settings")!=0) { //update the settings from the server
log(LOGLEVEL::ERR_NOSEND, "[main()]:Could not update settings (settings) from server.");
}
if (update_settings("rtp_included")!=0) { //update the settings from the server
log(LOGLEVEL::ERR_NOSEND, "[main()]:Could not update settings (rtp_included) from server.");
}
if (update_settings("rtp_excluded")!=0) { //update the settings from the server
log(LOGLEVEL::ERR_NOSEND, "[main()]:Could not update settings (rtp_excluded) from server.");
}
if (update_settings("sched")!=0) { //update the settings from the server
log(LOGLEVEL::ERR_NOSEND, "[main()]:Could not update settings (scheduled_tasks) from server.");
}
load_settings(); //load the updated settings from the settings file
}
else {
log(LOGLEVEL::ERR_NOSEND, "[main()]:Could not load settings from file.");
log(LOGLEVEL::PANIC_NOSEND, "[main()]:Panic, no settings file loaded, terminating process!");
exit(1);
}
// Initialize hash databases
err = initialize(DB_DIR);
if (err != 0) {
switch (err) {
case 1:
log(LOGLEVEL::ERR, "[main()]:Error opening database file in: ", DB_DIR);
break;
case 2:
log(LOGLEVEL::ERR, "[main()]:Error creating database file mapping in: ", DB_DIR);
break;
case 3:
log(LOGLEVEL::ERR, "[main()]:Error mapping database file in: ", DB_DIR);
break;
default:
log(LOGLEVEL::ERR, "[main()]:Unknown error while loading database file in: ", DB_DIR);
break;
}
}
// Start a second thread for real-time protection
if (get_setting("rtp_folder_scan:status") == 1) {
log(LOGLEVEL::INFO, "[main()]:Starting real time file protection.");
std::thread folder_scanner_thread(folder_scanner);
folder_scanner_thread.detach();
}
if (get_setting("rtp_process_scan:status") == 1) {
log(LOGLEVEL::INFO, "[main()]:Starting real time process protection.");
std::thread process_scanner_thread(process_scanner);
process_scanner_thread.detach();
}
// Main thread loop
while (!app_stop()) {
auto start = std::chrono::high_resolution_clock::now();
// Check for tasks from user interface
if (check_for_com_tasks(MAIN_COM, MAIN_COM_PATH) != 0) {
// Log message commented out as this error is expected when the file doesn't exist
// log(LOGLEVEL::ERR, "[main()]:Error opening communication file in: ", MAIN_COM_PATH);
}
// Check for scheduled tasks
if (check_for_sched_tasks(SCHED, SCHED_PATH) != 0) {
log(LOGLEVEL::ERR, "[main()]:Error opening schedule file in: ", SCHED_PATH);
}
// Execute tasks from the queue
if (can_run_thread()) {
int queue_size = get_queue_size();
for (int i = 0; i < queue_size; i++) {
char* queue_entry = new char[300 * 2 + 5];
queue_entry[0] = '\0';
queue_pop(queue_entry);
start_thread(queue_entry);
delete[] queue_entry;
}
}
// Sleep to ensure loop takes at least 1 second
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
if (duration.count() < 1000)
Sleep(1000 - duration.count());
}
return 0;
}

View File

@@ -1,242 +0,0 @@
#pragma warning(disable:4996)
#ifndef CONNECT_CPP
#define CONNECT_CPP
#include "connect.h"
#include "well_known.h"
#include "security.h"
#include <curl/curl.h>
#include <string>
#include <mutex>
std::mutex connect_mutex;
//this function is thread safe
int fast_send(const std::string& url, bool ignore_insecure) {
std::lock_guard<std::mutex> lock(connect_mutex);
thread_local const std::string url_ = url;
thread_local const bool ignore_insecure_ = ignore_insecure;
thread_local CURL* curl;
thread_local CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url_.c_str());
if (ignore_insecure_)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res == CURLE_OK) {
return 0;
}
else {
return res;
}
}
return 1;
}
static size_t write_callback_connect(void* contents, size_t size, size_t nmemb, void* userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
//make this multi thread safe
int connect_to_srv(const std::string& url, char* out, int max_len, bool ignore_insecure) {
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_connect);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
if (ignore_insecure)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (max_len > (int)readBuffer.length()) {
strcpy(out, readBuffer.c_str());
return 0;
}
else
return 1;
}
return 2;
}
size_t write_callback_download(void* contents, size_t size, size_t nmemb, void* userp) {
size_t totalSize = size * nmemb;
FILE* file = (FILE*)userp;
if (file) {
fwrite(contents, 1, totalSize, file);
}
return totalSize;
}
int download_file_from_srv(const std::string& url, const std::string& output_file_path, bool ignore_insecure, bool do_not_check_cyberhex_cert) {
char* temp_path = new char[output_file_path.size() + 6];
strcpy(temp_path, output_file_path.c_str());
strcat(temp_path, ".temp");
CURL* curl;
CURLcode res;
FILE* output_file;
curl = curl_easy_init();
if (!curl) {
delete[] temp_path;
return 1;
}
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
output_file = fopen(temp_path, "wb");
if (!output_file) {
curl_easy_cleanup(curl);
delete[] temp_path;
return 2;
}
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_download);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, output_file);
if (ignore_insecure)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fclose(output_file);
delete[] temp_path;
return 3;
}
curl_easy_cleanup(curl);
fclose(output_file);
if ((output_file = fopen(temp_path, "r")) == 0) {
delete[] temp_path;
return 4;
}
else {
char buf[501];
fscanf(output_file, "%500s", buf);
if (strcmp(buf, "no_auth") == 0) {
fclose(output_file);
delete[] temp_path;
return 5;
}
else if (check_cert(buf, SECRETS) == 0 or do_not_check_cyberhex_cert==true) {
remove(output_file_path.c_str());
fclose(output_file);
if (rename(temp_path, output_file_path.c_str()) != 0) {
delete[] temp_path;
return 6;
}
}
else {
fclose(output_file);
delete[] temp_path;
return 7;
}
}
delete[] temp_path;
return 0;
}
std::string url_encode(const std::string& input) {
static const char* const safe_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
std::string encoded;
for (char c : input) {
if (std::strchr(safe_chars, c) != nullptr) {
encoded += c;
}
else {
char temp[4];
sprintf(temp, "%%%02X", (unsigned char)c);
encoded += temp;
}
}
return encoded;
}
int upload_to_srv(const std::string& url, const std::string& filepath, bool ignore_insecure) {
CURL* curl;
CURLcode res;
struct curl_httppost* formpost = nullptr;
struct curl_httppost* lastptr = nullptr;
struct curl_slist* headerlist = nullptr;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filepath.c_str(), CURLFORM_END);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (ignore_insecure)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
headerlist = curl_slist_append(headerlist, buf);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (res == CURLE_OK) {
return 0;
}
else {
return 1;
}
}
return 2;
}
int send_to_pipe(const std::string& message) {
HANDLE hPipe;
DWORD dwRead;
DWORD dwWritten;
hPipe = CreateFile(TEXT("\\\\.\\pipe\\cyberhex_pipe"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
WriteFile(hPipe,
message.c_str(),
strlen(message.c_str()) + 1, // = length of string + terminating '\0' !!!
&dwWritten,
NULL);
CloseHandle(hPipe);
return 0;
}
else {
return 1;
}
}
std::string read_from_pipe() {
HANDLE hPipe;
DWORD dwRead;
DWORD dwWritten;
char buffer[1000];
hPipe = CreateFile(TEXT("\\\\.\\pipe\\cyberhex_pipe"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
ReadFile(hPipe, buffer, sizeof(buffer), &dwRead, NULL);
CloseHandle(hPipe);
buffer[strlen(buffer)+1]= '\0';
return std::string(buffer);
}
else {
return "Error";
}
}
#endif

View File

@@ -1,36 +0,0 @@
#pragma warning(disable:4996)
#include "md5hash.h"
#include "log.h"
int md5_file(const char*path,char*md5Hash) {
std::ifstream file(path, std::ios::binary);
if (!file) {
log(LOGLEVEL::ERR, "[md5_file()]: Could not open file for scanning ",path);
return 1;
}
// Initialize OpenSSL's MD5 context
MD5_CTX md5Context;
MD5_Init(&md5Context);
// Read and update the context with the file's content
char buffer[1024];
while (file.good()) {
file.read(buffer, sizeof(buffer));
MD5_Update(&md5Context, buffer, file.gcount());
}
// Finalize the MD5 hash and store it in result
unsigned char result[MD5_DIGEST_LENGTH];
MD5_Final(result, &md5Context);
// Close the file
file.close();
// Store the MD5 hash in a char array
//char md5Hash[2 * MD5_DIGEST_LENGTH + 1]; // +1 for null-terminator
for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
snprintf(&md5Hash[i * 2], 3, "%02x", result[i]);
}
}

View File

@@ -1,209 +0,0 @@
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#ifndef SCAN_CPP
#define SCAN_CPP
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads=0;
//load all the db files into memory
void initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath +"\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
continue; // Move on to the next file if there's an error
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
continue; // Move on to the next file if there's an error
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
continue; // Move on to the next file if there's an error
}
// Store the handles in the global maps
fileHandles[filename] = hFile;
mappingHandles[filename] = hMapping;
fileData[filename] = fileDataPtr;
}
}
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
fileHandles.clear();
mappingHandles.clear();
fileData.clear();
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
thread_local std::string dbname (dbname_);
thread_local std::string hash (hash_);
thread_local std::string filepath (filepath_);
thread_local auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() or dbname_.find("c:.jdbf") != std::string::npos) {
log(LOGLEVEL::ERR, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
// Use fileData for subsequent searches
thread_local DWORD fileSize = GetFileSize(fileHandles[dbname], NULL);
thread_local std::string fileContent(fileData[dbname], fileSize);
// Search for the specific string in the file content
thread_local size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_folder(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[scan_folder()]: Error opening directory: ", search_path.c_str() , " while scanning files inside folder.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder(full_path);
}
else {
//action scanfile_t will start the trheads for scanning the hashes
//action_scanfile_t(full_path.c_str());
//do multithreading here
while (num_threads >= std::thread::hardware_concurrency()) {
Sleep(10);
}
num_threads++;
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
//for singlethreaded scans
void action_scanfile(const char*filepath) {
thread_init();
char* db_path = new char[300];
//log(LOGLEVEL::INFO, "[action_scanfile_t()]: Scanning file: ", filepath);
if (strlen(filepath) == 0 or strcmp("", filepath) == 0 or file_exists(filepath) == false) {
thread_shutdown();
return; //no filepath given or file not accessible
}
else {
char* hash = new char[300];
hash[0] = '\0';
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
delete[] hash;
}
delete[] db_path;
thread_shutdown();
}
void action_scanfolder(const char*folderpath) {
thread_init();
cnt = 0;
thread_local std::string folderpath_ (folderpath);
scan_folder(folderpath_);
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
thread_local const std::string filepath (filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash,295 ,md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
num_threads--;
}
#endif

View File

@@ -1,312 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_folder(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::WARN, "[scan_folder()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder(full_path);
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path, "threads: ", num_threads);
//action scanfile_t will start the trheads for scanning the hashes
//action_scanfile_t(full_path.c_str());
//do multithreading here
int thread_timeout = 0;
while (num_threads >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {//if there is for more than 30 seconds no thread available, chances are high, that the threads did not temrinate correctly but aren t running anymore. so set the counter to 0 because else it might just stop the scan.
num_threads = 0;
printf("Number of threads_max: %d\n", num_threads);
}
}
//log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path, "threads: ",num_threads);
if (is_valid_path(full_path)==0) {
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) {//4gb
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
//Sleep(1);
}
}else
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if(num_threads<0)
printf("Number of threads_min: %d\n", num_threads);
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH,std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
cnt = 0;
thread_local std::string folderpath_(folderpath);
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
num_threads--;
}
void scan_process_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
num_threads--;
}
#endif

View File

@@ -1,311 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_folder(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::WARN, "[scan_folder()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder(full_path);
}
else {
//action scanfile_t will start the trheads for scanning the hashes
//action_scanfile_t(full_path.c_str());
//do multithreading here
int thread_timeout = 0;
while (num_threads >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {//if there is for more than 30 seconds no thread available, chances are high, that the threads did not temrinate correctly but aren t running anymore. so set the counter to 0 because else it might just stop the scan.
num_threads = 0;
printf("Number of threads_max: %d\n", num_threads);
}
}
if (is_valid_path(full_path)) { //filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) {//4gb
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
Sleep(10);
}
}else
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if(num_threads<0)
printf("Number of threads_min: %d\n", num_threads);
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH,std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
cnt = 0;
thread_local std::string folderpath_(folderpath);
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
num_threads--;
}
void scan_process_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
num_threads--;
}
#endif

View File

@@ -1,388 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
//log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path);
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
//printf("Thread timeout: %d\n", thread_timeout);
if (thread_timeout == 100 * 20) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
//log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path);
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if (cnt % 1000 == 0) {
int actual_threads = get_num_threads();
if(get_num_threads()>actual_threads)
set_num_threads(actual_threads);//correct value of threads minus the main and the rtp thread
printf("Number of threads: %d\n", get_num_threads());
//send progress to com file
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "progress " << (cnt * 100 / (all_files + 1)) << "\n";
answer_com.close();
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[scan_folder()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,366 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,367 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,368 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,369 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[scan_folder()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,382 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path);
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if (cnt % 1000 == 0) {
//send progress to com file
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "progress " << (cnt * 100 / (all_files + 1)) << "\n";
answer_com.close();
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[scan_folder()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,384 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <stack>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
int get_num_threads() {
std::lock_guard<std::mutex> lock(numThreadsMutex);
return num_threads;
}
int set_num_threads(int num) {
std::lock_guard<std::mutex> lock(numThreadsMutex);
num_threads = num;
return 0;
}
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc (iterative)
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
//std::cerr << "[get_num_files()]: Could not open directory: " << search_path << " while scanning files inside directory." << std::endl;
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path, " while scanning files inside directory.");
return 0;
}
// Stack to store directories to be traversed iteratively
std::stack<std::string> directories;
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
search_path = current_dir + "\\*.*";
hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[get_num_files()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
std::stack<std::string> directories; // Stack to store directories to be scanned
void scan_folder(const std::string& directory) {
directories.push(directory);
while (!directories.empty()) {
std::string current_dir = directories.top();
directories.pop();
std::string search_path = current_dir + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = current_dir + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, add it to the stack
directories.push(full_path);
}
else {
// Do multithreading here
int thread_timeout = 0;
while (get_num_threads() >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {
// If there is no available thread for more than 30 seconds, reset the thread counter
set_num_threads(0);
}
}
//log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path);
if (is_valid_path(full_path)) { // Filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) { // 4GB
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}
else {
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
}
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if (cnt % 1000 == 0) {
set_num_threads(get_num_running_threads()-1-1);//correct value of threads minus the main and the rtp thread
printf("Number of threads: %d\n", num_threads);
//send progress to com file
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "progress " << (cnt * 100 / (all_files + 1)) << "\n";
answer_com.close();
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
else {
log(LOGLEVEL::ERR_NOSEND, "[scan_folder()]: Could not open directory: ", current_dir, " while scanning files inside directory.");
//std::cerr << "[scan_folder()]: Could not open directory: " << current_dir << " while scanning files inside directory." << std::endl;
}
}
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
set_num_threads(get_num_threads() - 1);
}
void scan_process_t(const std::string& filepath_) {
set_num_threads(get_num_threads() + 1);
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
set_num_threads(get_num_threads() - 1);
}
#endif

View File

@@ -1,132 +0,0 @@
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#ifndef SCAN_CPP
#define SCAN_CPP
int cnt = 0;
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
void scan_files_recursive(const std::string& directory, int thread_id) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[ListFilesRecursive()]: Error opening directory: ", directory, " while scanning files inside folder.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_files_recursive(full_path,thread_id);
}
else {
// If it's a file, print its name
/*char md5Hash[2 * MD5_DIGEST_LENGTH + 1];
md5_file(full_path.c_str(), md5Hash);
printf("%s\n", md5Hash);
printf("%d\n", scan_hash("C:\\Users\\janis\\Documents\\ma_av_tests\\OutputFile.txt", "96be95b122c2b9b8bb5765c312ca4f73"));
if (scan_hash("C:\\Users\\janis\\Documents\\ma_av_tests\\OutputFile.txt", md5Hash) == 1) {
printf("virus found");
}*/
cnt++;
if (cnt % 1000 == 0) {
printf("Processed %d files; sent from thread %d\n", cnt,thread_id);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int scan_hash(const std::string& filename, const std::string& hash) {//!!!! does not work with e.g. utf-16 or something like that. either ascii or utf8!!
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error opening database file: ", filename, " while searching for hash.", hash);
return 2;
}
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error creating database file mapping: ", filename, " while searching for hash.");
CloseHandle(hFile);
return 2;
}
char* fileData = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileData == NULL) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error mapping database file: ", filename, " while searching for hash.");
CloseHandle(hMapping);
CloseHandle(hFile);
return 2;
}
DWORD fileSize = GetFileSize(hFile, NULL);
std::string fileContent(fileData, fileSize);
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
UnmapViewOfFile(fileData);
CloseHandle(hMapping);
CloseHandle(hFile);
return 1;//found
}
// Unmap the memory and close the handles
UnmapViewOfFile(fileData);
CloseHandle(hMapping);
CloseHandle(hFile);
return 0;
}
int scan_hash(const char* hash) {
char* path = new char[600];
path[0] = '\0';
sprintf_s(path, 595, "%s\\%c%c.jdbf", DB_DIR, hash[0],hash[1]);
return scan_hash(path,hash);
}
void action_scanfile(const char*filepath) {
if (strlen(filepath) == 0 or strcmp("", filepath) == 0 or file_exists(filepath) == false) {
//log(LOGLEVEL::ERR, "[action_scanfile()]: Error opening file: ", filepath, " while scanning file for viruses.");
return; //no filepath given or file not accessible
}
else {
char* hash = new char[300];
md5_file(filepath, hash);
if (scan_hash(hash) == 1) { //virus found
log(LOGLEVEL::VIRUS, "[action_scanfile()]: Virus found in file: ", filepath);
//add it to a database which stores filepaths of infected files
virus_ctrl_store(filepath, hash, "sf");
//afterwards do the processing with that file
virus_ctrl_process("sf");
}
delete[] hash;
}
}
#endif

View File

@@ -1,147 +0,0 @@
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#ifndef SCAN_CPP
#define SCAN_CPP
int cnt = 0;
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_files_recursive(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[ListFilesRecursive()]: Error opening directory: ", directory, " while scanning files inside folder.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_files_recursive(full_path);
}
else {
//we can use a modified version of action_scanfile for this
//action_scanfile_t(full_path.c_str());
cnt++;
if (cnt % 1000 == 0) {
printf("Processed %d files;\n", cnt);
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
int scan_hash(thread_local const std::string& filename, thread_local const std::string& hash) {//!!!! does not work with e.g. utf-16 or something like that. either ascii or utf8!!
thread_local HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error opening database file: ", filename, " while searching for hash.", hash);
return 2;
}
thread_local HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error creating database file mapping: ", filename, " while searching for hash.");
CloseHandle(hFile);
return 2;
}
char* fileData = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileData == NULL) {
log(LOGLEVEL::ERR, "[scan_hash()]: Error mapping database file: ", filename, " while searching for hash.");
CloseHandle(hMapping);
CloseHandle(hFile);
return 2;
}
DWORD fileSize = GetFileSize(hFile, NULL);
std::string fileContent(fileData, fileSize);
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
UnmapViewOfFile(fileData);
CloseHandle(hMapping);
CloseHandle(hFile);
return 1;//found
}
// Unmap the memory and close the handles
UnmapViewOfFile(fileData);
CloseHandle(hMapping);
CloseHandle(hFile);
return 0;
}
int scan_hash(thread_local const char* hash) {
thread_local char* path = new char[600];
path[0] = '\0';
sprintf_s(path, 595, "%s\\%c%c.jdbf", DB_DIR, hash[0],hash[1]);
return scan_hash(path,hash);
}
//for singlethreaded scans
void action_scanfile(const char*filepath) {
if (strlen(filepath) == 0 or strcmp("", filepath) == 0 or file_exists(filepath) == false) {
//log(LOGLEVEL::ERR, "[action_scanfile()]: Error opening file: ", filepath, " while scanning file for viruses.");
return; //no filepath given or file not accessible
}
else {
char* hash = new char[300];
md5_file(filepath, hash);
if (scan_hash(hash) == 1) { //virus found
log(LOGLEVEL::VIRUS, "[action_scanfile()]: Virus found in file: ", filepath);
//add it to a database which stores filepaths of infected files
virus_ctrl_store(filepath, hash, "sf");
//afterwards do the processing with that file
virus_ctrl_process("sf");
}
delete[] hash;
}
}
//for multithreaded scans
void action_scanfile_t(thread_local const char* filepath) {
if (strlen(filepath) == 0 or strcmp("", filepath) == 0 or file_exists(filepath) == false) {
return; //no filepath given or file not accessible
}
else {
thread_local char* hash = new char[300];
md5_file(filepath, hash);
if (scan_hash(hash) == 1) { //virus found
log(LOGLEVEL::VIRUS, "[action_scanfile()]: Virus found in file: ", filepath);
//add it to a database which stores filepaths of infected files
virus_ctrl_store(filepath, hash, "sft");
//we do the processing at the end of the scan in order to not slow down the scan !!i have to remember to do this!!
//virus_ctrl_process("sft");
}
delete[] hash;
}
}
#endif

View File

@@ -1,323 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
bool file_exists(const std::string& filePath) {
DWORD fileAttributes = GetFileAttributes(filePath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
// The file does not exist or there was an error
return false;
}
// Check if it's a regular file and not a directory
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_folder(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::WARN, "[scan_folder()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder(full_path);
}
else {
//action scanfile_t will start the trheads for scanning the hashes
//action_scanfile_t(full_path.c_str());
//do multithreading here
int thread_timeout = 0;
while (num_threads >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {//if there is for more than 30 seconds no thread available, chances are high, that the threads did not temrinate correctly but aren t running anymore. so set the counter to 0 because else it might just stop the scan.
num_threads = 0;
printf("Number of threads_max: %d\n", num_threads);
}
}
if (is_valid_path(full_path)) { //filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) {//4gb
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}else
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if (cnt % 1000 == 0) {
//send progress to com file
printf("Processed %d files; Sending to frontend\n", cnt);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "progress " << 50 << "\n";
answer_com.close();
}
}
if(num_threads<0)
printf("Number of threads_min: %d\n", num_threads);
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
cnt = 0;
thread_local std::string folderpath_(folderpath);
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
num_threads--;
}
void scan_process_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
num_threads--;
}
#endif

View File

@@ -1,344 +0,0 @@
#ifndef SCAN_CPP
#define SCAN_CPP
#include "scan.h"
#include <windows.h>
#include <iostream>
#include <openssl/md5.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
#include "md5hash.h"
#include <string>
#include "well_known.h"
#include "log.h"
#include "virus_ctrl.h"
#include "app_ctrl.h"
#include <mutex> // Include the mutex header
#include <filesystem>
#include "utils.h"
// Define mutexes for thread synchronization
std::mutex fileHandlesMutex;
std::mutex mappingHandlesMutex;
std::mutex fileDataMutex;
std::mutex cntMutex;
std::mutex numThreadsMutex;
std::unordered_map<std::string, HANDLE> fileHandles;
std::unordered_map<std::string, HANDLE> mappingHandles;
std::unordered_map<std::string, char*> fileData;
int cnt = 0;
int num_threads = 0;
int all_files = 0;
//load all the db files into memory
int initialize(const std::string& folderPath) {
for (char firstChar = '0'; firstChar <= 'f'; ++firstChar) {
for (char secondChar = '0'; secondChar <= 'f'; ++secondChar) {
// Ensure that the characters are valid hexadecimal digits
if (!std::isxdigit(firstChar) || !std::isxdigit(secondChar) or std::isupper(firstChar) or std::isupper(secondChar)) {
continue;
}
// Create the filename based on the naming convention
std::string filename = folderPath + "\\" + firstChar + secondChar + ".jdbf";
//printf("Loading %s\n", filename.c_str());
// Open the file
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
//log(LOGLEVEL::ERR, "[initialize()]: Error opening database file: ", filename);
return 1;
}
// Create the file mapping
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL) {
// log(LOGLEVEL::ERR, "[initialize()]: Error creating database file mapping: ", filename);
CloseHandle(hFile);
return 2;
}
// Map the file into memory
char* fileDataPtr = static_cast<char*>(MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
if (fileDataPtr == NULL) {
//log(LOGLEVEL::ERR, "[initialize()]: Error mapping database file: ", filename);
CloseHandle(hMapping);
CloseHandle(hFile);
return 3;
}
// Store the handles in the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles[filename] = hFile;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles[filename] = hMapping;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData[filename] = fileDataPtr;
}
}
}
return 0;
}
// Call this function when you are done using the file mappings
void cleanup() {
for (const auto& entry : fileHandles) {
UnmapViewOfFile(fileData[entry.first]);
CloseHandle(mappingHandles[entry.first]);
CloseHandle(entry.second);
}
// Clear the global maps
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
fileHandles.clear();
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
mappingHandles.clear();
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileData.clear();
}
}
//the latest and fastest version of searching a hash by now
int search_hash(const std::string& dbname_, const std::string& hash_, const std::string& filepath_) {
// Check if the file mapping is already open for the given filename
std::string dbname;
std::string hash;
std::string filepath;
{
std::lock_guard<std::mutex> lock(fileHandlesMutex);
dbname = dbname_;
}
{
std::lock_guard<std::mutex> lock(fileDataMutex);
hash = hash_;
}
{
std::lock_guard<std::mutex> lock(mappingHandlesMutex);
filepath = filepath_;
}
auto fileIter = fileHandles.find(dbname);
if (fileIter == fileHandles.end() && dbname_.find("c:.jdbf") == std::string::npos) {
log(LOGLEVEL::ERR_NOSEND, "[search_hash()]: File mapping not initialized for ", dbname);
return 2;
}
else if (fileIter == fileHandles.end()) {
return 2;
}
// Use fileData for subsequent searches
DWORD fileSize;
std::string fileContent;
{
std::lock_guard<std::mutex> lock(fileDataMutex);
fileSize = GetFileSize(fileHandles[dbname], NULL);
fileContent = std::string(fileData[dbname], fileSize);
}
// Search for the specific string in the file content
size_t foundPos = fileContent.find(hash);
if (foundPos != std::string::npos) {
//log(LOGLEVEL::VIRUS, "[search_hash()]: Found virus: ", hash, " in file: ", filepath);
virus_ctrl_store(filepath.c_str(), hash.c_str(), hash.c_str());
//afterwards do the processing with that file
virus_ctrl_process(hash.c_str());
return 1; // Found
}
return 0; // Not found
}
//function to get num of files in idr and its subdirs etc
int get_num_files(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
int num_files = 0;
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::ERR_NOSEND, "[get_num_files()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory.");
return 0;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
num_files += get_num_files(full_path);
}
else {
num_files++;
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
return num_files;
}
//this is the main function to scan folders. it will then start multuiple threads based on the number of cores / settings
void scan_folder(const std::string& directory) {
std::string search_path = directory + "\\*.*";
WIN32_FIND_DATA find_file_data;
HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data);
if (hFind == INVALID_HANDLE_VALUE) {
log(LOGLEVEL::WARN, "[scan_folder()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory.");
return;
}
do {
if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) {
continue; // Skip the current and parent directories
}
const std::string full_path = directory + "\\" + find_file_data.cFileName;
if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// If it's a directory, recurse into it
scan_folder(full_path);
}
else {
//action scanfile_t will start the trheads for scanning the hashes
//action_scanfile_t(full_path.c_str());
if (cnt > 47400) {
//say which file we are scanning now
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Scanning file: ", full_path);
}
//do multithreading here
int thread_timeout = 0;
while (num_threads >= std::thread::hardware_concurrency()) {
Sleep(10);
thread_timeout++;
if (thread_timeout == 100 * 60) {//if there is for more than 30 seconds no thread available, chances are high, that the threads did not temrinate correctly but aren t running anymore. so set the counter to 0 because else it might just stop the scan.
num_threads = 0;
}
}
if (is_valid_path(full_path)) { //filter out invalid paths and paths with weird characters
std::uintmax_t fileSize = std::filesystem::file_size(full_path);
if (fileSize > 4000000000) {//4gb
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: File too large to scan: ", full_path);
}
else {
std::thread scan_thread(scan_file_t, full_path);
scan_thread.detach();
}
}else
log(LOGLEVEL::INFO_NOSEND, "[scan_folder()]: Invalid path: ", full_path);
cnt++;
if (cnt % 100 == 0) {
printf("Processed %d files;\n", cnt);
//printf("Number of threads: %d\n", num_threads);
}
if (cnt % 1000 == 0) {
//send progress to com file
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "progress " << (cnt*100/(all_files+1)) << "\n";
answer_com.close();
}
}
}
} while (FindNextFile(hFind, &find_file_data) != 0);
FindClose(hFind);
}
//for singlethreaded scans
void action_scanfile(const std::string& filepath_) {
thread_init();
const std::string filepath(filepath_);
char* db_path = new char[300];
char* hash = new char[300];
if (is_valid_path(filepath_)) { //filter out invalid paths and paths with weird characters
std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else {
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) != 1) {
//notify desktop client by writing to answer_com file
//if there is now virus, we notify here. if there is a virus we only notify in the virus_ctrl_process function
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "not_found " << "\"" << filepath_ << "\"" << " " << hash << " " << "no_action_taken" << "\n";
answer_com.close();
}
}
}
else
log(LOGLEVEL::INFO_NOSEND, "[action_scanfile()]: Invalid path: ", filepath_);
thread_shutdown();
}
void action_scanfolder(const std::string& folderpath) {
thread_init();
thread_local std::string folderpath_(folderpath);
cnt = 0;
all_files = get_num_files(folderpath_);
//tell the desktop client that the scan has started
std::ofstream answer_com1(ANSWER_COM_PATH, std::ios::app);
if (answer_com1.is_open()) {
answer_com1 << "start " << all_files << "\n";
answer_com1.close();
}
scan_folder(folderpath_);
std::ofstream answer_com(ANSWER_COM_PATH, std::ios::app);
if (answer_com.is_open()) {
answer_com << "end " << "\"" << "nothing" << "\"" << " " << "nothing" << " " << "nothing" << "\n";
answer_com.close();
}
thread_shutdown();
}
void scan_file_t(const std::string& filepath_) {
num_threads++;
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
thread_local std::string hash_(md5_file_t(filepath));
if (strlen(hash_.c_str()) < 290)
strcpy_s(hash, 295, hash_.c_str());
else{
strcpy_s(hash, 295, "");
log(LOGLEVEL::ERR_NOSEND, "[scan_file_t()]: Could not calculate hash for file: ", filepath);
}
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
search_hash(db_path, hash, filepath);
num_threads--;
}
void scan_process_t(const std::string& filepath_) {
thread_local const std::string filepath(filepath_);
thread_local char* db_path = new char[300];
thread_local char* hash = new char[300];
strcpy_s(hash, 295, md5_file_t(filepath).c_str());
sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]);
if (search_hash(db_path, hash, filepath) == 1) {
//check if need to kill process
if (get_setting("virus_ctrl:virus_process_found:kill") == 1) {
//kill the process
kill_process(filepath.c_str());
log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath);
}
}
}
#endif

View File

@@ -1,78 +0,0 @@
#ifndef THREAD_CTRL_CPP
#define THREAD_CTRL_CPP
#include "thread_ctrl.h"
#include "log.h"
#include "well_known.h"
#include "scan.h"
#include "app_ctrl.h"
#include "update.h"
void split(char* input,const char delimiter, char* out1, char* out2) {
//split a string at the delimiter. the delimiter only occurs once. so the first part is out1 and the second part is out2
int i = 0;
int j = 0;
int k = 0;
while (input[i] != '\0') {
if (input[i] == delimiter) {
out1[j] = '\0';
i++;
while (input[i] != '\0') {
out2[k] = input[i];
i++;
k++;
}
out2[k] = '\0';
return;
}
else {
out1[j] = input[i];
i++;
j++;
}
}
}
int start_thread(const char* command) {
if (can_run_thread()) {
char* out2 = new char[100]; //for the command
char* out1 = new char[300]; //for the arguments
split((char*)command,';', (char*)out1, (char*)out2);
//log(LOGLEVEL::INFO, "[start_thread()]: starting command: ", out1, " with arguments: ",out2);
//printf("out1: %s\n", out1);
//printf("out2: %s\n", out2);
//determine what should be executed
if (strcmp(out1, "scanfile") == 0) {
log(LOGLEVEL::INFO, "[start_thread()]: starting scanfile with arguments: ", out2);
//start a new thread with the scanfile function
std::thread t1(action_scanfile, out2);
t1.detach();
}
else if (strcmp(out1, "scanfolder") == 0) {
//start a new thread with the scanfolder function
log(LOGLEVEL::INFO, "[start_thread()]: starting scanfolder with arguments: ", out2);
std::thread t1(action_scanfolder, out2);
log(LOGLEVEL::INFO, "[start_thread()]: started scanfolder with arguments: ", out2);
t1.detach();
}
else if (strcmp(out1, "update_settings") == 0) {
//start a new thread with the scanfolder function
log(LOGLEVEL::INFO, "[start_thread()]: starting update_settings with arguments: ", out2);
std::thread t1(action_update_settings);
t1.detach();
}
else if (strcmp(out1, "update_db") == 0) {
//start a new thread with the scanfolder function
log(LOGLEVEL::INFO, "[start_thread()]: starting update_db with arguments: ", out2);
std::thread t1(action_update_settings);
t1.detach();
}
while (can_run_thread()) {
//delay a bit, in order to wait until the thread is started
Sleep(10);
}
delete[] out1;
delete[] out2;
}
return 0;
}
#endif

View File

@@ -1,102 +0,0 @@
#include "utils.h"
#include <windows.h>
#include <string.h>
#include <iostream>
#include "log.h"
#include <tlhelp32.h>
#include <regex>
void split(const std::string& input, char delimiter, std::string& out1, std::string& out2) {
// Split a string at the delimiter. The delimiter only occurs once.
// The first part is stored in out1 and the second part in out2.
size_t pos = input.find(delimiter);
if (pos != std::string::npos) {
out1 = input.substr(0, pos);
out2 = input.substr(pos + 1);
}
}
bool is_valid_path(const std::string& filename) {
// Define a regular expression pattern for allowed characters
// This pattern allows letters (upper and lower case), numbers, underscores, and hyphens
std::regex pattern("[^<>:\"/\\\\|?*]+");
// Check if the filename matches the pattern
return std::regex_match(filename, pattern);
}
void startup(LPCTSTR lpApplicationName)
{
// additional information
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcess(lpApplicationName, // the path
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
std::string get_filename(const std::string& path) {
auto pos = path.find_last_of("\\");
if (pos == std::string::npos) {
// No directory separator found, return the original path
return path;
}
else {
// Return the substring after the last directory separator
return path.substr(pos + 1);
}
}
int strcasecmp(const std::string& s1, const std::string& s2) {
auto it1 = s1.begin();
auto it2 = s2.begin();
while (it1 != s1.end() && it2 != s2.end()) {
int diff = std::tolower(*it1) - std::tolower(*it2);
if (diff != 0)
return diff;
++it1;
++it2;
}
return 0;
}
void kill_process(const std::string& path) {
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(pEntry);
BOOL hRes = Process32First(hSnapShot, &pEntry);
while (hRes)
{
if (strcasecmp(pEntry.szExeFile, get_filename(path).c_str()) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, static_cast<DWORD>(pEntry.th32ProcessID));
if (hProcess != NULL)
{
TerminateProcess(hProcess, 9);
CloseHandle(hProcess);
}
else
log(LOGLEVEL::ERR, "[kill_process()]: Error while killing process: ", path);
}
hRes = Process32Next(hSnapShot, &pEntry);
}
CloseHandle(hSnapShot);
}

View File

@@ -1,105 +0,0 @@
#include "utils.h"
#include <windows.h>
#include <string.h>
#include <iostream>
#include "log.h"
#include <tlhelp32.h>
#include <regex>
#include <filesystem>
#include <regex>
void split(const std::string& input, char delimiter, std::string& out1, std::string& out2) {
// Split a string at the delimiter. The delimiter only occurs once.
// The first part is stored in out1 and the second part in out2.
size_t pos = input.find(delimiter);
if (pos != std::string::npos) {
out1 = input.substr(0, pos);
out2 = input.substr(pos + 1);
}
}
bool is_valid_path(const std::string& filename) {
for (char c : filename) {
if (c == '<' || c == '>' || c == '"' || c == '|' || c == '?' || c == '*') {
return 0; // Special character found
}
}
return 1; // No special character found
}
void startup(LPCTSTR lpApplicationName)
{
// additional information
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcess(lpApplicationName, // the path
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
std::string get_filename(const std::string& path) {
auto pos = path.find_last_of("\\");
if (pos == std::string::npos) {
// No directory separator found, return the original path
return path;
}
else {
// Return the substring after the last directory separator
return path.substr(pos + 1);
}
}
int strcasecmp(const std::string& s1, const std::string& s2) {
auto it1 = s1.begin();
auto it2 = s2.begin();
while (it1 != s1.end() && it2 != s2.end()) {
int diff = std::tolower(*it1) - std::tolower(*it2);
if (diff != 0)
return diff;
++it1;
++it2;
}
return 0;
}
void kill_process(const std::string& path) {
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(pEntry);
BOOL hRes = Process32First(hSnapShot, &pEntry);
while (hRes)
{
if (strcasecmp(pEntry.szExeFile, get_filename(path).c_str()) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, static_cast<DWORD>(pEntry.th32ProcessID));
if (hProcess != NULL)
{
TerminateProcess(hProcess, 9);
CloseHandle(hProcess);
}
else
log(LOGLEVEL::ERR, "[kill_process()]: Error while killing process: ", path);
}
hRes = Process32Next(hSnapShot, &pEntry);
}
CloseHandle(hSnapShot);
}

View File

@@ -1,105 +0,0 @@
#include "utils.h"
#include <windows.h>
#include <string.h>
#include <iostream>
#include "log.h"
#include <tlhelp32.h>
#include <regex>
#include <filesystem>
#include <regex>
void split(const std::string& input, char delimiter, std::string& out1, std::string& out2) {
// Split a string at the delimiter. The delimiter only occurs once.
// The first part is stored in out1 and the second part in out2.
size_t pos = input.find(delimiter);
if (pos != std::string::npos) {
out1 = input.substr(0, pos);
out2 = input.substr(pos + 1);
}
}
bool is_valid_path(const std::string& filename) {
for (char c : filename) {
if (c == '<' || c == '>' || c == '"' || c == '|' || c == '?' || c == '*' || c > 126 || c < 32 ) {
return 0; // Special character found
}
}
return 1; // No special character found
}
void startup(LPCTSTR lpApplicationName)
{
// additional information
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcess(lpApplicationName, // the path
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
std::string get_filename(const std::string& path) {
auto pos = path.find_last_of("\\");
if (pos == std::string::npos) {
// No directory separator found, return the original path
return path;
}
else {
// Return the substring after the last directory separator
return path.substr(pos + 1);
}
}
int strcasecmp(const std::string& s1, const std::string& s2) {
auto it1 = s1.begin();
auto it2 = s2.begin();
while (it1 != s1.end() && it2 != s2.end()) {
int diff = std::tolower(*it1) - std::tolower(*it2);
if (diff != 0)
return diff;
++it1;
++it2;
}
return 0;
}
void kill_process(const std::string& path) {
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(pEntry);
BOOL hRes = Process32First(hSnapShot, &pEntry);
while (hRes)
{
if (strcasecmp(pEntry.szExeFile, get_filename(path).c_str()) == 0)
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, static_cast<DWORD>(pEntry.th32ProcessID));
if (hProcess != NULL)
{
TerminateProcess(hProcess, 9);
CloseHandle(hProcess);
}
else
log(LOGLEVEL::ERR, "[kill_process()]: Error while killing process: ", path);
}
hRes = Process32Next(hSnapShot, &pEntry);
}
CloseHandle(hSnapShot);
}