diff --git a/src/client_backend/.vs/client_backend/v17/.suo b/src/client_backend/.vs/client_backend/v17/.suo index e8bb0c8..2974c2f 100644 Binary files a/src/client_backend/.vs/client_backend/v17/.suo and b/src/client_backend/.vs/client_backend/v17/.suo differ diff --git a/src/client_backend/.vs/client_backend/v17/Browse.VC.db b/src/client_backend/.vs/client_backend/v17/Browse.VC.db index 9e4fe29..bc4f157 100644 Binary files a/src/client_backend/.vs/client_backend/v17/Browse.VC.db and b/src/client_backend/.vs/client_backend/v17/Browse.VC.db differ diff --git a/src/client_backend/.vs/client_backend/v17/DocumentLayout.json b/src/client_backend/.vs/client_backend/v17/DocumentLayout.json index ac1d25d..c4c912a 100644 --- a/src/client_backend/.vs/client_backend/v17/DocumentLayout.json +++ b/src/client_backend/.vs/client_backend/v17/DocumentLayout.json @@ -2,6 +2,14 @@ "Version": 1, "WorkspaceRootPath": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\", "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_dir.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:check_dir.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\client_backend.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:client_backend.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, { "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:scan.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" @@ -15,29 +23,25 @@ "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:check_process.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, { - "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", - "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" - }, - { - "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\client_backend.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", - "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:client_backend.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\virus_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:virus_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, { "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\thread_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:thread_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, { - "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_dir.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", - "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:check_dir.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:scan.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, { "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\local_com.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:local_com.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, - { - "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\virus_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", - "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:virus_ctrl.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" - }, { "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\connect.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:connect.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" @@ -54,10 +58,6 @@ "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\log.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:log.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" }, - { - "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", - "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:scan.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" - }, { "AbsoluteMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\update.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", "RelativeMoniker": "D:0:0:{56E65283-AAC9-43F6-9613-72BE8D648AC4}|client_backend.vcxproj|solutionrelative:update.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" @@ -102,7 +102,7 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 2, + "SelectedChildIndex": 11, "Children": [ { "$type": "Document", @@ -118,32 +118,32 @@ }, { "$type": "Document", - "DocumentIndex": 13, + "DocumentIndex": 8, "Title": "scan.h", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.h", "RelativeDocumentMoniker": "scan.h", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.h", "RelativeToolTip": "scan.h", - "ViewState": "AQIAAAkAAAAAAAAAAABRwBMAAAAPAAAA", + "ViewState": "AQIAAA0AAAAAAAAAAAAAABUAAAADAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", "WhenOpened": "2024-03-13T06:41:43.701Z" }, { "$type": "Document", - "DocumentIndex": 0, + "DocumentIndex": 2, "Title": "scan.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.cpp", "RelativeDocumentMoniker": "scan.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\scan.cpp", "RelativeToolTip": "scan.cpp", - "ViewState": "AQIAAMwAAAAAAAAAAAAkwNgAAAA0AAAA", + "ViewState": "AQIAAEYBAAAAAAAAAAAawGcBAAAtAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", "WhenOpened": "2024-01-28T20:40:06.248Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 10, "Title": "connect.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\connect.cpp", "RelativeDocumentMoniker": "connect.cpp", @@ -155,31 +155,32 @@ }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 1, "Title": "client_backend.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\client_backend.cpp", "RelativeDocumentMoniker": "client_backend.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\client_backend.cpp", "RelativeToolTip": "client_backend.cpp", - "ViewState": "AQIAAEIAAAAAAAAAAAAAAGkAAAAJAAAA", + "ViewState": "AQIAADkAAAAAAAAAAAAawEwAAAA4AAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", - "WhenOpened": "2024-01-28T20:40:06.279Z" + "WhenOpened": "2024-01-28T20:40:06.279Z", + "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 5, + "DocumentIndex": 6, "Title": "thread_ctrl.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\thread_ctrl.cpp", "RelativeDocumentMoniker": "thread_ctrl.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\thread_ctrl.cpp", "RelativeToolTip": "thread_ctrl.cpp", - "ViewState": "AQIAAAYAAAAAAAAAAAAAADUAAABGAAAA", + "ViewState": "AQIAAAAAAAAAAAAAAAAAABwAAAAsAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", "WhenOpened": "2024-03-13T06:52:01.533Z" }, { "$type": "Document", - "DocumentIndex": 7, + "DocumentIndex": 9, "Title": "local_com.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\local_com.cpp", "RelativeDocumentMoniker": "local_com.cpp", @@ -191,15 +192,16 @@ }, { "$type": "Document", - "DocumentIndex": 8, + "DocumentIndex": 5, "Title": "virus_ctrl.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\virus_ctrl.cpp", "RelativeDocumentMoniker": "virus_ctrl.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\virus_ctrl.cpp", "RelativeToolTip": "virus_ctrl.cpp", - "ViewState": "AQIAAEsAAAAAAAAAAAAIwHYAAAARAAAA", + "ViewState": "AQIAAFQAAAAAAAAAAAAAACoAAAAAAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", - "WhenOpened": "2024-02-18T12:49:41.861Z" + "WhenOpened": "2024-02-18T12:49:41.861Z", + "EditorCaption": "" }, { "$type": "Document", @@ -215,7 +217,7 @@ }, { "$type": "Document", - "DocumentIndex": 12, + "DocumentIndex": 13, "Title": "log.h", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\log.h", "RelativeDocumentMoniker": "log.h", @@ -239,25 +241,26 @@ }, { "$type": "Document", - "DocumentIndex": 6, + "DocumentIndex": 0, "Title": "check_dir.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_dir.cpp", "RelativeDocumentMoniker": "check_dir.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_dir.cpp", "RelativeToolTip": "check_dir.cpp", - "ViewState": "AQIAAAAAAAAAAAAAAAAAABUAAAAAAAAA", + "ViewState": "AQIAAGIAAAAAAAAAAAAawKUAAAAAAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", - "WhenOpened": "2024-03-13T06:48:31.009Z" + "WhenOpened": "2024-03-13T06:48:31.009Z", + "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 1, + "DocumentIndex": 3, "Title": "utils.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.cpp", "RelativeDocumentMoniker": "utils.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.cpp", "RelativeToolTip": "utils.cpp", - "ViewState": "AQIAAD8AAAAAAAAAAAAAABgAAAAFAAAA", + "ViewState": "AQIAAAAAAAAAAAAAAAAAABkAAAAEAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", "WhenOpened": "2024-03-14T15:55:22.469Z", "EditorCaption": "" @@ -324,7 +327,7 @@ }, { "$type": "Document", - "DocumentIndex": 10, + "DocumentIndex": 11, "Title": "connect.h", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\connect.h", "RelativeDocumentMoniker": "connect.h", @@ -336,26 +339,26 @@ }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 4, "Title": "check_process.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_process.cpp", "RelativeDocumentMoniker": "check_process.cpp", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\check_process.cpp", "RelativeToolTip": "check_process.cpp", - "ViewState": "AQIAABIAAAAAAAAAAAAAADgAAABGAAAA", + "ViewState": "AQIAABUAAAAAAAAAAAAAADMAAAAaAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", "WhenOpened": "2024-03-14T13:35:33.369Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 7, "Title": "utils.h", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.h", "RelativeDocumentMoniker": "utils.h", "ToolTip": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\utils.h", "RelativeToolTip": "utils.h", - "ViewState": "AQIAAAAAAAAAAAAAAAAAAAoAAAAuAAAA", + "ViewState": "AQIAAAAAAAAAAAAAAAAAAAsAAAAbAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", "WhenOpened": "2024-03-14T15:55:30.524Z" }, @@ -373,7 +376,7 @@ }, { "$type": "Document", - "DocumentIndex": 11, + "DocumentIndex": 12, "Title": "local_schedule.cpp", "DocumentMoniker": "C:\\Users\\janis\\Documents\\Projekte_mit_c\\ma\\ma\\src\\client_backend\\local_schedule.cpp", "RelativeDocumentMoniker": "local_schedule.cpp", diff --git a/src/client_backend/check_dir.cpp b/src/client_backend/check_dir.cpp index fcdda24..ea3c9b8 100644 --- a/src/client_backend/check_dir.cpp +++ b/src/client_backend/check_dir.cpp @@ -45,8 +45,19 @@ void process_changes(const FILE_NOTIFY_INFORMATION* pInfo) { } else { //log(LOGLEVEL::INFO_NOSEND, "[process_changes()]: File ", filename_str, " has been changed. Scanning it for viruses"); + int thread_timeout = 0; + while (get_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. + set_num_threads(0); + } + } + //log(LOGLEVEL::INFO_NOSEND, "[process_changes()]: Scanning new file: ", filename_str); std::thread scan_thread(scan_file_t, filename_str); scan_thread.detach(); + Sleep(1); + } } } @@ -91,7 +102,11 @@ void monitor_directory(LPCSTR directory) { CloseHandle(hDir); return; } - + if (overlapped.hEvent == NULL) { + log(LOGLEVEL::ERR, "[monitor_directory()]: Error creating event for directory changes: ", GetLastError(), " while monitoring directory for changes"); + CloseHandle(hDir); + return; + } log(LOGLEVEL::INFO, "[monitor_directory()]: Monitoring directory: ", directory, " for changes"); // Wait for changes @@ -107,8 +122,7 @@ void monitor_directory(LPCSTR directory) { do { process_changes(pInfo); - pInfo = reinterpret_cast( - reinterpret_cast(pInfo) + pInfo->NextEntryOffset); + pInfo = reinterpret_cast(reinterpret_cast(pInfo) + pInfo->NextEntryOffset); } while (pInfo->NextEntryOffset != 0); diff --git a/src/client_backend/check_process.cpp b/src/client_backend/check_process.cpp index f726c27..f3c1a36 100644 --- a/src/client_backend/check_process.cpp +++ b/src/client_backend/check_process.cpp @@ -49,11 +49,22 @@ void monitor_processes() { strcpy_s(path, MAX_PATH, exePath); for (size_t z = 0; z < strlen(path); z++) path[z] = tolower(path[z]); + //log(LOGLEVEL::INFO_NOSEND, "[monitor_processes()]: New process: ", path); if (is_valid_path(path)) { //filter out invalid paths and paths with weird characters if (!is_folder_included(path) || is_folder_excluded(path)) { // Don't scan excluded files or folders } else { + int thread_timeout = 0; + while (get_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. + set_num_threads(0); + //log(LOGLEVEL::INFO_NOSEND, "[monitor_processes()]: Resetting thread counter because of timeout"); + } + } + //log(LOGLEVEL::INFO_NOSEND, "[monitor_processes()]: Scanning process: ", path); std::thread scan_thread(scan_process_t, path); scan_thread.detach(); } diff --git a/src/client_backend/client_backend.cpp b/src/client_backend/client_backend.cpp index 8d9c675..4ea84ee 100644 --- a/src/client_backend/client_backend.cpp +++ b/src/client_backend/client_backend.cpp @@ -19,7 +19,9 @@ #include "virus_ctrl.h" #include "update.h" #include "check_process.h" +#include "utils.h" int main(int argc, char*argv[]) { + //log(LOGLEVEL::INFO, "[main()]:Starting main thread."); //return 0; diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.ilk b/src/client_backend/client_backend/x64/Debug/client_backend.ilk index d9fa679..70a49a5 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.ilk and b/src/client_backend/client_backend/x64/Debug/client_backend.ilk differ diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.log b/src/client_backend/client_backend/x64/Debug/client_backend.log index 648c73e..be4e832 100644 --- a/src/client_backend/client_backend/x64/Debug/client_backend.log +++ b/src/client_backend/client_backend/x64/Debug/client_backend.log @@ -1,2 +1,37 @@  Quellen werden auf Modulabhängigkeiten überprüft... + check_dir.cpp +C:\Users\janis\Documents\Projekte_mit_c\ma\ma\src\client_backend\check_dir.cpp(49,38): warning C4018: ">=": Konflikt zwischen "signed" und "unsigned" +C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\xutility(4537,18): warning C4244: "=": Konvertierung von "wchar_t" in "char", möglicher Datenverlust + (Quelldatei „check_dir.cpp“ wird kompiliert) + C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\xutility(4537,18): + der Vorlageninstanziierungskontext (der älteste zuerst) ist + C:\Users\janis\Documents\Projekte_mit_c\ma\ma\src\client_backend\check_dir.cpp(36,29): + Siehe Verweis auf die gerade kompilierte Instanziierung "std::basic_string,std::allocator>::basic_string>>,0>(_Iter,_Iter,const _Alloc &)" der Funktions-Vorlage. + with + [ + _Elem=wchar_t, + _Iter=std::_String_iterator>>, + _Alloc=std::allocator + ] + C:\Users\janis\Documents\Projekte_mit_c\ma\ma\src\client_backend\check_dir.cpp(36,29): + Ersten Verweis auf "std::basic_string,std::allocator>::basic_string" in "process_changes" anzeigen + C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\xstring(2600,17): + Siehe Verweis auf die gerade kompilierte Instanziierung "void std::basic_string,std::allocator>::_Construct_from_iter(_Iter,const _Sent,_Size)" der Funktions-Vorlage. + with + [ + _Size_type=unsigned __int64, + _Iter=wchar_t *, + _Sent=wchar_t *, + _Size=unsigned __int64 + ] + C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\xstring(2756,18): + Siehe Verweis auf die gerade kompilierte Instanziierung "_OutIt *std::_Copy_n_unchecked4(_InIt,_SizeTy,_OutIt)" der Funktions-Vorlage. + with + [ + _OutIt=char *, + _Size=unsigned __int64, + _InIt=wchar_t *, + _SizeTy=unsigned __int64 + ] + client_backend.vcxproj -> C:\Users\janis\Documents\Projekte_mit_c\ma\ma\src\client_backend\x64\Debug\client_backend.exe diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.command.1.tlog b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.command.1.tlog index abccc2a..ff35fef 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.command.1.tlog and b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.command.1.tlog differ diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.read.1.tlog b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.read.1.tlog index af0f582..4811e18 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.read.1.tlog and b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.read.1.tlog differ diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.write.1.tlog b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.write.1.tlog index 19b6b88..17f48e3 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.write.1.tlog and b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/CL.write.1.tlog differ diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/client_backend.write.1u.tlog b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/client_backend.write.1u.tlog index b64e6a5..8005e1a 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/client_backend.write.1u.tlog and b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/client_backend.write.1u.tlog differ diff --git a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/link.read.1.tlog b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/link.read.1.tlog index 45dcab6..aa811da 100644 Binary files a/src/client_backend/client_backend/x64/Debug/client_backend.tlog/link.read.1.tlog and b/src/client_backend/client_backend/x64/Debug/client_backend.tlog/link.read.1.tlog differ diff --git a/src/client_backend/client_backend/x64/Debug/vc143.idb b/src/client_backend/client_backend/x64/Debug/vc143.idb index be535f2..a1f939f 100644 Binary files a/src/client_backend/client_backend/x64/Debug/vc143.idb and b/src/client_backend/client_backend/x64/Debug/vc143.idb differ diff --git a/src/client_backend/client_backend/x64/Debug/vc143.pdb b/src/client_backend/client_backend/x64/Debug/vc143.pdb index 8d51d34..c1a5311 100644 Binary files a/src/client_backend/client_backend/x64/Debug/vc143.pdb and b/src/client_backend/client_backend/x64/Debug/vc143.pdb differ diff --git a/src/client_backend/scan.cpp b/src/client_backend/scan.cpp index 56c7145..9ee1951 100644 --- a/src/client_backend/scan.cpp +++ b/src/client_backend/scan.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "md5hash.h" #include @@ -34,6 +35,15 @@ int cnt = 0; int num_threads = 0; int all_files = 0; +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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) { @@ -115,9 +125,9 @@ void cleanup() { //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; + thread_local std::string dbname; + thread_local std::string hash; + thread_local std::string filepath; { std::lock_guard lock(fileHandlesMutex); dbname = dbname_; @@ -161,98 +171,134 @@ int search_hash(const std::string& dbname_, const std::string& hash_, const std: return 0; // Not found } -//function to get num of files in idr and its subdirs etc +//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; + 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; - } + //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; + } - do { - if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) { - continue; // Skip the current and parent directories - } + // Stack to store directories to be traversed iteratively + std::stack directories; + directories.push(directory); - 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); + 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 { - num_files++; - } - } while (FindNextFile(hFind, &find_file_data) != 0); - FindClose(hFind); + 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 directories; // Stack to store directories to be scanned + 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); + directories.push(directory); - if (hFind == INVALID_HANDLE_VALUE) { - log(LOGLEVEL::WARN, "[scan_folder()]: Could not open directory: ", search_path.c_str(), " while scanning files inside directory."); - return; - } + while (!directories.empty()) { + std::string current_dir = directories.top(); + directories.pop(); - do { - if (strcmp(find_file_data.cFileName, ".") == 0 || strcmp(find_file_data.cFileName, "..") == 0) { - continue; // Skip the current and parent directories - } + std::string search_path = current_dir + "\\*.*"; + WIN32_FIND_DATA find_file_data; + HANDLE hFind = FindFirstFile(search_path.c_str(), &find_file_data); - - 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; + 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 } - } - 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); + 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 { - std::thread scan_thread(scan_file_t, full_path); - scan_thread.detach(); + // 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(); + } + } } - }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); } - } 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; + } + } } @@ -307,7 +353,7 @@ void action_scanfolder(const std::string& folderpath) { } void scan_file_t(const std::string& filepath_) { - num_threads++; + 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]; @@ -320,9 +366,10 @@ void scan_file_t(const std::string& filepath_) { } sprintf_s(db_path, 295, "%s\\%c%c.jdbf", DB_DIR, hash[0], hash[1]); search_hash(db_path, hash, filepath); - num_threads--; + 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]; @@ -336,5 +383,6 @@ void scan_process_t(const std::string& filepath_) { log(LOGLEVEL::VIRUS, "[scan_process_t()]: Killing process: ", filepath); } } + set_num_threads(get_num_threads() - 1); } #endif \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF2b9c1f.TMP b/src/client_backend/scan.cpp~RF2b9c1f.TMP new file mode 100644 index 0000000..1b36f08 --- /dev/null +++ b/src/client_backend/scan.cpp~RF2b9c1f.TMP @@ -0,0 +1,388 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF469c204.TMP b/src/client_backend/scan.cpp~RF469c204.TMP new file mode 100644 index 0000000..e091055 --- /dev/null +++ b/src/client_backend/scan.cpp~RF469c204.TMP @@ -0,0 +1,366 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF469e80a.TMP b/src/client_backend/scan.cpp~RF469e80a.TMP new file mode 100644 index 0000000..e69de29 diff --git a/src/client_backend/scan.cpp~RF469e81a.TMP b/src/client_backend/scan.cpp~RF469e81a.TMP new file mode 100644 index 0000000..b7e7165 --- /dev/null +++ b/src/client_backend/scan.cpp~RF469e81a.TMP @@ -0,0 +1,367 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF46a5887.TMP b/src/client_backend/scan.cpp~RF46a5887.TMP new file mode 100644 index 0000000..c4db40e --- /dev/null +++ b/src/client_backend/scan.cpp~RF46a5887.TMP @@ -0,0 +1,368 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF4708bfe.TMP b/src/client_backend/scan.cpp~RF4708bfe.TMP new file mode 100644 index 0000000..b1127f7 --- /dev/null +++ b/src/client_backend/scan.cpp~RF4708bfe.TMP @@ -0,0 +1,369 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF4748023.TMP b/src/client_backend/scan.cpp~RF4748023.TMP new file mode 100644 index 0000000..b988897 --- /dev/null +++ b/src/client_backend/scan.cpp~RF4748023.TMP @@ -0,0 +1,382 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.cpp~RF4948855.TMP b/src/client_backend/scan.cpp~RF4948855.TMP new file mode 100644 index 0000000..c210612 --- /dev/null +++ b/src/client_backend/scan.cpp~RF4948855.TMP @@ -0,0 +1,384 @@ +#ifndef SCAN_CPP +#define SCAN_CPP +#include "scan.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "md5hash.h" +#include +#include "well_known.h" +#include "log.h" +#include "virus_ctrl.h" +#include "app_ctrl.h" +#include // Include the mutex header +#include +#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 fileHandles; +std::unordered_map mappingHandles; +std::unordered_map fileData; + +int cnt = 0; +int num_threads = 0; +int all_files = 0; + +int get_num_threads() { + std::lock_guard lock(numThreadsMutex); + return num_threads; +} +int set_num_threads(int num) { + std::lock_guard 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(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 lock(fileHandlesMutex); + fileHandles[filename] = hFile; + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles[filename] = hMapping; + } + { + std::lock_guard 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 lock(fileHandlesMutex); + fileHandles.clear(); + } + { + std::lock_guard lock(mappingHandlesMutex); + mappingHandles.clear(); + } + { + std::lock_guard 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 lock(fileHandlesMutex); + dbname = dbname_; + } + { + std::lock_guard lock(fileDataMutex); + hash = hash_; + } + { + std::lock_guard 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 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 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 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 \ No newline at end of file diff --git a/src/client_backend/scan.h b/src/client_backend/scan.h index 1a231a4..a882a50 100644 --- a/src/client_backend/scan.h +++ b/src/client_backend/scan.h @@ -17,4 +17,6 @@ void action_scanfolder(const std::string& folderpath); void scan_file_t(const std::string& filepath_); int initialize(const std::string& folderPath); void scan_process_t(const std::string& filepath_); -void cleanup(); \ No newline at end of file +void cleanup(); +int get_num_threads(); +int set_num_threads(int num_threads); \ No newline at end of file diff --git a/src/client_backend/utils.cpp b/src/client_backend/utils.cpp index 7a7307f..f3f7c1b 100644 --- a/src/client_backend/utils.cpp +++ b/src/client_backend/utils.cpp @@ -4,6 +4,7 @@ #include #include "log.h" #include +#include #include #include #include @@ -118,4 +119,30 @@ bool file_exists(const std::string& filePath) { // Check if it's a regular file and not a directory return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; -} \ No newline at end of file +} + +int get_num_running_threads() { + DWORD runningThreads = 0; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + + if (hSnapshot != INVALID_HANDLE_VALUE) { + THREADENTRY32 te; + te.dwSize = sizeof(THREADENTRY32); + + if (Thread32First(hSnapshot, &te)) { + do { + if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + + sizeof(te.th32OwnerProcessID)) { + if (te.th32OwnerProcessID == GetCurrentProcessId()) { + runningThreads++; + } + } + te.dwSize = sizeof(THREADENTRY32); + } while (Thread32Next(hSnapshot, &te)); + } + + CloseHandle(hSnapshot); + } + + return runningThreads; +} diff --git a/src/client_backend/utils.h b/src/client_backend/utils.h index f87edc7..957812d 100644 --- a/src/client_backend/utils.h +++ b/src/client_backend/utils.h @@ -8,4 +8,5 @@ void kill_process(const std::string& path); void startup(LPCTSTR lpApplicationName); void split(const std::string& input, char delimiter, std::string& out1, std::string& out2); bool is_valid_path(const std::string& filename); -bool file_exists(const std::string& filename); \ No newline at end of file +bool file_exists(const std::string& filename); +int get_num_running_threads(); \ No newline at end of file diff --git a/src/client_backend/x64/Debug/client_backend.pdb b/src/client_backend/x64/Debug/client_backend.pdb index 02c347b..90c9a31 100644 Binary files a/src/client_backend/x64/Debug/client_backend.pdb and b/src/client_backend/x64/Debug/client_backend.pdb differ