├── Raccine.aps ├── Raccine.ico ├── images ├── logfile.png ├── screen1.png ├── screen2.png ├── screen3.png ├── screen4.png ├── screen5.png ├── screen6.png ├── eventlog2.png ├── raccine-gui1.png ├── raccine-gui2.png ├── raccine-gui3.png ├── raccine_logo.png ├── batch-installer.png ├── screen-tweet1.png ├── emotet-wo-raccine.png ├── eventlog-withdll.png ├── raccine-installer.png ├── emotet-with-raccine.png ├── eventlog-withoutdll.png ├── raccine-simulation.png └── screen-explorer-injection.png ├── source ├── Raccine │ ├── Raccine.aps │ ├── resource.h │ ├── Raccine.vcxproj.filters │ ├── Version.h │ ├── version.rc │ ├── Raccine.rc │ ├── raccine.cpp │ └── Raccine.vcxproj └── RaccineLib │ ├── EventLogHelper.h │ ├── Utils.h │ ├── RaccineLib.vcxproj.filters │ ├── RaccineConfig.h │ ├── YaraRuleRunner.h │ ├── Raccine.h │ ├── HandleWrapper.h │ ├── EventLog.cpp │ ├── RaccineConfig.cpp │ ├── YaraRuleRunner.cpp │ └── RaccineLib.vcxproj ├── data_samples └── mordor_raccine_simulation_mode.zip ├── RaccineGUI └── RaccineCfg │ ├── RaccineSettings │ ├── Raccine.ico │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Program.cs │ ├── frmAlert.cs │ ├── RaccineSettings.csproj │ ├── frmAlert.Designer.cs │ └── frmBootstrap.Designer.cs │ ├── RaccineElevatedCfg │ ├── Raccine.ico │ ├── raccine_logo.png │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Program.cs │ ├── RaccineCfg.csproj │ ├── app.manifest │ ├── RaccineElevatedCfg.csproj │ └── RaccineCfg.cs │ ├── RaccineRulesSync │ ├── App.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── app.manifest │ ├── RaccineRulesSync.csproj │ └── Program.cs │ └── RaccineCfg.sln ├── tests └── Raccine-Test │ ├── pch.cpp │ ├── pch.h │ ├── packages.config │ ├── test.cpp │ └── Raccine-Test.vcxproj ├── yara ├── ext-vars-test.yar ├── gen_raccine_kills.yar ├── mal_emotet.yar ├── mal_darkside.yar ├── other_0xa9five_poc.yar ├── mal_exchange_cryptominer.yar ├── ryuk-commandlines.yar ├── mal_revil.yar ├── gen_powershell_invocation.yar ├── powershell_loaders.yar ├── gen_ransomware_command_lines.yar └── in-memory │ └── gen_loaders.yar ├── reg-patches ├── raccine-reg-patch-net.reg ├── raccine-reg-patch-wmic.reg ├── raccine-reg-patch-bcdedit.reg ├── raccine-reg-patch-taskkill.reg ├── raccine-reg-patch-vssadmin.reg ├── raccine-reg-patch-wbadmin.reg ├── raccine-reg-patch-diskshadow.reg ├── raccine-reg-patch-powershell.reg ├── raccine-reg-patch-ransomware.reg └── raccine-reg-patch-uninstall.reg ├── explore.bat ├── sigma └── win_raccine_block.yml ├── .gitignore ├── LICENSE ├── GPO ├── Raccine.ADML └── Raccine.ADMX ├── .github └── workflows │ ├── test-cases.yml │ └── msbuild.yml ├── Raccine.sln ├── robot-tests └── robot-tests.ps1 └── install-raccine.bat /Raccine.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/Raccine.aps -------------------------------------------------------------------------------- /Raccine.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/Raccine.ico -------------------------------------------------------------------------------- /images/logfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/logfile.png -------------------------------------------------------------------------------- /images/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen1.png -------------------------------------------------------------------------------- /images/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen2.png -------------------------------------------------------------------------------- /images/screen3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen3.png -------------------------------------------------------------------------------- /images/screen4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen4.png -------------------------------------------------------------------------------- /images/screen5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen5.png -------------------------------------------------------------------------------- /images/screen6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen6.png -------------------------------------------------------------------------------- /images/eventlog2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/eventlog2.png -------------------------------------------------------------------------------- /images/raccine-gui1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine-gui1.png -------------------------------------------------------------------------------- /images/raccine-gui2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine-gui2.png -------------------------------------------------------------------------------- /images/raccine-gui3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine-gui3.png -------------------------------------------------------------------------------- /images/raccine_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine_logo.png -------------------------------------------------------------------------------- /images/batch-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/batch-installer.png -------------------------------------------------------------------------------- /images/screen-tweet1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen-tweet1.png -------------------------------------------------------------------------------- /source/Raccine/Raccine.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/source/Raccine/Raccine.aps -------------------------------------------------------------------------------- /images/emotet-wo-raccine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/emotet-wo-raccine.png -------------------------------------------------------------------------------- /images/eventlog-withdll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/eventlog-withdll.png -------------------------------------------------------------------------------- /images/raccine-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine-installer.png -------------------------------------------------------------------------------- /images/emotet-with-raccine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/emotet-with-raccine.png -------------------------------------------------------------------------------- /images/eventlog-withoutdll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/eventlog-withoutdll.png -------------------------------------------------------------------------------- /images/raccine-simulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/raccine-simulation.png -------------------------------------------------------------------------------- /images/screen-explorer-injection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/images/screen-explorer-injection.png -------------------------------------------------------------------------------- /data_samples/mordor_raccine_simulation_mode.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/data_samples/mordor_raccine_simulation_mode.zip -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Raccine.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/RaccineGUI/RaccineCfg/RaccineSettings/Raccine.ico -------------------------------------------------------------------------------- /tests/Raccine-Test/pch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // pch.cpp 3 | // Include the standard header and generate the precompiled header. 4 | // 5 | 6 | #include "pch.h" 7 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Raccine.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/RaccineGUI/RaccineCfg/RaccineElevatedCfg/Raccine.ico -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/raccine_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neo23x0/Raccine/HEAD/RaccineGUI/RaccineCfg/RaccineElevatedCfg/raccine_logo.png -------------------------------------------------------------------------------- /yara/ext-vars-test.yar: -------------------------------------------------------------------------------- 1 | rule env_vars_test { 2 | condition: 3 | Name contains "WMIC.exe" 4 | and CommandLine contains "delete justatest" 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /tests/Raccine-Test/pch.h: -------------------------------------------------------------------------------- 1 | // 2 | // pch.h 3 | // Header for standard system include files. 4 | // 5 | 6 | #pragma once 7 | 8 | #pragma warning(push, 3) 9 | #include "gtest/gtest.h" 10 | #pragma warning(pop) 11 | -------------------------------------------------------------------------------- /source/RaccineLib/EventLogHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "Utils.h" 6 | 7 | namespace eventloghelper 8 | { 9 | std::wstring GetEvents(); 10 | } -------------------------------------------------------------------------------- /tests/Raccine-Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-net.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\net.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-wmic.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\wmic.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /yara/gen_raccine_kills.yar: -------------------------------------------------------------------------------- 1 | rule ransomware_command_lines 2 | { 3 | strings: 4 | $s1 = "taskkill" nocase ascii 5 | $s2 = "RaccineSettings.exe" nocase ascii 6 | condition: 7 | all of them 8 | } 9 | 10 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineRulesSync/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-bcdedit.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\bcdedit.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-taskkill.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskkill.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-vssadmin.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vssadmin.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-wbadmin.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\wbadmin.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-diskshadow.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\diskshadow.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-powershell.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\powershell.exe] 4 | "Debugger"="C:\\Program Files\\Raccine\\Raccine.exe" -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-ransomware.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | ; RYUK Ransomware 4 | ; Source: https://thedfirreport.com/2020/10/18/ryuk-in-5-hours/ 5 | 6 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\xxx.exe] 7 | "Debugger"="notepad.exe" -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /yara/mal_emotet.yar: -------------------------------------------------------------------------------- 1 | rule MAL_Emotet_MalDocs { 2 | meta: 3 | description = "Detects PowerShell invocation as used by Emotet MalDocs" 4 | author = "Florian Roth" 5 | date = "2020-10-21" 6 | score = 60 7 | strings: 8 | /* Encoded Command */ 9 | $s1 = ".exe -ENCOD " ascii 10 | condition: 11 | 1 of them 12 | } 13 | -------------------------------------------------------------------------------- /source/Raccine/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Raccine.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /yara/mal_darkside.yar: -------------------------------------------------------------------------------- 1 | rule MAL_DarkSide_May21 { 2 | meta: 3 | description = "Detects PowerShell invocation as used by DarkSide loader" 4 | author = "Florian Roth" 5 | date = "2021-05-11" 6 | reference = "https://www.varonis.com/blog/darkside-ransomware/" 7 | score = 60 8 | strings: 9 | $ = " -ep bypass " ascii 10 | $ = "(0..61)|%{$s+=[char]" ascii 11 | $ = ";iex $" ascii 12 | condition: 13 | 2 of them 14 | } 15 | -------------------------------------------------------------------------------- /yara/other_0xa9five_poc.yar: -------------------------------------------------------------------------------- 1 | rule OTHER_0xA95_ChildsPlay_Jul21 { 2 | meta: 3 | description = "Detects code that deletes the local shadow copies" 4 | author = "Florian Roth" 5 | date = "2021-07-06" 6 | reference = "https://twitter.com/0xA9five/status/1412429707920936965" 7 | score = 60 8 | strings: 9 | $ = "Delleting following candidate" ascii wide 10 | $ = "Shadow copy set ID:" ascii wide 11 | condition: 12 | all of them 13 | } 14 | -------------------------------------------------------------------------------- /yara/mal_exchange_cryptominer.yar: -------------------------------------------------------------------------------- 1 | rule MAL_Exchange_CryptoMiner_Mar21_1 { 2 | meta: 3 | description = "Detects Cryptominer activity exploiting exchange vulnerability" 4 | author = "Florian Roth" 5 | date = "2021-03-16" 6 | reference = "https://twitter.com/ollieatnccgroup/status/1371840592246870023" 7 | score = 60 8 | strings: 9 | $s1 = "wmic.exe product where" 10 | $s2 = "%AntiVirus%" 11 | $s3 = "call uninstall /noninteractive" 12 | condition: 13 | all of them 14 | } 15 | -------------------------------------------------------------------------------- /source/Raccine/Raccine.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace RaccineElevatedCfg 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new RaccineCfg()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /explore.bat: -------------------------------------------------------------------------------- 1 | rem @ECHO OFF 2 | 3 | :: Download Components 4 | ECHO Create Temp directory for some downloads 5 | MKDIR bin 6 | :: Get YARA 7 | ECHO Downloading YARA ... 8 | powershell -executionpolicy bypass -Command "(New-Object System.Net.WebClient).DownloadFile('https://live.sysinternals.com/psloggedon.exe', '.\bin\psloggedon.exe')" 9 | powershell -executionpolicy bypass -Command "(New-Object System.Net.WebClient).DownloadFile('https://live.sysinternals.com/psinfo.exe', '.\bin\psinfo.exe')" 10 | set MYBIN=.\bin 11 | set 12 | whoami /groups 13 | tasklist /m 14 | dir %USERPROFILE% 15 | dir %TEMP% 16 | net localgroup administrators 17 | %MYBIN%\psloggedon /accepteula 18 | %MYBIN%\psinfo -d /accepteula 19 | dir "c:\Program Files\" 20 | -------------------------------------------------------------------------------- /yara/ryuk-commandlines.yar: -------------------------------------------------------------------------------- 1 | rule Ryuk_CmdLines { 2 | strings: 3 | /* Sandbox Report https://app.any.run/tasks/d41b5569-f3bd-409e-99b1-fc4c728d21aa/ */ 4 | $a1 = "net.exe" 5 | $a2 = "stop" fullword 6 | $a3 = " /y" 7 | 8 | $s1 = "audioendpointbuilder" fullword 9 | $s2 = "samss" fullword 10 | 11 | /* FireEye report https://www.fireeye.com/blog/threat-research/2020/10/kegtap-and-singlemalt-with-a-ransomware-chaser.html */ 12 | $ba1 = "process call create" 13 | $ba2 = "bitsadmin /transfer" 14 | $ba3 = "AppData" nocase 15 | 16 | $bx1 = "/transfer vVv" 17 | $bx2 = "temp\\vVv.exe" 18 | condition: 19 | all of ($a*) and 1 of ($s*) 20 | or all of ($ba*) 21 | or 1 of ($bx*) 22 | } 23 | -------------------------------------------------------------------------------- /sigma/win_raccine_block.yml: -------------------------------------------------------------------------------- 1 | title: Raccine Blocked Malicious Activity 2 | id: ce1ae413-3a83-4424-a61d-25827480c173 3 | description: Detects Raccine blocking the execution of an executable that has been invoked with parameters that are on the blocklist 4 | date: 2020/10/17 5 | modified: 2020/11/14 6 | author: Florian Roth, John Lambert 7 | references: 8 | - https://github.com/Neo23x0/Raccine 9 | tags: 10 | - attack.execution 11 | - attack.ta0002 12 | - attack.t1059.003 13 | logsource: 14 | product: windows 15 | service: application 16 | detection: 17 | selection: 18 | Source: Raccine 19 | EventID: 2 20 | Level: Warning 21 | condition: selection 22 | falsepositives: 23 | - Backup software triggering the blocks by accessing the volume shadow copies 24 | level: high -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace RaccineSettings 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | frmBootstrap f = new frmBootstrap(); 20 | f.Visible = false; 21 | if (!f.IsDisposed) // our single instance check will exit the constructor early 22 | Application.Run(f); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/RaccineCfg.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | netcoreapp3.1 6 | true 7 | app.manifest 8 | 9 | 10 | 11 | 12 | True 13 | True 14 | Resources.resx 15 | 16 | 17 | 18 | 19 | 20 | ResXFileCodeGenerator 21 | Resources.Designer.cs 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/frmAlert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Diagnostics.Eventing.Reader; 6 | using System.Drawing; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | /// Raccine settings launcher 11 | /// Initial code by @JohnLaTwC 12 | namespace RaccineSettings 13 | { 14 | public partial class frmAlert : Form 15 | { 16 | public frmAlert(EventRecord e) 17 | { 18 | InitializeComponent(); 19 | txtLog.Text = e.TimeCreated + "\r\n" + e.FormatDescription().Trim(); 20 | } 21 | 22 | private void lnkWebsite_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 23 | { 24 | System.Diagnostics.Process.Start("https://github.com/Neo23x0/Raccine/"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/Raccine/Version.h: -------------------------------------------------------------------------------- 1 | #ifndef VERSIONINFO_H 2 | #define VERSIONINFO_H 3 | 4 | #define VER_FILEVERSION 1,4,2,0 5 | #define VER_FILEVERSION_STR "1.4.2.0 BETA\0" 6 | 7 | #define VER_PRODUCTVERSION 1,4,2,0 8 | #define VER_PRODUCTVERSION_STR "1.4.2.0\0" 9 | 10 | #define VER_COMPANYNAME_STR "Raccine" 11 | #define VER_FILEDESCRIPTION_STR "A Simple Ransomware Vaccine - see https://github.com/Neo23x0/Raccine" 12 | #define VER_INTERNALNAME_STR "Raccine" 13 | #define VER_LEGALCOPYRIGHT_STR "Copyright 2021" 14 | #define VER_LEGALTRADEMARKS1_STR "All Rights Reserved" 15 | #define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR 16 | #define VER_ORIGINALFILENAME_STR "Raccine.exe" 17 | #define VER_PRODUCTNAME_STR "Raccine" 18 | 19 | #define VER_COMPANYDOMAIN_STR "https://github.com/Neo23x0/Raccine" 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ####################### 2 | # Visual Studio files # 3 | ####################### 4 | *.suo 5 | *.user 6 | *.sdf 7 | ipch/ 8 | .vs/ 9 | 10 | ################## 11 | # Python Ness # 12 | ################## 13 | __pycache__/ 14 | env/ 15 | *.pyc 16 | 17 | ################## 18 | # Compiled files # 19 | ################## 20 | linux/ 21 | bin/ 22 | obj/ 23 | Release/ 24 | Debug/ 25 | *.dll 26 | *.exe 27 | *.pdb 28 | *.obj 29 | *.log 30 | *.tlog 31 | *.htm 32 | *.pch 33 | watchlist.db 34 | 35 | # Prerequisites 36 | *.d 37 | 38 | # Compiled Object files 39 | *.slo 40 | *.lo 41 | *.o 42 | *.obj 43 | 44 | # Precompiled Headers 45 | *.gch 46 | *.pch 47 | 48 | # Compiled Dynamic libraries 49 | *.so 50 | *.dylib 51 | *.dll 52 | 53 | # Fortran module files 54 | *.mod 55 | *.smod 56 | 57 | # Compiled Static libraries 58 | *.lai 59 | *.la 60 | *.a 61 | *.lib 62 | 63 | # Executables 64 | *.exe 65 | *.out 66 | *.app 67 | *.json 68 | raccine.pdb 69 | vc140.pdb 70 | raccine.ilk 71 | Raccine/* 72 | Raccine.zip 73 | build_dist.bat 74 | 75 | packages/ -------------------------------------------------------------------------------- /source/Raccine/version.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "version.h" 3 | 4 | VS_VERSION_INFO VERSIONINFO 5 | FILEVERSION VER_FILEVERSION 6 | PRODUCTVERSION VER_PRODUCTVERSION 7 | BEGIN 8 | BLOCK "StringFileInfo" 9 | BEGIN 10 | BLOCK "040904E4" 11 | BEGIN 12 | VALUE "CompanyName", VER_COMPANYNAME_STR 13 | VALUE "FileDescription", VER_FILEDESCRIPTION_STR 14 | VALUE "FileVersion", VER_FILEVERSION_STR 15 | VALUE "InternalName", VER_INTERNALNAME_STR 16 | VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR 17 | VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR 18 | VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR 19 | VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR 20 | VALUE "ProductName", VER_PRODUCTNAME_STR 21 | VALUE "ProductVersion", VER_PRODUCTVERSION_STR 22 | END 23 | END 24 | 25 | BLOCK "VarFileInfo" 26 | BEGIN 27 | VALUE "Translation", 0x409, 1252 28 | END 29 | END 30 | -------------------------------------------------------------------------------- /yara/mal_revil.yar: -------------------------------------------------------------------------------- 1 | rule MAL_REvil_Dec20 { 2 | meta: 3 | description = "Detects PowerShell invocation as used by REvil loader" 4 | author = "Florian Roth" 5 | date = "2020-12-02" 6 | reference = "https://app.any.run/tasks/b5146ffd-328f-4d6f-9bf7-c544d02f1d47/" 7 | score = 60 8 | strings: 9 | /* Encoded Command */ 10 | $ = " -Enc \"PAA" ascii 11 | 12 | /* [Reflection.Assembly]::Load( */ 13 | $ = "WwBSAGUAZgBsAGUAYwB0AGkAbwBuAC4AQQBzAHMAZQBtAGIAbAB5AF0AOgA6AEwAbwBhAGQAKA" ascii 14 | $ = "sAUgBlAGYAbABlAGMAdABpAG8AbgAuAEEAcwBzAGUAbQBiAGwAeQBdADoAOgBMAG8AYQBkACgA" ascii 15 | $ = "bAFIAZQBmAGwAZQBjAHQAaQBvAG4ALgBBAHMAcwBlAG0AYgBsAHkAXQA6ADoATABvAGEAZAAoA" ascii 16 | 17 | /* Win32_Shadowcopy | ForEach-Object */ 18 | $ = "VwBpAG4AMwAyAF8AUwBoAGEAZABvAHcAYwBvAHAAeQAgAHwAIABGAG8AcgBFAGEAYwBoAC0ATwBiAGoAZQBjAHQA" ascii 19 | $ = "cAaQBuADMAMgBfAFMAaABhAGQAbwB3AGMAbwBwAHkAIAB8ACAARgBvAHIARQBhAGMAaAAtAE8AYgBqAGUAYwB0A" ascii 20 | $ = "XAGkAbgAzADIAXwBTAGgAYQBkAG8AdwBjAG8AcAB5ACAAfAAgAEYAbwByAEUAYQBjAGgALQBPAGIAagBlAGMAdA" ascii 21 | condition: 22 | 1 of them 23 | } 24 | -------------------------------------------------------------------------------- /reg-patches/raccine-reg-patch-uninstall.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\vssadmin.exe] 4 | 5 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\wmic.exe] 6 | 7 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\wbadmin.exe] 8 | 9 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\bcdedit.exe] 10 | 11 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\powershell.exe] 12 | 13 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\diskshadow.exe] 14 | 15 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\net.exe] 16 | 17 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskkill.exe] 18 | 19 | [-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Raccine] 20 | 21 | [-HKEY_CURRENT_USER\SOFTWARE\Raccine] 22 | 23 | [-HKEY_LOCAL_MACHINE\SOFTWARE\Raccine] 24 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaccineSettings.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaccineElevatedCfg.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /GPO/Raccine.ADML: -------------------------------------------------------------------------------- 1 | 2 | 3 | Raccine Policy 4 | Raccine Policy 5 | 6 | 7 | Raccine 8 | Enable Raccine Audit Only mode 9 | 10 | When this setting is enabled, Raccine will not terminate any processes. 11 | 12 | If you do not configure this policy setting, Raccine will operate in enforcement mode. 13 | 14 | If you enable this property setting, Raccine will only log and not take actions. 15 | 16 | Enable eventlog logging 17 | 18 | When this setting is enabled, Raccine will log key events to the Windows Event Log. 19 | 20 | If you do not configure this policy setting, Raccine will only log to the console and a local file. 21 | 22 | If you enable this property setting, Raccine will log to the Windows Application Log. 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /yara/gen_powershell_invocation.yar: -------------------------------------------------------------------------------- 1 | rule PowerShell_Susp_Parameter_Combo { 2 | meta: 3 | description = "Detects PowerShell invocation with suspicious parameters" 4 | author = "Florian Roth" 5 | reference = "https://goo.gl/uAic1X" 6 | date = "2017-03-12" 7 | score = 60 8 | type = "file" 9 | strings: 10 | /* Encoded Command */ 11 | $sa1 = " -enc " ascii nocase 12 | $sa2 = " -EncodedCommand " ascii nocase 13 | 14 | /* Window Hidden */ 15 | $sb1 = " -w hidden " ascii nocase 16 | $sb2 = " -window hidden " ascii nocase 17 | $sb3 = " -windowstyle hidden " ascii nocase 18 | 19 | /* Non Profile */ 20 | $sc1 = " -nop " ascii nocase 21 | $sc2 = " -noprofile " ascii nocase 22 | 23 | /* Non Interactive */ 24 | $sd1 = " -noni " ascii nocase 25 | $sd2 = " -noninteractive " ascii nocase 26 | 27 | /* Exec Bypass */ 28 | $se1 = " -ep bypass " ascii nocase 29 | $se2 = " -exec bypass " ascii nocase 30 | $se3 = " -executionpolicy bypass " ascii nocase 31 | $se4 = " -exec bypass " ascii nocase 32 | 33 | /* Single Threaded - PowerShell Empire */ 34 | $sf1 = " -sta " ascii 35 | 36 | $fp1 = "Chocolatey Software" 37 | $fp2 = "VBOX_MSI_INSTALL_PATH" 38 | condition: 39 | 4 of ($s*) and not 1 of ($fp*) 40 | } 41 | -------------------------------------------------------------------------------- /.github/workflows/test-cases.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | # Trigger the workflow on push or pull requests, but only for the 5 | # main branch 6 | push: 7 | branches: 8 | - main 9 | - '*/ci' 10 | pull_request: 11 | branches: 12 | - main 13 | 14 | jobs: 15 | robot-tests: 16 | runs-on: 'windows-latest' 17 | steps: 18 | - name: Checkout Raccine 19 | uses: actions/checkout@v2 20 | 21 | - name: Add msbuild to PATH 22 | uses: microsoft/setup-msbuild@v1.0.2 23 | env: 24 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 25 | 26 | - name: Setup NuGet 27 | uses: NuGet/setup-nuget@v1.0.2 28 | env: 29 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 30 | 31 | - name: Nuget Restore 32 | run: nuget restore Raccine.sln 33 | 34 | - name: Run msbuild of Raccine for x86 release 35 | run: msbuild -m /p:Configuration=Release /p:Platform=x86 36 | 37 | - name: Run msbuild of Raccine for x64 release 38 | run: msbuild -m /p:Configuration=Release /p:Platform=x64 39 | 40 | - name: Run msbuild of RaccineGUI for release 41 | run: msbuild -m /p:Configuration=Release 42 | working-directory: ./RaccineGUI/RaccineCfg 43 | 44 | - name: Run build_dist.bat 45 | run: ./build_dist.bat 46 | shell: cmd 47 | 48 | - name: Run Test 1 49 | run: ./robot-tests/robot-tests.ps1 50 | shell: powershell 51 | 52 | - name: Hard End 53 | run: git config --local --get remote.origin.url 54 | -------------------------------------------------------------------------------- /yara/powershell_loaders.yar: -------------------------------------------------------------------------------- 1 | rule SUSP_PowerShell_Loader_Generic { 2 | meta: 3 | description = "Detects different kinds of PowerShell loaders" 4 | author = "Florian Roth" 5 | date = "2020-12-10" 6 | modified = "2021-05-11" 7 | score = 60 8 | reference = "https://app.any.run/tasks/93fa402c-c6d7-4bc6-bf88-1ec954ae7f51/" 9 | reference2 = "https://app.any.run/tasks/d9d249db-f583-46e5-b774-511f28370aad/" 10 | strings: 11 | /* catch the ones that are easy to catch */ 12 | $s1 = "powershell" ascii nocase 13 | $s2 = "-w hidden" ascii nocase 14 | $s3 = " -e" nocase 15 | $s4 = " -command " ascii 16 | 17 | $enc01 = " IABz" 18 | $enc02 = " IABT" 19 | $enc03 = " cwBl" 20 | $enc04 = " cwBF" 21 | $enc05 = " UwBl" 22 | $enc06 = " UwBF" 23 | $enc07 = " SUVYI" 24 | $enc08 = " aWV4I" 25 | $enc09 = " SQBFAFgA" 26 | $enc10 = " aQBlAHgA" 27 | $enc11 = "SW52b2tlLVdlYlJlcXVlc3Q" 28 | 29 | /* catch the ones that try to hide */ 30 | $p1 = "powershell" nocase fullword 31 | 32 | /* filter valid casing */ 33 | $pf1 = "powershell" fullword 34 | $pf2 = "Powershell" fullword 35 | $pf3 = "PowerShell" fullword 36 | $pf4 = "POWERSHELL" fullword 37 | $pf5 = "powerShell" fullword 38 | condition: 39 | /* simple */ 40 | ( 3 of ($s*) and 1 of ($e*) ) or 41 | /* casing anomalies */ 42 | $p1 and not 1 of ($pf*) 43 | } 44 | -------------------------------------------------------------------------------- /source/Raccine/Raccine.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE 9, 1 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | #endif // English (United States) resources 48 | ///////////////////////////////////////////////////////////////////////////// 49 | 50 | 51 | 52 | #ifndef APSTUDIO_INVOKED 53 | ///////////////////////////////////////////////////////////////////////////// 54 | // 55 | // Generated from the TEXTINCLUDE 3 resource. 56 | // 57 | 58 | 59 | ///////////////////////////////////////////////////////////////////////////// 60 | #endif // not APSTUDIO_INVOKED 61 | 62 | MAINICON ICON "..\\..\\Raccine.ico" -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineRulesSync/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RaccineRulesSync")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RaccineRulesSync")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7c5f0973-5a9c-49fd-b674-f83d086333cf")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RaccineElevatedCfg")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RaccineElevatedCfg")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2a98f319-c56e-4786-98c2-b0ffd76becea")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RaccineSettings BETA")] 9 | [assembly: AssemblyDescription("Project website: https://github.com/Neo23x0/Raccine")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RaccineSettings")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("00d6357c-d619-4dd3-8f08-aaa4f45a0795")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GPO/Raccine.ADMX: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | # Trigger the workflow on push or pull requests, but only for the 5 | # main branch 6 | push: 7 | branches: 8 | - main 9 | - '*/ci' 10 | pull_request: 11 | branches: 12 | - main 13 | 14 | jobs: 15 | msbuild: 16 | runs-on: 'windows-latest' 17 | steps: 18 | - name: Checkout Raccine 19 | uses: actions/checkout@v2 20 | 21 | - name: Add msbuild to PATH 22 | uses: microsoft/setup-msbuild@v1.0.2 23 | env: 24 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 25 | 26 | - name: Setup NuGet 27 | uses: NuGet/setup-nuget@v1.0.2 28 | env: 29 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 30 | 31 | - name: Nuget Restore 32 | run: nuget restore Raccine.sln 33 | 34 | - name: Run msbuild of Raccine for x86 release 35 | run: msbuild -m /p:Configuration=Release /p:Platform=x86 36 | 37 | - name: Run msbuild of Raccine for x64 release 38 | run: msbuild -m /p:Configuration=Release /p:Platform=x64 39 | 40 | - name: Run msbuild of RaccineGUI for release 41 | run: msbuild -m /p:Configuration=Release 42 | working-directory: ./RaccineGUI/RaccineCfg 43 | 44 | - name: Run msbuild of RaccineGUI for release 45 | run: msbuild -m /p:Configuration=Release 46 | working-directory: ./RaccineGUI/RaccineCfg 47 | 48 | - name: Run Tests (x64) 49 | run: Raccine-Test.exe 50 | working-directory: ./x64/Release 51 | shell: cmd 52 | 53 | - name: Run Tests (x86) 54 | run: Raccine-Test.exe 55 | working-directory: ./Release 56 | shell: cmd 57 | 58 | - name: Run build_dist.bat 59 | run: ./build_dist.bat 60 | shell: cmd 61 | 62 | - name: Upload Raccine 63 | uses: actions/upload-artifact@v2 64 | with: 65 | name: Raccine 66 | path: Raccine/ 67 | -------------------------------------------------------------------------------- /source/RaccineLib/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | namespace utils 9 | { 10 | 11 | class ProcessDetail final 12 | { 13 | public: 14 | ProcessDetail(DWORD pid); 15 | 16 | ~ProcessDetail() = default; 17 | 18 | [[nodiscard]] std::wstring ToString(const std::wstring& szPrefix) const; 19 | 20 | [[nodiscard]] std::wstring ToPrintedString(const std::wstring& szPrefix) const; 21 | 22 | 23 | private: 24 | struct PROCESS_DETAIL 25 | { 26 | DWORD dwPid; 27 | std::wstring ExeName; 28 | std::wstring ExePath; 29 | std::wstring CommandLine; 30 | ULONG TimeSinceExeCreation; 31 | }; 32 | PROCESS_DETAIL ProcessDetailStruct; 33 | }; 34 | 35 | enum class Integrity 36 | { 37 | Error = 0, // Indicates integrity level could not be found 38 | Low = 1, 39 | Medium = 2, 40 | High = 3, 41 | System = 4, 42 | 43 | }; 44 | 45 | std::wstring to_lower(const std::wstring& input); 46 | 47 | bool isProcessAllowed(const PROCESSENTRY32W& pe32); 48 | 49 | std::wstring getImageName(DWORD pid); 50 | 51 | std::wstring getImageEXEPath(DWORD pid); 52 | 53 | Integrity getIntegrityLevel(HANDLE hProcess); 54 | 55 | DWORD getParentPid(DWORD pid); 56 | 57 | BOOL killProcess(DWORD dwProcessId, UINT uExitCode); 58 | 59 | std::wstring GetProcessCommandLine(DWORD pid); 60 | 61 | DWORD GetPriorityClassByPid(DWORD pid); 62 | 63 | std::wstring expand_environment_strings(const std::wstring& input); 64 | 65 | bool write_string_to_file(const std::filesystem::path& file_path, const std::wstring& string_to_write); 66 | 67 | std::optional convert_wstring_to_string(const std::wstring& input); 68 | 69 | ULONG getLastWriteTime(const std::wstring& szFilePath); 70 | 71 | std::wstring getFileName(const std::wstring& s); 72 | 73 | DWORD getCurrentSessionId(); 74 | 75 | std::wstring getUserSid(); 76 | 77 | int removeNewLines(std::wstring& str); 78 | 79 | } 80 | -------------------------------------------------------------------------------- /source/RaccineLib/RaccineLib.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /source/RaccineLib/RaccineConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #define RACCINE_REG_CONFIG L"SOFTWARE\\Raccine" 7 | #define RACCINE_REG_POLICY_CONFIG L"SOFTWARE\\Policies\\Raccine" 8 | 9 | constexpr wchar_t RACCINE_YARA_RULES_PATH[] = L"RulesDir"; 10 | constexpr wchar_t RACCINE_YARA_SCAN_MEMORY[] = L"ScanMemory"; 11 | constexpr wchar_t RACCINE_CONFIG_SHOW_GUI[] = L"ShowGui"; 12 | constexpr wchar_t RACCINE_CONFIG_LOG_ONLY[] = L"LogOnly"; 13 | constexpr wchar_t RACCINE_CONFIG_EVENTLOG_DATA_IN_RULES[] = L"EventlogRules"; 14 | constexpr wchar_t RACCINE_CONFIG_DEBUG[] = L"Debug"; 15 | constexpr wchar_t RACCINE_YARA_RULES_PATH_INMEMORY_PATH[] = L"in-memory"; 16 | // 17 | // Query for config in HKLM and HKLM\Software\Policies override by GPO 18 | // 19 | class 20 | RaccineConfig final 21 | { 22 | public: 23 | 24 | RaccineConfig(); 25 | 26 | ~RaccineConfig() = default; 27 | 28 | [[nodiscard]] bool log_only() const; 29 | [[nodiscard]] bool show_gui() const; 30 | [[nodiscard]] bool is_debug_mode() const; 31 | [[nodiscard]] bool use_eventlog_data_in_rules() const; 32 | [[nodiscard]] std::wstring yara_rules_directory() const; 33 | [[nodiscard]] std::wstring yara_in_memory_rules_directory() const; 34 | [[nodiscard]] bool scan_memory() const; 35 | 36 | RaccineConfig(const RaccineConfig&) = delete; 37 | RaccineConfig& operator=(const RaccineConfig&) = delete; 38 | RaccineConfig(RaccineConfig&&) = delete; 39 | RaccineConfig& operator=(RaccineConfig&&) = delete; 40 | 41 | private: 42 | 43 | static std::vector get_raccine_registry_paths(); 44 | static std::wstring get_yara_rules_directory(); 45 | static std::wstring get_yara_in_memory_rules_directory(); 46 | 47 | static bool read_flag_from_registry(const std::wstring& flag_name); 48 | static std::wstring read_string_from_registry(const std::wstring& string_name); 49 | 50 | static std::optional read_from_registry(const std::wstring& key_path, 51 | const std::wstring& value_name); 52 | 53 | static std::optional read_string_from_registry(const std::wstring& key_path, 54 | const std::wstring& value_name); 55 | 56 | const bool m_log_only; 57 | const bool m_show_gui; 58 | const bool m_is_debug_mode; 59 | const bool m_scan_memory; 60 | const bool m_use_eventlog_data_in_rules; 61 | std::wstring m_yara_rules_directory; 62 | std::wstring m_yara_in_memory_rules_directory; 63 | }; 64 | -------------------------------------------------------------------------------- /source/RaccineLib/YaraRuleRunner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "HandleWrapper.h" 6 | 7 | #define YARA_RESULTS_SUFFIX L".out" 8 | #ifdef _WIN64 9 | #define YARA_INSTANCE L"yara64.exe" 10 | #elif defined _WIN32 11 | #define YARA_INSTANCE L"yara32.exe" 12 | #endif 13 | constexpr UINT TIMEOUT = 5000; 14 | 15 | const std::wstring ext(L".yar"); 16 | const std::wstring compiled_ext(L".yarc"); 17 | 18 | class YaraRuleRunner final 19 | { 20 | public: 21 | [[nodiscard]] YaraRuleRunner(const std::filesystem::path& yara_rules_dir, 22 | const std::filesystem::path& raccine_program_directory); 23 | 24 | ~YaraRuleRunner() = default; 25 | 26 | [[nodiscard]] bool run_yara_rules_on_file(const std::filesystem::path& target_file, 27 | const std::wstring& command_line, 28 | std::wstring& out_yara_output, 29 | std::wstring& yara_cmd_optional_defines); 30 | 31 | [[nodiscard]] bool run_yara_rules_on_process(const DWORD dwPid, 32 | const std::wstring& command_line, 33 | std::wstring& out_yara_output, 34 | std::wstring& yara_cmd_optional_defines); 35 | 36 | // Deleted functions 37 | YaraRuleRunner(const YaraRuleRunner&) = delete; 38 | YaraRuleRunner& operator=(const YaraRuleRunner&) = delete; 39 | YaraRuleRunner(YaraRuleRunner&&) = delete; 40 | YaraRuleRunner& operator=(YaraRuleRunner&&) = delete; 41 | 42 | private: 43 | 44 | bool run_yara_rule_on_file(const std::filesystem::path& yara_rule, 45 | const std::filesystem::path& target_file, 46 | const std::wstring& command_line, 47 | std::wstring& out_yara_output, 48 | std::wstring& yara_cmd_optional_defines); 49 | 50 | bool run_yara_rule_on_process(const std::filesystem::path& yara_rule, 51 | const DWORD dwPid, 52 | const std::wstring& command_line, 53 | std::wstring& out_yara_output, 54 | std::wstring& yara_cmd_optional_defines); 55 | 56 | bool run_yara_process(std::wstring& command_line, HANDLE writepipe); 57 | 58 | std::wstring read_output_file(const std::filesystem::path& target_file); 59 | 60 | std::vector get_yara_rules(const std::filesystem::path& yara_rules_dir); 61 | 62 | bool CreateRedirectedOutput(PHANDLE phPipeRead, PHANDLE phPipeWrite); 63 | 64 | std::wstring ReadFromPipe(HANDLE readpipe); 65 | 66 | const std::filesystem::path m_raccine_program_directory; 67 | 68 | std::vector m_yara_rules; 69 | }; 70 | -------------------------------------------------------------------------------- /Raccine.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30413.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Raccine-Test", "tests\Raccine-Test\Raccine-Test.vcxproj", "{B6CF8E12-D257-4E81-8634-3D5E4320B7E9}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RaccineLib", "source\RaccineLib\RaccineLib.vcxproj", "{1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Raccine", "source\Raccine\Raccine.vcxproj", "{E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Debug|x64.ActiveCfg = Debug|x64 21 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Debug|x64.Build.0 = Debug|x64 22 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Debug|x86.ActiveCfg = Debug|Win32 23 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Debug|x86.Build.0 = Debug|Win32 24 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Release|x64.ActiveCfg = Release|x64 25 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Release|x64.Build.0 = Release|x64 26 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Release|x86.ActiveCfg = Release|Win32 27 | {B6CF8E12-D257-4E81-8634-3D5E4320B7E9}.Release|x86.Build.0 = Release|Win32 28 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Debug|x64.ActiveCfg = Debug|x64 29 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Debug|x64.Build.0 = Debug|x64 30 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Debug|x86.ActiveCfg = Debug|Win32 31 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Debug|x86.Build.0 = Debug|Win32 32 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Release|x64.ActiveCfg = Release|x64 33 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Release|x64.Build.0 = Release|x64 34 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Release|x86.ActiveCfg = Release|Win32 35 | {1E00BDF5-F2B2-4A59-8E3A-58EDBFE0E420}.Release|x86.Build.0 = Release|Win32 36 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Debug|x64.ActiveCfg = Debug|x64 37 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Debug|x64.Build.0 = Debug|x64 38 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Debug|x86.ActiveCfg = Debug|Win32 39 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Debug|x86.Build.0 = Debug|Win32 40 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Release|x64.ActiveCfg = Release|x64 41 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Release|x64.Build.0 = Release|x64 42 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Release|x86.ActiveCfg = Release|Win32 43 | {E402FCEB-A95B-44FF-BC00-B24CE6DAF0AB}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {4D604A7A-EE64-4DDB-9529-6524D18536A6} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaccineSettings.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RaccineSettings.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RaccineElevatedCfg.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RaccineElevatedCfg.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /yara/gen_ransomware_command_lines.yar: -------------------------------------------------------------------------------- 1 | rule ransomware_command_lines 2 | { 3 | meta: 4 | description = "This is a rewrite of the formerly hard-coded program plus command line combinations that have been blocked by the first version of Raccine" 5 | last_modified = "2022-08-22" 6 | strings: 7 | $e_vssadmin = "vssadmin" fullword nocase 8 | $e_wmic = "wmic" fullword nocase 9 | $e_wbadmin = "wbadmin" fullword nocase 10 | $e_bcdedit = "bcdedit" fullword nocase 11 | $e_powershell = "powershell" fullword nocase 12 | $e_diskshadow = "diskshadow" fullword nocase 13 | $e_fsutil = "fsutil" fullword nocase 14 | 15 | $p_delete = "delete" fullword nocase 16 | $p_shadows = "shadows" fullword nocase 17 | $p_shadowstorage= "shadowstorage" fullword nocase 18 | $p_resize = "resize" fullword nocase 19 | $p_shadowcopy = "shadowcopy" fullword nocase 20 | $p_catalog = "catalog" fullword nocase 21 | $p_quiet = "-quiet" nocase 22 | $p_quiet2 = "/quiet" nocase 23 | $p_backup1 = "backup" nocase fullword 24 | $p_backup2 = "systemstatebackup" nocase fullword 25 | $p_recoveryenabled = "recoveryenabled" fullword nocase 26 | $p_ignoreallfailures = "ignoreallfailures" fullword nocase 27 | $p_win32_shadowcopy = "win32_shadowcopy" fullword nocase 28 | $p_ps_version = "-version" nocase 29 | $p_ps_version2 = "/version" nocase 30 | $p_ps_enc = "-e" nocase 31 | $p_ps_enc2 = "/e" nocase 32 | $p_fsutil_usn = "usn deletejournal" nocase 33 | $p_ps_cmds1 = "JAB" 34 | $p_ps_cmds2 = "SQBFAF" 35 | $p_ps_cmds3 = "SQBuAH" 36 | $p_ps_cmds4 = "SUVYI" 37 | $p_ps_cmds5 = "cwBhA" 38 | $p_ps_cmds6 = "aWV4I" 39 | $p_ps_cmds7 = "aQBlAHgA" 40 | $p_ps_cmds8 = "cwB" 41 | $p_ps_cmds9 = "IAA" 42 | $p_ps_cmdsa = "IAB" 43 | $p_ps_cmdsb = "UwB" 44 | 45 | $fp1a = "ParentName=\"Termius.exe\"" 46 | $fp1b = "ParentExecutablePath=\"C:\\Program Files\\WindowsApps\\" 47 | condition: 48 | ( 49 | ( $e_vssadmin and $p_delete and $p_shadows) 50 | or ( $e_vssadmin and $p_delete and $p_shadowstorage) 51 | or ( $e_vssadmin and $p_resize and $p_shadowstorage) 52 | or ( $e_wmic and $p_delete and $p_shadowcopy) 53 | or ( $e_wbadmin and $p_delete and $p_catalog and 1 of ($p_quiet*)) 54 | or ( $e_wbadmin and $p_delete and 1 of ($p_backup*)) 55 | or ( $e_bcdedit and $p_ignoreallfailures) 56 | or ( $e_bcdedit and $p_recoveryenabled) 57 | or ( $e_diskshadow and $p_delete and $p_shadows) 58 | or ( $e_powershell and $p_win32_shadowcopy) 59 | or ( $e_powershell and 1 of ($p_ps_version*)) 60 | or ( $e_powershell and 1 of ($p_ps_enc*) and 1 of ($p_ps_cmds*)) 61 | or ( $e_fsutil and $p_fsutil_usn ) 62 | ) 63 | and not all of ($fp1*) 64 | } 65 | 66 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineCfg.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30523.141 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RaccineSettings", "RaccineSettings\RaccineSettings.csproj", "{00D6357C-D619-4DD3-8F08-AAA4F45A0795}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RaccineElevatedCfg", "RaccineElevatedCfg\RaccineElevatedCfg.csproj", "{2A98F319-C56E-4786-98C2-B0FFD76BECEA}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RaccineRulesSync", "RaccineRulesSync\RaccineRulesSync.csproj", "{7C5F0973-5A9C-49FD-B674-F83D086333CF}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Debug|x64 = Debug|x64 16 | Release|Any CPU = Release|Any CPU 17 | Release|x64 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Debug|x64.ActiveCfg = Debug|Any CPU 23 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Debug|x64.Build.0 = Debug|Any CPU 24 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Release|x64.ActiveCfg = Release|Any CPU 27 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795}.Release|x64.Build.0 = Release|Any CPU 28 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Debug|x64.ActiveCfg = Debug|Any CPU 31 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Debug|x64.Build.0 = Debug|Any CPU 32 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Release|x64.ActiveCfg = Release|Any CPU 35 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA}.Release|x64.Build.0 = Release|Any CPU 36 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Debug|x64.ActiveCfg = Debug|x64 39 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Debug|x64.Build.0 = Debug|x64 40 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Release|x64.ActiveCfg = Release|x64 43 | {7C5F0973-5A9C-49FD-B674-F83D086333CF}.Release|x64.Build.0 = Release|x64 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {9146C810-BDCD-400B-B948-45CE37B1496B} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /source/RaccineLib/Raccine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Raccine 4 | // A Simple Ransomware Vaccine 5 | // https://github.com/Neo23x0/Raccine 6 | // 7 | // Florian Roth, Ollie Whitehouse, Branislav Djalic, John Lambert 8 | // with help of Hilko Bengen 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include "HandleWrapper.h" 16 | #include "RaccineConfig.h" 17 | #include "YaraRuleRunner.h" 18 | #include "..\Raccine\Version.h" 19 | 20 | // Log Config and Flags 21 | #define RACCINE_DEFAULT_EVENTID 1 22 | #define RACCINE_EVENTID_MALICIOUS_ACTIVITY 2 23 | #define RACCINE_EVENTID_BENIGN_ACTIVITY 3 24 | 25 | #define RACCINE_DATA_DIRECTORY L"%PROGRAMDATA%\\Raccine" 26 | #define RACCINE_YARA_DIRECTORY L"%PROGRAMFILES%\\Raccine\\yara" 27 | #define RACCINE_PROGRAM_DIRECTORY L"%PROGRAMFILES%\\Raccine" 28 | #define RACCINE_USER_CONTEXT_DIRECTORY L"%TEMP%\\RaccineUserContext" 29 | 30 | 31 | /// 32 | /// Evaluate a set of yara rules on a command line 33 | /// 34 | /// The raccine configuration 35 | /// The command line to test 36 | /// if not empty, an output string containing match results is written to this parameter. 37 | /// TRUE if at least one match result was found 38 | bool EvaluateYaraRules(const RaccineConfig& raccine_config, 39 | const std::wstring& lpCommandLine, 40 | std::wstring& outYaraOutput, 41 | DWORD dwChildPid, 42 | DWORD dwParentPid, 43 | DWORD dwGrandParentPid); 44 | 45 | /// This function will optionally log messages to the eventlog 46 | void WriteEventLogEntryWithId(const std::wstring& pszMessage, DWORD dwEventId); 47 | 48 | void WriteEventLogEntry(const std::wstring& pszMessage); 49 | 50 | bool needs_powershell_workaround(const std::wstring& command_line); 51 | 52 | void trigger_gui_event(); 53 | 54 | // Check if process is in allowed list 55 | bool isAllowListed(DWORD pid); 56 | 57 | // Get timestamp 58 | std::string getTimeStamp(); 59 | 60 | // Format a log lines 61 | std::wstring logFormat(const std::wstring& cmdLine, const std::wstring& comment = L"done"); 62 | 63 | std::wstring logFormatLine(const std::wstring& line = L""); 64 | 65 | // Format the activity log lines 66 | std::wstring logFormatAction(DWORD pid, const std::wstring& imageName, const std::wstring& cmdLine, const std::wstring& comment = L"done"); 67 | 68 | // Log to file 69 | void logSend(const std::wstring& logStr); 70 | 71 | std::tuple createChildProcessWithDebugger(LPWSTR lpzchildCommandLine, 72 | DWORD dwAdditionalCreateParams); 73 | 74 | // Find all parent processes 75 | std::set find_processes_to_kill(const std::wstring& sCommandLine, std::wstring& sListLogs); 76 | 77 | // Find all parent processes and kill them 78 | void find_and_kill_processes(bool log_only, 79 | const std::wstring& sCommandLine, 80 | std::wstring& sListLogs); 81 | 82 | std::wstring CreateContextForProgram(DWORD pid, const std::wstring& szDefinePrefix); 83 | -------------------------------------------------------------------------------- /tests/Raccine-Test/test.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | 4 | 5 | #include "../../source/RaccineLib/HandleWrapper.h" 6 | #include "../../source/RaccineLib/Raccine.h" 7 | #include "../../source/RaccineLib/Utils.h" 8 | 9 | TEST(TestUtils, ToLower) 10 | { 11 | const std::wstring input = L"HellO WoRld"; 12 | std::wstring excepted_output = L"hello world"; 13 | EXPECT_EQ(excepted_output, utils::to_lower(input)); 14 | } 15 | 16 | TEST(TestGetImageName, System) 17 | { 18 | std::wstring image_name = utils::getImageName(4); 19 | ASSERT_EQ(image_name, L"System"); 20 | } 21 | 22 | TEST(TestGetImageName, NonExistant) 23 | { 24 | std::wstring image_name = utils::getImageName(3); 25 | ASSERT_EQ(image_name, L"(unavailable)"); 26 | } 27 | 28 | TEST(TestGetImageName, CurrentProcess) 29 | { 30 | std::wstring image_name = utils::getImageName(GetCurrentProcessId()); 31 | ASSERT_EQ(image_name, L"Raccine-Test.exe"); 32 | } 33 | 34 | TEST(TestGetParentPid, System) 35 | { 36 | DWORD parent_pid = utils::getParentPid(4); 37 | ASSERT_EQ(parent_pid, 0); 38 | } 39 | 40 | TEST(TestGetParentPid, NonExistant) 41 | { 42 | DWORD parent_pid = utils::getParentPid(3); 43 | ASSERT_EQ(parent_pid, 0); 44 | } 45 | 46 | TEST(TestGetIntegrityLevel, CurrentProcess) 47 | { 48 | ProcessHandleWrapper hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 49 | FALSE, 50 | GetCurrentProcessId()); 51 | if (!hProcess) { 52 | FAIL() << "Failed to open process"; 53 | } 54 | 55 | const utils::Integrity integrity = utils::getIntegrityLevel(hProcess); 56 | EXPECT_TRUE(integrity == utils::Integrity::Medium || integrity == utils::Integrity::High); 57 | } 58 | 59 | TEST(TestGetIntegrityLevel, InvalidHAndle) 60 | { 61 | const utils::Integrity integrity = utils::getIntegrityLevel(reinterpret_cast(1)); 62 | EXPECT_TRUE(integrity == utils::Integrity::Error); 63 | } 64 | 65 | TEST(TestExpandEnvironmentStrings, RaccineDataDirectory) 66 | { 67 | std::wstring result = utils::expand_environment_strings(RACCINE_DATA_DIRECTORY); 68 | EXPECT_EQ(result, L"C:\\ProgramData\\Raccine"); 69 | } 70 | 71 | TEST(TestFindProcessesToKill, Parent) 72 | { 73 | const std::wstring command_line = L"TEST_COMMAND_LINE"; 74 | std::wstring logs; 75 | const std::set pids = find_processes_to_kill(command_line, logs); 76 | EXPECT_FALSE(pids.empty()); 77 | 78 | const DWORD parent_pid = utils::getParentPid(GetCurrentProcessId()); 79 | EXPECT_TRUE(pids.contains(parent_pid)); 80 | 81 | // TODO: test logs output 82 | } 83 | 84 | TEST(TestFindProcessesToKill, System) 85 | { 86 | const std::wstring command_line = L"TEST_COMMAND_LINE"; 87 | std::wstring logs; 88 | const std::set pids = find_processes_to_kill(command_line, logs); 89 | EXPECT_FALSE(pids.empty()); 90 | 91 | EXPECT_FALSE(pids.contains(4)); 92 | } 93 | 94 | TEST(TestFindProcessesToKill, NonExistant) 95 | { 96 | const std::wstring command_line = L"TEST_COMMAND_LINE"; 97 | std::wstring logs; 98 | const std::set pids = find_processes_to_kill(command_line, logs); 99 | EXPECT_FALSE(pids.empty()); 100 | 101 | EXPECT_FALSE(pids.contains(3)); 102 | } 103 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineRulesSync/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineRulesSync/RaccineRulesSync.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7C5F0973-5A9C-49FD-B674-F83D086333CF} 8 | Exe 9 | RaccineRulesSync 10 | RaccineRulesSync 11 | v4.6.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | app.manifest 39 | 40 | 41 | true 42 | bin\x64\Debug\ 43 | DEBUG;TRACE 44 | full 45 | x64 46 | 7.3 47 | prompt 48 | MinimumRecommendedRules.ruleset 49 | 50 | 51 | bin\x64\Release\ 52 | TRACE 53 | true 54 | pdbonly 55 | x64 56 | 7.3 57 | prompt 58 | MinimumRecommendedRules.ruleset 59 | true 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /source/RaccineLib/HandleWrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma once 3 | #pragma once 4 | 5 | #include 6 | 7 | template< class traits > 8 | class HandleWrapper final 9 | { 10 | public: 11 | HandleWrapper() : 12 | m_handle(traits::InvalidValue) 13 | { 14 | } 15 | 16 | HandleWrapper(typename traits::HandleType value) : 17 | m_handle(value) 18 | { 19 | } 20 | 21 | ~HandleWrapper() 22 | { 23 | Close(); 24 | } 25 | 26 | void Close() 27 | { 28 | if (m_handle != traits::InvalidValue) { 29 | traits::Close(m_handle); 30 | m_handle = traits::InvalidValue; 31 | } 32 | } 33 | 34 | bool operator !() const 35 | { 36 | return m_handle == traits::InvalidValue; 37 | } 38 | 39 | operator bool() const 40 | { 41 | return m_handle != traits::InvalidValue; 42 | } 43 | 44 | operator typename traits::HandleType() 45 | { 46 | return m_handle; 47 | } 48 | 49 | typename traits::HandleType* operator&() 50 | { 51 | return &m_handle; 52 | } 53 | 54 | private: 55 | typename traits::HandleType m_handle; 56 | }; 57 | 58 | // Handle wrapper for handles from CreateToolhelp32Snapshot 59 | struct SnapshotHandleTraits 60 | { 61 | typedef HANDLE HandleType; 62 | inline static const HANDLE InvalidValue = INVALID_HANDLE_VALUE; 63 | 64 | static void Close(HANDLE value) 65 | { 66 | CloseHandle(value); 67 | } 68 | }; 69 | 70 | // Handle wrapper for handles from OpenProcess 71 | struct ProcessHandleTraits 72 | { 73 | typedef HANDLE HandleType; 74 | inline static const HANDLE InvalidValue = NULL; 75 | 76 | static void Close(HANDLE value) 77 | { 78 | CloseHandle(value); 79 | } 80 | }; 81 | 82 | // Handle wrapper for handles from OpenThread 83 | struct ThreadHandleTraits 84 | { 85 | typedef HANDLE HandleType; 86 | inline static const HANDLE InvalidValue = NULL; 87 | 88 | static void Close(HANDLE value) 89 | { 90 | CloseHandle(value); 91 | } 92 | 93 | }; 94 | // Handle wrapper for handles from RegisterEventSourceW 95 | struct EventSourceHandleTraits 96 | { 97 | typedef HANDLE HandleType; 98 | inline static const HANDLE InvalidValue = NULL; 99 | 100 | static void Close(HANDLE value) 101 | { 102 | DeregisterEventSource(value); 103 | } 104 | }; 105 | 106 | // Handle wrapper for handles from FindFirstFileW 107 | struct FindFileHandleTraits 108 | { 109 | typedef HANDLE HandleType; 110 | inline static const HANDLE InvalidValue = INVALID_HANDLE_VALUE; 111 | 112 | static void Close(HANDLE value) 113 | { 114 | FindClose(value); 115 | } 116 | }; 117 | 118 | // Handle wrapper for handles from OpenProcessToken 119 | struct TokenHandleTraits 120 | { 121 | typedef HANDLE HandleType; 122 | inline static const HANDLE InvalidValue = INVALID_HANDLE_VALUE; 123 | 124 | static void Close(HANDLE value) 125 | { 126 | CloseHandle(value); 127 | } 128 | }; 129 | 130 | // Handle wrapper for handles from OpenEvent 131 | struct EventHandleTraits 132 | { 133 | typedef HANDLE HandleType; 134 | inline static const HANDLE InvalidValue = NULL; 135 | 136 | static void Close(HANDLE value) 137 | { 138 | CloseHandle(value); 139 | } 140 | }; 141 | 142 | // Handle wrapper for handles from CreateFileW 143 | struct FileHandleTraits 144 | { 145 | typedef HANDLE HandleType; 146 | inline static const HANDLE InvalidValue = INVALID_HANDLE_VALUE; 147 | 148 | static void Close(HANDLE value) 149 | { 150 | CloseHandle(value); 151 | } 152 | }; 153 | 154 | using SnapshotHandleWrapper = HandleWrapper< SnapshotHandleTraits>; 155 | using ProcessHandleWrapper = HandleWrapper< ProcessHandleTraits>; 156 | using ThreadHandleWrapper = HandleWrapper< ThreadHandleTraits>; 157 | using EventSourceHandleWrapper = HandleWrapper< EventSourceHandleTraits>; 158 | using FindFileHandleWrapper = HandleWrapper< FindFileHandleTraits>; 159 | using TokenHandleWrapper = HandleWrapper< TokenHandleTraits>; 160 | using EventHandleWrapper = HandleWrapper< EventHandleTraits>; 161 | using FileHandleWrapper = HandleWrapper< FileHandleTraits>; 162 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/RaccineElevatedCfg.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2A98F319-C56E-4786-98C2-B0FFD76BECEA} 8 | WinExe 9 | RaccineElevatedCfg 10 | RaccineElevatedCfg 11 | v4.6.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | app.manifest 39 | 40 | 41 | Raccine.ico 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Form 61 | 62 | 63 | RaccineCfg.cs 64 | 65 | 66 | ResXFileCodeGenerator 67 | Resources.Designer.cs 68 | Designer 69 | 70 | 71 | True 72 | Resources.resx 73 | 74 | 75 | RaccineCfg.cs 76 | 77 | 78 | 79 | SettingsSingleFileGenerator 80 | Settings.Designer.cs 81 | 82 | 83 | True 84 | Settings.settings 85 | True 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /source/RaccineLib/EventLog.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLogHelper.h" 2 | 3 | #pragma comment(lib,"wevtapi.lib") 4 | 5 | namespace eventloghelper 6 | { 7 | //sysmon log is admin only by default. Add a Read ACE for interactive with (A;; 0x1;;; IU); 8 | //> wevtutil sl "Microsoft-Windows-Sysmon/Operational" / ca:D:(A;; 0xf0007;;; SY)(A;; 0x7;;; BA)(A;; 0x1;;; BO)(A;; 0x1;;; SO)(A;; 0x1;;; S - 1 - 5 - 32 - 573)(A;; 0x1;;; IU) 9 | // 10 | //> wevtutil gl "Microsoft-Windows-Sysmon/Operational" 11 | //name: Microsoft - Windows - Sysmon / Operational 12 | //channelAccess : D:(A;; 0xf0007;;; SY)(A;; 0x7;;; BA)(A;; 0x1;;; BO)(A;; 0x1;;; SO)(A;; 0x1;;; S - 1 - 5 - 32 - 573)(A;; 0x1;;; IU) 13 | 14 | std::wstring GetEvents() 15 | { 16 | PWSTR Buffer; 17 | ULONG BufferSize; 18 | ULONG BufferSizeNeeded; 19 | ULONG Count; 20 | EVT_HANDLE Event; 21 | ULONG Status; 22 | 23 | UINT cEventCountMax = 10; 24 | UINT cEvent = 0; 25 | 26 | DWORD dwSessionId = utils::getCurrentSessionId(); 27 | std::wstring session_id = L"" + std::to_wstring(dwSessionId) + L""; 28 | std::wstring current_usersid = L""; 29 | std::wstring ignore_process = L"C:\\Program Files\\Raccine\\"; 30 | std::wstring ignore_process2 = L"C:\\Windows\\System32\\conhost.exe"; 31 | 32 | std::wstring query = L"*[System[Task=1]]"; 33 | EVT_HANDLE Query = EvtQuery( 34 | NULL, 35 | L"Microsoft-Windows-Sysmon/Operational", 36 | query.c_str(), 37 | EvtQueryReverseDirection 38 | ); 39 | 40 | std::wstring event_detail(L""); 41 | 42 | // 43 | // Read each event and render it as XML. 44 | // 45 | 46 | Buffer = NULL; 47 | BufferSize = 0; 48 | BufferSizeNeeded = 0; 49 | 50 | while ((EvtNext(Query, 1, &Event, INFINITE, 0, &Count) != FALSE) && (cEvent < cEventCountMax)) 51 | { 52 | do { 53 | if (BufferSizeNeeded > BufferSize) { 54 | LocalFree(Buffer); 55 | BufferSize = BufferSizeNeeded; 56 | Buffer = (PWSTR) LocalAlloc(LPTR, BufferSize); 57 | if (Buffer == NULL) { 58 | Status = ERROR_OUTOFMEMORY; 59 | BufferSize = 0; 60 | break; 61 | } 62 | } 63 | 64 | if (EvtRender(NULL, 65 | Event, 66 | EvtRenderEventXml, 67 | BufferSize, 68 | Buffer, 69 | &BufferSizeNeeded, 70 | &Count) != FALSE) 71 | { 72 | Status = ERROR_SUCCESS; 73 | } 74 | else { 75 | Status = GetLastError(); 76 | } 77 | } while (Status == ERROR_INSUFFICIENT_BUFFER); 78 | 79 | // 80 | // Display either the event xml or an error message. 81 | // 82 | 83 | if (Status == ERROR_SUCCESS) 84 | { 85 | std::wstring xml_event(Buffer); 86 | 87 | //only process events for the current session 88 | if (xml_event.find(session_id) > 0 && 89 | xml_event.find(current_usersid) > 0 && 90 | xml_event.find(ignore_process) == std::wstring::npos && 91 | xml_event.find(ignore_process2) == std::wstring::npos) 92 | { 93 | event_detail += xml_event + L"\r\n"; 94 | cEvent++; 95 | } 96 | else 97 | { 98 | ; // skip this event 99 | } 100 | } 101 | 102 | 103 | EvtClose(Event); 104 | } 105 | 106 | // 107 | // When EvtNextChannelPath returns ERROR_NO_MORE_ITEMS, we have actually 108 | // iterated through all matching events and thus succeeded. 109 | // 110 | 111 | Status = GetLastError(); 112 | if (Status == ERROR_NO_MORE_ITEMS) { 113 | Status = ERROR_SUCCESS; 114 | } 115 | 116 | // 117 | // Free resources. 118 | // 119 | 120 | EvtClose(Query); 121 | LocalFree(Buffer); 122 | return event_detail; 123 | } 124 | 125 | } -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/RaccineSettings.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {00D6357C-D619-4DD3-8F08-AAA4F45A0795} 8 | WinExe 9 | RaccineSettings 10 | RaccineSettings 11 | v4.6.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | Raccine.ico 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Form 59 | 60 | 61 | frmBootstrap.cs 62 | 63 | 64 | Form 65 | 66 | 67 | frmAlert.cs 68 | 69 | 70 | 71 | 72 | frmBootstrap.cs 73 | 74 | 75 | frmAlert.cs 76 | 77 | 78 | ResXFileCodeGenerator 79 | Resources.Designer.cs 80 | Designer 81 | 82 | 83 | True 84 | Resources.resx 85 | 86 | 87 | SettingsSingleFileGenerator 88 | Settings.Designer.cs 89 | 90 | 91 | True 92 | Settings.settings 93 | True 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /robot-tests/robot-tests.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Test Cases 3 | # PoC 4 | # Florian Roth 5 | 6 | $RaccineInstallerFolder = ".\Raccine" 7 | $LogFile = "C:\ProgramData\Raccine\Raccine_log.txt" 8 | 9 | # Functions 10 | function Uninstall-Raccine { 11 | Invoke-Expression "$($RaccineInstallerFolder)\install-raccine.bat UNINSTALL" 12 | Start-Sleep -s 10 13 | } 14 | function Install-Raccine { 15 | Invoke-Expression "$($RaccineInstallerFolder)\install-raccine.bat FULL" 16 | Start-Sleep -s 10 17 | } 18 | function Install-Raccine-LogOnly { 19 | Invoke-Expression "$($RaccineInstallerFolder)\install-raccine.bat FULL_SIMU" 20 | Start-Sleep -s 10 21 | } 22 | function Is-Running($ProcessName) { 23 | $process = Get-Process $ProcessName -ErrorAction SilentlyContinue 24 | if ($process) { 25 | return $True 26 | } 27 | return $False 28 | } 29 | 30 | $MalCmds = @( 31 | "vssadmin.exe delete shadows", 32 | "powershell.exe -e JABbaTheHutt", 33 | "WMIC.exe delete justatest" # doesn't create a YARA match in Github workflow 34 | "bcdedit.exe recoveryenabled" 35 | ) 36 | 37 | $GoodCmds = @( 38 | "vssadmin.exe", 39 | "powershell.exe -EncodedCommand AllIsGood" 40 | ) 41 | 42 | # ######################################################## 43 | # Malicious Command Tests 44 | # 45 | 46 | Foreach ($Cmd in $MalCmds) { 47 | 48 | Write-Host " ########################################################## " 49 | Write-Host " MALICIOUS Command" 50 | Write-Host " $($Cmd)" 51 | Write-Host " ########################################################## " 52 | 53 | # Save some substrings 54 | $Img = $Cmd.Split(" ")[0] 55 | $ImgBase = $Img.Split(".")[0] 56 | Write-Host "Image File: $($Img)" 57 | 58 | # Install Raccine 59 | Install-Raccine-LogOnly 60 | 61 | # Run malicious command 62 | Invoke-Expression "& 'C:\Program Files\Raccine\Raccine.exe' $($Cmd)" 63 | Start-Sleep -s 10 64 | 65 | # Check correct handling 66 | # Log File 67 | $LogContent = Get-Content $LogFile 68 | $cointainsKeywords = $LogContent | %{$_ -match $Cmd -and $_ -Match 'malicious'} 69 | If ( -Not $cointainsKeywords ) { 70 | Write-Host "Log file content: $($LogContent)" 71 | Write-Host "Error: Log file entry of detection not found (Command: $($Cmd)" 72 | exit 1 73 | } 74 | 75 | # Eventlog 76 | $Result = Get-EventLog -LogName Application -Message *Raccine* -Newest 1 77 | If ( $Result.Message -NotMatch $Cmd ) { 78 | Write-Host $Result.Message 79 | Write-Host "Error: Eventlog entry of detection not found" 80 | exit 1 81 | } 82 | 83 | # Killed process / not hanging process 84 | if ( $ImgBase -NotMatch 'powershell') { 85 | #Write-Host "Testing if process $($ImgBase) is still running ..." 86 | If ( Is-Running($ImgBase) ) { 87 | Write-Host "Error: Malicious process is still running (probably suspended)" 88 | exit 1 89 | } 90 | } 91 | 92 | # End Message 93 | Write-Host "All checks completed successfully in test case: '$($Cmd)'" 94 | Start-Sleep -s 5 95 | 96 | # Cleanup 97 | Uninstall-Raccine 98 | } 99 | 100 | 101 | # ######################################################## 102 | # Good Command Tests 103 | # 104 | 105 | Foreach ($Cmd in $GoodCmds) { 106 | 107 | Write-Host " ########################################################## " 108 | Write-Host " GOOD Command" 109 | Write-Host " $($Cmd)" 110 | Write-Host " ########################################################## " 111 | 112 | # Save some substrings 113 | $Img = $Cmd.Split(" ")[0] 114 | $ImgBase = $Img.Split(".")[0] 115 | Write-Host "Image File: $($Img)" 116 | 117 | # Install Raccine 118 | Install-Raccine-LogOnly 119 | 120 | # Run malicious command 121 | Invoke-Expression "& 'C:\Program Files\Raccine\Raccine.exe' $($Cmd)" 122 | Start-Sleep -s 10 123 | 124 | # Check correct handling 125 | # Log File 126 | $LogContent = Get-Content $LogFile 127 | $cointainsKeywords = $LogContent | %{$_ -Match $Cmd -and $_ -Match 'benign'} 128 | If ( -Not $cointainsKeywords ) { 129 | Write-Host $LogContent 130 | Write-Host "Error: Log file entry of expected benign detection not found" 131 | exit 1 132 | } 133 | 134 | # Eventlog 135 | $Result = Get-EventLog -LogName Application -Message *Raccine* -Newest 1 136 | If ( $Result.Message -Match $Cmd -and $Result.Message -Match 'malicious') { 137 | Write-Host $Result.Message 138 | Write-Host "Error: Eventlog entry of detection found" 139 | exit 1 140 | } 141 | 142 | # End Message 143 | Write-Host "All good command checks completed successfully in test case: '$($Cmd)'" 144 | Start-Sleep -s 5 145 | 146 | # Cleanup 147 | Uninstall-Raccine 148 | } 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /yara/in-memory/gen_loaders.yar: -------------------------------------------------------------------------------- 1 | /* 2 | Modified version of gen_loaders.yar 3 | from https://github.com/Neo23x0/signature-base/blob/master/yara/gen_loaders.yar 4 | */ 5 | 6 | /* 7 | Yara Rule Set 8 | Copyright: Florian Roth 9 | Date: 2017-06-25 10 | Identifier: Rules that detect different malware characteristics 11 | Reference: Internal Research 12 | License: GPL 13 | */ 14 | 15 | import "pe" 16 | 17 | /* Rule Set ----------------------------------------------------------------- */ 18 | 19 | rule ReflectiveLoader { 20 | meta: 21 | description = "Detects a unspecified hack tool, crack or malware using a reflective loader - no hard match - further investigation recommended" 22 | reference = "Internal Research" 23 | score = 60 24 | strings: 25 | $s1 = "ReflectiveLoader" fullword ascii 26 | $s2 = "ReflectivLoader.dll" fullword ascii 27 | $s3 = "?ReflectiveLoader@@" ascii 28 | condition: 29 | 1 of them 30 | } 31 | 32 | /* 33 | Yara Rule Set 34 | Author: Florian Roth 35 | Date: 2017-08-20 36 | Identifier: Reflective DLL Loader 37 | Reference: Internal Research 38 | */ 39 | 40 | /* Rule Set ----------------------------------------------------------------- */ 41 | 42 | rule Reflective_DLL_Loader_Aug17_1 { 43 | meta: 44 | description = "Detects Reflective DLL Loader" 45 | license = "https://creativecommons.org/licenses/by-nc/4.0/" 46 | author = "Florian Roth" 47 | reference = "Internal Research" 48 | date = "2017-08-20" 49 | hash1 = "f2f85855914345eec629e6fc5333cf325a620531d1441313292924a88564e320" 50 | strings: 51 | $x1 = "\\Release\\reflective_dll.pdb" ascii 52 | $x2 = "reflective_dll.x64.dll" fullword ascii 53 | $s3 = "DLL Injection" fullword ascii 54 | $s4 = "?ReflectiveLoader@@YA_KPEAX@Z" fullword ascii 55 | condition: 56 | 1 of them 57 | } 58 | 59 | rule DLL_Injector_Lynx { 60 | meta: 61 | description = "Detects Lynx DLL Injector" 62 | license = "https://creativecommons.org/licenses/by-nc/4.0/" 63 | author = "Florian Roth" 64 | reference = "Internal Research" 65 | date = "2017-08-20" 66 | hash1 = "d594f60e766e0c3261a599b385e3f686b159a992d19fa624fad8761776efa4f0" 67 | strings: 68 | $x1 = " -p | -u [--obfuscate]" fullword wide 69 | $x2 = "You've selected to inject into process: %s" fullword wide 70 | $x3 = "Lynx DLL Injector" fullword wide 71 | $x4 = "Reflective DLL Injector" fullword wide 72 | $x5 = "Failed write payload: %lu" fullword wide 73 | $x6 = "Failed to start payload: %lu" fullword wide 74 | $x7 = "Injecting payload..." fullword wide 75 | condition: 76 | 1 of them 77 | } 78 | 79 | rule Reflective_DLL_Loader_Aug17_2 { 80 | meta: 81 | description = "Detects Reflective DLL Loader - suspicious - Possible FP could be program crack" 82 | license = "https://creativecommons.org/licenses/by-nc/4.0/" 83 | author = "Florian Roth" 84 | reference = "Internal Research" 85 | date = "2017-08-20" 86 | score = 60 87 | hash1 = "c2a7a2d0b05ad42386a2bedb780205b7c0af76fe9ee3d47bbe217562f627fcae" 88 | hash2 = "b90831aaf8859e604283e5292158f08f100d4a2d4e1875ea1911750a6cb85fe0" 89 | strings: 90 | $x1 = "\\ReflectiveDLLInjection-master\\" ascii 91 | $s2 = "reflective_dll.dll" fullword ascii 92 | $s3 = "DLL injection" fullword ascii 93 | $s4 = "_ReflectiveLoader@4" fullword ascii 94 | $s5 = "Reflective Dll Injection" fullword ascii 95 | condition: 96 | 1 of them 97 | } 98 | 99 | rule Reflective_DLL_Loader_Aug17_3 { 100 | meta: 101 | description = "Detects Reflective DLL Loader" 102 | license = "https://creativecommons.org/licenses/by-nc/4.0/" 103 | author = "Florian Roth" 104 | reference = "Internal Research" 105 | date = "2017-08-20" 106 | hash1 = "d10e4b3f1d00f4da391ac03872204dc6551d867684e0af2a4ef52055e771f474" 107 | strings: 108 | $s1 = "\\Release\\inject.pdb" fullword ascii 109 | $s2 = "!!! Failed to gather information on system processes! " fullword ascii 110 | $s3 = "reflective_dll.dll" fullword ascii 111 | $s4 = "[-] %s. Error=%d" fullword ascii 112 | $s5 = "\\Start Menu\\Programs\\reflective_dll.dll" ascii 113 | condition: 114 | 1 of them 115 | } 116 | 117 | rule Reflective_DLL_Loader_Aug17_4 { 118 | meta: 119 | description = "Detects Reflective DLL Loader" 120 | license = "https://creativecommons.org/licenses/by-nc/4.0/" 121 | author = "Florian Roth" 122 | reference = "Internal Research" 123 | date = "2017-08-20" 124 | hash1 = "205b881701d3026d7e296570533e5380e7aaccaa343d71b6fcc60802528bdb74" 125 | hash2 = "f76151646a0b94024761812cde1097ae2c6d455c28356a3db1f7905d3d9d6718" 126 | strings: 127 | $x1 = "

 >> >> >> Keylogger Installed - %s %s << << <<

" fullword ascii 128 | 129 | $s1 = "

----- Running Process -----

" fullword ascii 130 | $s2 = "

Operating system: %s

" fullword ascii 131 | $s3 = "

System32 dir: %s

" fullword ascii 132 | condition: 133 | 2 of them 134 | } -------------------------------------------------------------------------------- /source/RaccineLib/RaccineConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "RaccineConfig.h" 2 | 3 | #include 4 | #include 5 | 6 | 7 | #include "Raccine.h" 8 | #include "Utils.h" 9 | 10 | RaccineConfig::RaccineConfig() : 11 | m_log_only(read_flag_from_registry(RACCINE_CONFIG_LOG_ONLY)), 12 | m_show_gui(read_flag_from_registry(RACCINE_CONFIG_SHOW_GUI)), 13 | m_is_debug_mode(read_flag_from_registry(RACCINE_CONFIG_DEBUG)), 14 | m_scan_memory(read_flag_from_registry(RACCINE_YARA_SCAN_MEMORY)), 15 | m_use_eventlog_data_in_rules(read_flag_from_registry(RACCINE_CONFIG_EVENTLOG_DATA_IN_RULES)), 16 | m_yara_rules_directory(get_yara_rules_directory()), 17 | m_yara_in_memory_rules_directory(get_yara_in_memory_rules_directory()) 18 | { 19 | } 20 | 21 | bool RaccineConfig::log_only() const 22 | { 23 | return m_log_only; 24 | } 25 | 26 | bool RaccineConfig::show_gui() const 27 | { 28 | return m_show_gui; 29 | } 30 | 31 | bool RaccineConfig::is_debug_mode() const 32 | { 33 | return m_is_debug_mode; 34 | } 35 | 36 | 37 | bool RaccineConfig::scan_memory() const 38 | { 39 | return m_scan_memory; 40 | } 41 | 42 | bool RaccineConfig::use_eventlog_data_in_rules() const 43 | { 44 | return m_use_eventlog_data_in_rules; 45 | } 46 | 47 | std::wstring RaccineConfig::yara_rules_directory() const 48 | { 49 | return m_yara_rules_directory; 50 | } 51 | 52 | std::wstring RaccineConfig::yara_in_memory_rules_directory() const 53 | { 54 | return m_yara_in_memory_rules_directory; 55 | } 56 | 57 | 58 | std::vector RaccineConfig::get_raccine_registry_paths() 59 | { 60 | return { RACCINE_REG_CONFIG, RACCINE_REG_POLICY_CONFIG }; 61 | } 62 | 63 | std::wstring RaccineConfig::get_yara_rules_directory() 64 | { 65 | const std::wstring yara_directory = read_string_from_registry(RACCINE_YARA_RULES_PATH); 66 | if (!yara_directory.empty()) { 67 | return utils::expand_environment_strings(yara_directory); 68 | } 69 | 70 | return utils::expand_environment_strings(RACCINE_YARA_DIRECTORY); 71 | } 72 | 73 | std::wstring RaccineConfig::get_yara_in_memory_rules_directory() 74 | { 75 | const std::wstring yara_directory = read_string_from_registry(RACCINE_YARA_RULES_PATH); 76 | if (!yara_directory.empty()) { 77 | return utils::expand_environment_strings(yara_directory + L"\\" + RACCINE_YARA_RULES_PATH_INMEMORY_PATH); 78 | } 79 | 80 | return utils::expand_environment_strings(RACCINE_YARA_DIRECTORY) + +L"\\" + RACCINE_YARA_RULES_PATH_INMEMORY_PATH; 81 | } 82 | 83 | bool RaccineConfig::read_flag_from_registry(const std::wstring& flag_name) 84 | { 85 | for (const std::filesystem::path& registry_path : get_raccine_registry_paths()) { 86 | std::optional value = read_from_registry(registry_path, flag_name); 87 | if (value.has_value()) { 88 | return value.value() > 0; 89 | } 90 | } 91 | 92 | return false; 93 | } 94 | 95 | std::wstring RaccineConfig::read_string_from_registry(const std::wstring& string_name) 96 | { 97 | for (const std::filesystem::path& registry_path : get_raccine_registry_paths()) { 98 | std::optional value = read_string_from_registry(registry_path, string_name); 99 | if (value.has_value()) { 100 | return value.value(); 101 | } 102 | } 103 | 104 | return L""; 105 | } 106 | 107 | std::optional RaccineConfig::read_from_registry(const std::wstring& key_path, 108 | const std::wstring& value_name) 109 | { 110 | constexpr std::nullptr_t NO_TYPE = nullptr; 111 | DWORD result; 112 | DWORD size = sizeof result; 113 | 114 | const LSTATUS status = RegGetValueW(HKEY_LOCAL_MACHINE, 115 | key_path.c_str(), 116 | value_name.c_str(), 117 | RRF_RT_DWORD, 118 | NO_TYPE, 119 | &result, 120 | &size); 121 | if (status != ERROR_SUCCESS) { 122 | return std::nullopt; 123 | } 124 | 125 | return result; 126 | } 127 | 128 | std::optional RaccineConfig::read_string_from_registry(const std::wstring& key_path, 129 | const std::wstring& value_name) 130 | { 131 | constexpr std::nullptr_t NO_TYPE = nullptr; 132 | std::wstring result; 133 | DWORD size = 0; 134 | 135 | constexpr DWORD RESTRICT_TO_REG_SZ = RRF_RT_REG_SZ; 136 | 137 | LSTATUS status = RegGetValueW(HKEY_LOCAL_MACHINE, 138 | key_path.c_str(), 139 | value_name.c_str(), 140 | RESTRICT_TO_REG_SZ, 141 | NO_TYPE, 142 | result.data(), 143 | &size); 144 | if (status != ERROR_MORE_DATA) { 145 | return std::nullopt; 146 | } 147 | 148 | result.resize(size); 149 | 150 | status = RegGetValueW(HKEY_LOCAL_MACHINE, 151 | key_path.c_str(), 152 | value_name.c_str(), 153 | RRF_RT_REG_SZ, 154 | NO_TYPE, 155 | result.data(), 156 | &size); 157 | if (status != ERROR_SUCCESS) { 158 | return std::nullopt; 159 | } 160 | 161 | result.erase(std::find(result.begin(), result.end(), '\0'), result.end()); 162 | 163 | return result; 164 | } 165 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/frmAlert.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace RaccineSettings 2 | { 3 | partial class frmAlert 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAlert)); 32 | this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 33 | this.txtLog = new System.Windows.Forms.TextBox(); 34 | this.lnkWebsite = new System.Windows.Forms.LinkLabel(); 35 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 36 | this.splitContainer1.Panel1.SuspendLayout(); 37 | this.splitContainer1.Panel2.SuspendLayout(); 38 | this.splitContainer1.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // splitContainer1 42 | // 43 | this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 44 | this.splitContainer1.Location = new System.Drawing.Point(0, 0); 45 | this.splitContainer1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); 46 | this.splitContainer1.Name = "splitContainer1"; 47 | this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; 48 | // 49 | // splitContainer1.Panel1 50 | // 51 | this.splitContainer1.Panel1.BackColor = System.Drawing.Color.White; 52 | this.splitContainer1.Panel1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("splitContainer1.Panel1.BackgroundImage"))); 53 | this.splitContainer1.Panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; 54 | this.splitContainer1.Panel1.Controls.Add(this.lnkWebsite); 55 | // 56 | // splitContainer1.Panel2 57 | // 58 | this.splitContainer1.Panel2.Controls.Add(this.txtLog); 59 | this.splitContainer1.Size = new System.Drawing.Size(866, 593); 60 | this.splitContainer1.SplitterDistance = 313; 61 | this.splitContainer1.SplitterWidth = 3; 62 | this.splitContainer1.TabIndex = 0; 63 | this.splitContainer1.Text = "splitContainer1"; 64 | // 65 | // txtLog 66 | // 67 | this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill; 68 | this.txtLog.Font = new System.Drawing.Font("Consolas", 10F); 69 | this.txtLog.Location = new System.Drawing.Point(0, 0); 70 | this.txtLog.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); 71 | this.txtLog.Multiline = true; 72 | this.txtLog.Name = "txtLog"; 73 | this.txtLog.ReadOnly = true; 74 | this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both; 75 | this.txtLog.Size = new System.Drawing.Size(866, 277); 76 | this.txtLog.TabIndex = 0; 77 | // 78 | // lnkWebsite 79 | // 80 | this.lnkWebsite.AutoSize = true; 81 | this.lnkWebsite.Location = new System.Drawing.Point(557, 267); 82 | this.lnkWebsite.Name = "lnkWebsite"; 83 | this.lnkWebsite.Size = new System.Drawing.Size(120, 20); 84 | this.lnkWebsite.TabIndex = 0; 85 | this.lnkWebsite.TabStop = true; 86 | this.lnkWebsite.Text = "Project Website"; 87 | this.lnkWebsite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkWebsite_LinkClicked); 88 | // 89 | // frmAlert 90 | // 91 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 92 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 93 | this.ClientSize = new System.Drawing.Size(866, 593); 94 | this.Controls.Add(this.splitContainer1); 95 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 96 | this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); 97 | this.Name = "frmAlert"; 98 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 99 | this.Text = "Raccine Notification"; 100 | this.splitContainer1.Panel1.ResumeLayout(false); 101 | this.splitContainer1.Panel1.PerformLayout(); 102 | this.splitContainer1.Panel2.ResumeLayout(false); 103 | this.splitContainer1.Panel2.PerformLayout(); 104 | ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 105 | this.splitContainer1.ResumeLayout(false); 106 | this.ResumeLayout(false); 107 | 108 | } 109 | 110 | #endregion 111 | 112 | private System.Windows.Forms.SplitContainer splitContainer1; 113 | private System.Windows.Forms.TextBox txtLog; 114 | private System.Windows.Forms.LinkLabel lnkWebsite; 115 | } 116 | } -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /source/Raccine/raccine.cpp: -------------------------------------------------------------------------------- 1 | // Raccine 2 | // A Simple Ransomware Vaccine 3 | // https://github.com/Neo23x0/Raccine 4 | // 5 | // Florian Roth, Ollie Whitehouse, Branislav Djalic, John Lambert 6 | // with help of Hilko Bengen 7 | 8 | #include "RaccineLib/Raccine.h" 9 | 10 | #include 11 | 12 | #include "RaccineLib/RaccineConfig.h" 13 | #include "RaccineLib/Utils.h" 14 | 15 | int wmain(int argc, WCHAR* argv[]) 16 | { 17 | setlocale(LC_ALL, ""); 18 | DWORD threadExitcode = 0; 19 | 20 | std::vector command_line; 21 | std::wstring sCommandLine; 22 | 23 | // Append all original command line parameters to a string for later log messages 24 | for (int i = 1; i < argc; i++) { 25 | sCommandLine.append(std::wstring(argv[i]).append(L" ")); 26 | command_line.emplace_back(argv[i]); 27 | } 28 | 29 | const RaccineConfig configuration; 30 | 31 | // Launch the new child in a suspended state (CREATE_SUSPENDED) 32 | // this will allow yara rules to run against this process 33 | // if we should block, we will terminate it later 34 | 35 | //skip argv[0] and create a new command line string from our argv, 36 | //if we get a quoted path for the exe back, adjust the command line to skip past that. 37 | LPWSTR lpzchildCommandLine = GetCommandLine() + (wcslen(argv[0]) + 1); 38 | const std::wstring originalCommandLine(GetCommandLine()); 39 | if (originalCommandLine.starts_with(L"\"") && (wcslen(argv[0]) + 3) < originalCommandLine.length()) 40 | lpzchildCommandLine = GetCommandLine() + (wcslen(argv[0]) + 3); 41 | if (needs_powershell_workaround(sCommandLine)) { 42 | lpzchildCommandLine = static_cast(std::wstring(L"powershell.exe ").append(sCommandLine).data()); 43 | } 44 | 45 | auto [dwChildPid, hProcess, hThread] = createChildProcessWithDebugger(lpzchildCommandLine, CREATE_SUSPENDED); 46 | // TODO: What happens if the process isn't created? 47 | 48 | const DWORD dwParentPid = utils::getParentPid(GetCurrentProcessId()); 49 | 50 | const DWORD dwGrandParentPid = utils::getParentPid(dwParentPid); // parent of parent of raccine.exe 51 | 52 | std::wstring szYaraOutput; 53 | const bool bBlock = EvaluateYaraRules(configuration, 54 | sCommandLine, 55 | szYaraOutput, 56 | dwChildPid, 57 | dwParentPid, 58 | dwGrandParentPid); 59 | 60 | std::wstring sListLogs; 61 | 62 | // If activity that should be block has been registered (always log) 63 | if (bBlock) { 64 | std::wstring message; 65 | // Log to the windows Eventlog 66 | if (!configuration.log_only()) { 67 | // Eventlog 68 | message = L"Raccine detected malicious activity:\r\n" + sCommandLine + L"\r\n"; 69 | // Log to the text log file 70 | sListLogs.append(logFormat(sCommandLine, L"Raccine detected malicious activity")); 71 | } 72 | else { 73 | // Eventlog 74 | message = L"Raccine detected malicious activity:\r\n" + sCommandLine + L"\r\n(simulation mode)"; 75 | // Log to the text log file 76 | sListLogs.append(logFormat(sCommandLine, L"Raccine detected malicious activity (simulation mode)")); 77 | } 78 | 79 | 80 | // YARA Matches Detected 81 | if (bBlock && !szYaraOutput.empty()) { 82 | message += L"\r\n\r\nYara matches:\r\n" + szYaraOutput; 83 | sListLogs.append(logFormatLine(szYaraOutput)); 84 | } 85 | 86 | const utils::ProcessDetail details(dwChildPid); 87 | std::wstring context = L"\r\n\r\nRaccine Context:\r\n" + details.ToPrintedString(L"Child"); 88 | const utils::ProcessDetail detailsParent(dwParentPid); 89 | context += detailsParent.ToPrintedString(L"Parent"); 90 | const utils::ProcessDetail detailsGrandParent(dwGrandParentPid); 91 | context += detailsGrandParent.ToPrintedString(L"GrandParent"); 92 | message += context; 93 | 94 | WriteEventLogEntryWithId(message, RACCINE_EVENTID_MALICIOUS_ACTIVITY); 95 | 96 | // signal Event for UI to know an alert happened. If no UI is running, this has no effect. 97 | if (configuration.show_gui()) { 98 | trigger_gui_event(); 99 | } 100 | } 101 | else 102 | { 103 | if (configuration.log_only()) 104 | { 105 | std::wstring message; 106 | // Eventlog 107 | message = L"Raccine detected benign activity:\r\n" + sCommandLine + L"\r\n(simulation mode)"; 108 | WriteEventLogEntryWithId(message, RACCINE_EVENTID_BENIGN_ACTIVITY); 109 | // Log to the text log file 110 | sListLogs.append(logFormat(sCommandLine, L"Raccine detected benign activity (simulation mode)")); 111 | } 112 | } 113 | 114 | // If block and not simulation mode 115 | if (bBlock && !configuration.log_only()) { 116 | find_and_kill_processes(configuration.log_only(), sCommandLine, sListLogs); 117 | } 118 | 119 | 120 | // if we're in simulation mode or we didn't need to block the process, let it run 121 | if (configuration.log_only() || !bBlock) { 122 | if (hThread != INVALID_HANDLE_VALUE && hProcess != INVALID_HANDLE_VALUE) { 123 | 124 | ResumeThread(hThread); 125 | WaitForSingleObject(hProcess, INFINITE); 126 | if (GetExitCodeThread(hThread, &threadExitcode) == false) 127 | { 128 | if (configuration.is_debug_mode()) { 129 | wprintf(L"can't get return code. error number: %d\n", GetLastError()); 130 | } 131 | } 132 | } 133 | } 134 | else { 135 | if (bBlock) { 136 | utils::killProcess(dwChildPid, 1); 137 | } 138 | } 139 | 140 | //if (configuration.is_debug_mode()) { 141 | // wprintf(L"return code: %d\n", threadExitcode); 142 | //} 143 | // Log events 144 | logSend(sListLogs); 145 | 146 | return threadExitcode; 147 | } 148 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineSettings/frmBootstrap.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace RaccineSettings 2 | { 3 | partial class frmBootstrap 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmBootstrap)); 33 | this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); 34 | this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); 35 | this.mnuSettings = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.createTroubleshootingLogsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.mnuUpdateRules = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.mnuLastAlert = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.mnuExit = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.contextMenuStrip1.SuspendLayout(); 41 | this.SuspendLayout(); 42 | // 43 | // notifyIcon1 44 | // 45 | this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1; 46 | this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon"))); 47 | this.notifyIcon1.Text = "Raccine"; 48 | this.notifyIcon1.Visible = true; 49 | // 50 | // contextMenuStrip1 51 | // 52 | this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(24, 24); 53 | this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 54 | this.mnuSettings, 55 | this.createTroubleshootingLogsToolStripMenuItem, 56 | this.mnuUpdateRules, 57 | this.mnuLastAlert, 58 | this.mnuExit}); 59 | this.contextMenuStrip1.Name = "contextMenuStrip1"; 60 | this.contextMenuStrip1.Size = new System.Drawing.Size(312, 197); 61 | // 62 | // mnuSettings 63 | // 64 | this.mnuSettings.Name = "mnuSettings"; 65 | this.mnuSettings.Size = new System.Drawing.Size(311, 32); 66 | this.mnuSettings.Text = "&Settings"; 67 | this.mnuSettings.Click += new System.EventHandler(this.mnuSettings_Click); 68 | // 69 | // createTroubleshootingLogsToolStripMenuItem 70 | // 71 | this.createTroubleshootingLogsToolStripMenuItem.Name = "createTroubleshootingLogsToolStripMenuItem"; 72 | this.createTroubleshootingLogsToolStripMenuItem.Size = new System.Drawing.Size(311, 32); 73 | this.createTroubleshootingLogsToolStripMenuItem.Text = "Create &Troubleshooting Logs"; 74 | this.createTroubleshootingLogsToolStripMenuItem.Click += new System.EventHandler(this.createTroubleshootingLogsToolStripMenuItem_Click); 75 | // 76 | // mnuUpdateRules 77 | // 78 | this.mnuUpdateRules.Name = "mnuUpdateRules"; 79 | this.mnuUpdateRules.Size = new System.Drawing.Size(311, 32); 80 | this.mnuUpdateRules.Text = "Update &Rules"; 81 | this.mnuUpdateRules.Click += new System.EventHandler(this.updateRulesToolStripMenuItem_Click); 82 | // 83 | // mnuLastAlert 84 | // 85 | this.mnuLastAlert.Name = "mnuLastAlert"; 86 | this.mnuLastAlert.Size = new System.Drawing.Size(311, 32); 87 | this.mnuLastAlert.Text = "Last Alert"; 88 | this.mnuLastAlert.Click += new System.EventHandler(this.mnuLastAlert_Click); 89 | // 90 | // mnuExit 91 | // 92 | this.mnuExit.Name = "mnuExit"; 93 | this.mnuExit.Size = new System.Drawing.Size(311, 32); 94 | this.mnuExit.Text = "E&xit"; 95 | this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click); 96 | // 97 | // frmBootstrap 98 | // 99 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 100 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 101 | this.ClientSize = new System.Drawing.Size(408, 155); 102 | this.Name = "frmBootstrap"; 103 | this.ShowInTaskbar = false; 104 | this.Text = "Form1"; 105 | this.WindowState = System.Windows.Forms.FormWindowState.Minimized; 106 | this.contextMenuStrip1.ResumeLayout(false); 107 | this.ResumeLayout(false); 108 | 109 | } 110 | 111 | #endregion 112 | 113 | private System.Windows.Forms.NotifyIcon notifyIcon1; 114 | private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; 115 | private System.Windows.Forms.ToolStripMenuItem mnuSettings; 116 | private System.Windows.Forms.ToolStripMenuItem mnuExit; 117 | private System.Windows.Forms.ToolStripMenuItem mnuLastAlert; 118 | private System.Windows.Forms.ToolStripMenuItem createTroubleshootingLogsToolStripMenuItem; 119 | private System.Windows.Forms.ToolStripMenuItem mnuUpdateRules; 120 | } 121 | } -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineRulesSync/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Net.Http.Headers; 8 | using System.Text; 9 | using System.Text.RegularExpressions; 10 | using System.Web.Script.Serialization; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | using Microsoft.Win32; 14 | 15 | namespace RaccineSettings 16 | { 17 | class RulesSync 18 | { 19 | 20 | public static bool fCompileRules = false; 21 | static public void Main(String[] args) 22 | { 23 | var contentsUrl = $"https://api.github.com/repos/Neo23x0/Raccine/contents/yara?ref=main"; 24 | //var contentsUrl = $"https://api.github.com/repos/Neo23x0/Raccine/contents/yara?ref=yara-mem-matching"; 25 | SyncContentFromUrl(contentsUrl, ""); 26 | } 27 | 28 | public static string GetYaraDefines() 29 | { 30 | return " -d Name=\"\" -d ExecutablePath=\"\" -d CommandLine=\"\" -d TimeSinceExeCreation=0 -d ParentName=\"\" -d ParentExecutablePath=\"\" -d ParentCommandLine= -d ParentTimeSinceExeCreation=0 -d GrandParentName=\"\" -d GrandParentExecutablePath=\"\" -d GrandParentCommandLine=\"\" -d GrandParentTimeSinceExeCreation=0 "; 31 | } 32 | 33 | public static bool SyncContentFromUrl(string contentsUrl, string subdir) 34 | { 35 | String newLinePattern = "([\r]?\n)"; 36 | var httpClient = new HttpClient(); 37 | 38 | Console.WriteLine("Downloading rules from " + contentsUrl); 39 | var jsonData = string.Empty; 40 | 41 | try 42 | { 43 | using (var webClient = new System.Net.WebClient()) 44 | { 45 | webClient.Headers.Add("user-agent", "Mozilla/4.0"); 46 | jsonData = webClient.DownloadString(contentsUrl); 47 | } 48 | 49 | string szRulesDir = RulesDir; 50 | 51 | JavaScriptSerializer js = new JavaScriptSerializer(); 52 | Rule[] rules = js.Deserialize(jsonData); 53 | uint iRuleCount = 0; 54 | foreach (Rule rule in rules) 55 | { 56 | string type = rule.type; 57 | if (rule.name.EndsWith(".yar")) 58 | { 59 | using (var webClient = new System.Net.WebClient()) 60 | { 61 | webClient.Headers.Add("user-agent", "Mozilla/4.0"); 62 | string yararule = webClient.DownloadString(rule.download_url); 63 | 64 | string szDir = szRulesDir + "\\" + subdir; 65 | System.IO.Directory.CreateDirectory(szDir); 66 | 67 | string szRulePath = szDir + rule.name; 68 | Console.WriteLine("Updating rule " + szRulePath); 69 | 70 | using (System.IO.StreamWriter file = 71 | new System.IO.StreamWriter(szRulePath, false)) 72 | { 73 | file.WriteLine(Regex.Replace(yararule, newLinePattern, "\r\n")); 74 | file.Flush(); 75 | file.Close(); 76 | iRuleCount++; 77 | 78 | if (fCompileRules) 79 | { 80 | string szCompiledRulePath = szRulePath + "c"; // e.g. rule_file.yarc 81 | string compilation_program = ""; 82 | if (Environment.Is64BitOperatingSystem) 83 | { 84 | compilation_program = "%ProgramFiles%\\Raccine\\yarac64.exe"; 85 | } 86 | else 87 | { 88 | compilation_program = "%ProgramFiles%\\Raccine\\yarac32.exe"; 89 | } 90 | compilation_program = Environment.ExpandEnvironmentVariables(compilation_program); 91 | 92 | if (File.Exists(compilation_program)) 93 | { 94 | string command_line = GetYaraDefines() + "\"" + szRulePath + "\" \"" + szCompiledRulePath + "\""; 95 | compilation_program = "\"" + compilation_program + "\""; 96 | 97 | ProcessStartInfo psi = new ProcessStartInfo(compilation_program); 98 | psi.Arguments = command_line; 99 | psi.UseShellExecute = false; 100 | Process.Start(psi); 101 | if (File.Exists(szCompiledRulePath)) 102 | { 103 | Console.WriteLine("Compiled rule to {0}", szCompiledRulePath); 104 | } 105 | } 106 | else 107 | { 108 | Console.WriteLine("Can't find yara rule compiler: " + compilation_program); 109 | } 110 | } 111 | } 112 | } 113 | } 114 | else if (rule.type == "dir") 115 | { 116 | SyncContentFromUrl(rule.url, rule.name + "\\"); 117 | 118 | } 119 | } 120 | Console.WriteLine("Updated {0} rules.", iRuleCount); 121 | Thread.Sleep(2000); 122 | } 123 | catch (Exception e) 124 | { 125 | Console.WriteLine(e.Message); 126 | Thread.Sleep(4000); 127 | } 128 | 129 | return true; 130 | } 131 | 132 | public static string RulesDir 133 | { 134 | get 135 | { 136 | RegistryKey RaccineKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Raccine", false); 137 | String setting = (String)RaccineKey.GetValue("RulesDir"); 138 | if (String.IsNullOrEmpty(setting)) 139 | { 140 | setting = Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\Raccine\yara"); 141 | } 142 | Console.WriteLine("YARA Rules directory is: {0}", setting); 143 | return setting; 144 | } 145 | 146 | } 147 | } 148 | 149 | class Rule 150 | { 151 | public string name { get; set; } 152 | public string path { get; set; } 153 | public string sha { get; set; } 154 | public uint size { get; set; } 155 | 156 | public string url { get; set; } 157 | public string html_url { get; set; } 158 | public string git_url { get; set; } 159 | public string download_url { get; set; } 160 | public string type { get; set; } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /tests/Raccine-Test/Raccine-Test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {b6cf8e12-d257-4e81-8634-3d5e4320b7e9} 23 | Win32Proj 24 | 10.0.19041.0 25 | Application 26 | v142 27 | Unicode 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | Create 42 | Create 43 | Create 44 | Create 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {1e00bdf5-f2b2-4a59-8e3a-58edbfe0e420} 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Use 63 | pch.h 64 | Disabled 65 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 66 | EnableFastChecks 67 | MultiThreadedDebug 68 | Level4 69 | stdcpplatest 70 | true 71 | 72 | 73 | true 74 | Console 75 | 76 | 77 | 78 | 79 | Use 80 | pch.h 81 | Disabled 82 | X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 83 | EnableFastChecks 84 | MultiThreadedDebug 85 | Level4 86 | stdcpplatest 87 | true 88 | 89 | 90 | true 91 | Console 92 | 93 | 94 | 95 | 96 | Use 97 | pch.h 98 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 99 | MultiThreaded 100 | Level4 101 | ProgramDatabase 102 | stdcpplatest 103 | true 104 | 105 | 106 | true 107 | Console 108 | true 109 | true 110 | 111 | 112 | 113 | 114 | Use 115 | pch.h 116 | X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 117 | MultiThreaded 118 | Level4 119 | ProgramDatabase 120 | stdcpplatest 121 | true 122 | 123 | 124 | true 125 | Console 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /source/RaccineLib/YaraRuleRunner.cpp: -------------------------------------------------------------------------------- 1 | #include "YaraRuleRunner.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | YaraRuleRunner::YaraRuleRunner(const std::filesystem::path& yara_rules_dir, const std::filesystem::path& raccine_program_directory) : 8 | m_raccine_program_directory(raccine_program_directory), 9 | m_yara_rules(get_yara_rules(yara_rules_dir)) 10 | { 11 | } 12 | 13 | bool YaraRuleRunner::run_yara_rules_on_process(const DWORD dwPid, 14 | const std::wstring& command_line, 15 | std::wstring& out_yara_output, 16 | std::wstring& yara_cmd_optional_defines) 17 | { 18 | bool fRetVal = false; 19 | // run all rules, don't bail out early 20 | 21 | for (const std::filesystem::path& yara_rule : m_yara_rules) 22 | { 23 | //wprintf(L"Running with YARA rule: %s", yara_rule.c_str()); 24 | bool fSuccess = run_yara_rule_on_process(yara_rule, dwPid, command_line, out_yara_output, yara_cmd_optional_defines); 25 | if (fSuccess) 26 | fRetVal = true; 27 | } 28 | 29 | return fRetVal; 30 | } 31 | bool YaraRuleRunner::run_yara_rules_on_file(const std::filesystem::path& target_file, 32 | const std::wstring& command_line, 33 | std::wstring& out_yara_output, 34 | std::wstring& yara_cmd_optional_defines) 35 | { 36 | bool fRetVal = false; 37 | // run all rules, don't bail out early 38 | 39 | for (const std::filesystem::path& yara_rule : m_yara_rules) 40 | { 41 | //wprintf(L"Running with YARA rule: %s", yara_rule.c_str()); 42 | bool fSuccess = run_yara_rule_on_file(yara_rule, target_file, command_line, out_yara_output, yara_cmd_optional_defines); 43 | if (fSuccess) 44 | fRetVal = true; 45 | } 46 | 47 | return fRetVal; 48 | } 49 | 50 | bool YaraRuleRunner::CreateRedirectedOutput(PHANDLE phPipeRead, PHANDLE phPipeWrite) 51 | { 52 | SECURITY_ATTRIBUTES saAttr = { 0 }; 53 | saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 54 | saAttr.bInheritHandle = TRUE; 55 | saAttr.lpSecurityDescriptor = NULL; 56 | 57 | if (!CreatePipe(phPipeRead, phPipeWrite, &saAttr, 0)) 58 | { 59 | return false; 60 | } 61 | 62 | //the read side of the pipe is just for this process, not to be inherited. 63 | if (!SetHandleInformation(*phPipeRead, HANDLE_FLAG_INHERIT, 0)) 64 | { 65 | return false; 66 | } 67 | 68 | return true; 69 | } 70 | 71 | 72 | bool YaraRuleRunner::run_yara_rule_on_process(const std::filesystem::path& yara_rule, 73 | const DWORD dwPid, 74 | const std::wstring& command_line, 75 | std::wstring& out_yara_output, 76 | std::wstring& yara_cmd_optional_defines) 77 | { 78 | std::wstring yara_compiled_rule_option = L" "; 79 | 80 | if (yara_rule.filename().extension() == compiled_ext) 81 | { 82 | yara_compiled_rule_option = L" -C "; 83 | } 84 | 85 | std::wstring yara_command_line = L"\"" + m_raccine_program_directory.wstring() + L"\\" 86 | + YARA_INSTANCE + L"\"" + yara_compiled_rule_option + L"\"" + yara_rule.wstring() + L"\" " + std::to_wstring(dwPid) + L" -d MemoryScan=1 " + yara_cmd_optional_defines; 87 | 88 | 89 | HANDLE readpipe = INVALID_HANDLE_VALUE; 90 | HANDLE writepipe = INVALID_HANDLE_VALUE; 91 | 92 | if (!CreateRedirectedOutput(&readpipe, &writepipe)) 93 | { 94 | return false; 95 | } 96 | 97 | const bool yara_succeeded = run_yara_process(yara_command_line, writepipe); 98 | if (!yara_succeeded) { 99 | return false; 100 | } 101 | 102 | std::wstring yara_output = ReadFromPipe(readpipe); 103 | 104 | if (yara_output.empty()) 105 | { 106 | return false; 107 | } 108 | 109 | out_yara_output = L"Rule file: " + yara_rule.wstring() + L"\r\nYARA Output: " + yara_output + L"\r\n" + L"Command line: " + command_line + L"\r\n"; 110 | return true; 111 | } 112 | 113 | 114 | bool YaraRuleRunner::run_yara_rule_on_file(const std::filesystem::path& yara_rule, 115 | const std::filesystem::path& target_file, 116 | const std::wstring& command_line, 117 | std::wstring& out_yara_output, 118 | std::wstring& yara_cmd_optional_defines) 119 | { 120 | 121 | std::wstring yara_compiled_rule_option = L" "; 122 | 123 | if (yara_rule.filename().extension() == compiled_ext) 124 | { 125 | yara_compiled_rule_option = L" -C "; 126 | } 127 | 128 | std::wstring yara_command_line = L"\"" + m_raccine_program_directory.wstring() + L"\\" 129 | + YARA_INSTANCE + L"\"" + yara_compiled_rule_option + L"\"" + yara_rule.wstring() + L"\" " + target_file.wstring() + L" " + yara_cmd_optional_defines; 130 | 131 | 132 | HANDLE readpipe = INVALID_HANDLE_VALUE; 133 | HANDLE writepipe = INVALID_HANDLE_VALUE; 134 | 135 | if (!CreateRedirectedOutput(&readpipe, &writepipe)) 136 | { 137 | return false; 138 | } 139 | 140 | const bool yara_succeeded = run_yara_process(yara_command_line, writepipe); 141 | if (!yara_succeeded) { 142 | return false; 143 | } 144 | 145 | std::wstring yara_output = ReadFromPipe(readpipe); 146 | 147 | if (yara_output.empty()) 148 | { 149 | return false; 150 | } 151 | 152 | out_yara_output = L"Rule file: " + yara_rule.wstring() + L"\r\nYARA Output: " + yara_output + L"\r\n" + L"Command line: " + command_line + L"\r\n"; 153 | return true; 154 | } 155 | 156 | bool YaraRuleRunner::run_yara_process(std::wstring& command_line, HANDLE writepipe) 157 | { 158 | STARTUPINFO info{}; 159 | info.cb = sizeof info; 160 | info.hStdOutput = writepipe; 161 | info.dwFlags |= STARTF_USESTDHANDLES; 162 | 163 | PROCESS_INFORMATION processInfo{}; 164 | 165 | if (!CreateProcessW( 166 | NULL, 167 | command_line.data(), 168 | NULL, 169 | NULL, 170 | TRUE, 171 | CREATE_NO_WINDOW, 172 | NULL, 173 | NULL, 174 | &info, 175 | &processInfo)) { 176 | return false; 177 | } 178 | 179 | CloseHandle(processInfo.hThread); 180 | CloseHandle(writepipe); 181 | 182 | const DWORD wait_result = WaitForSingleObject(processInfo.hProcess, TIMEOUT); 183 | 184 | CloseHandle(processInfo.hProcess); 185 | 186 | if (wait_result == WAIT_TIMEOUT) { 187 | return false; 188 | } 189 | 190 | return true; 191 | } 192 | 193 | std::wstring YaraRuleRunner::ReadFromPipe(HANDLE readpipe) 194 | { 195 | DWORD dwRead; 196 | CHAR chBuf[1000] = { 0 }; 197 | BOOL bSuccess = FALSE; 198 | for (;;) 199 | { 200 | 201 | bSuccess = ReadFile(readpipe, chBuf, sizeof(chBuf), &dwRead, NULL); 202 | if (!bSuccess || dwRead == 0) break; 203 | } 204 | CloseHandle(readpipe); 205 | 206 | if (strlen(chBuf) == 0) 207 | { 208 | return L""; 209 | } 210 | std::wstring output_string(&chBuf[0], &chBuf[ARRAYSIZE(chBuf)]); 211 | 212 | return output_string; 213 | } 214 | std::wstring YaraRuleRunner::read_output_file(const std::filesystem::path& target_file) 215 | { 216 | std::ifstream file_stream(target_file); 217 | const std::string str((std::istreambuf_iterator(file_stream)), 218 | std::istreambuf_iterator()); 219 | return std::wstring(str.cbegin(), str.cend()); 220 | } 221 | 222 | std::vector YaraRuleRunner::get_yara_rules(const std::filesystem::path& yara_rules_dir) 223 | { 224 | std::vector yara_rules; 225 | //wprintf(L"Checking Rules Directory: %s\n", yara_rules_dir.c_str()); 226 | 227 | for (const auto& p : std::filesystem::directory_iterator(yara_rules_dir.c_str())) { 228 | if (p.path().extension() == compiled_ext) { 229 | yara_rules.push_back(p.path()); 230 | } 231 | } 232 | if (yara_rules.size() == 0) 233 | { 234 | for (const auto& p : std::filesystem::directory_iterator(yara_rules_dir.c_str())) { 235 | if (p.path().extension() == ext) { 236 | yara_rules.push_back(p.path()); 237 | } 238 | } 239 | } 240 | return yara_rules; 241 | } 242 | -------------------------------------------------------------------------------- /source/RaccineLib/RaccineLib.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {1e00bdf5-f2b2-4a59-8e3a-58edbfe0e420} 25 | RaccineLib 26 | 10.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | StaticLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level4 88 | true 89 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 90 | true 91 | NotUsing 92 | pch.h 93 | stdcpplatest 94 | MultiThreadedDebug 95 | true 96 | 97 | 98 | 99 | 100 | true 101 | 102 | 103 | 104 | 105 | Level4 106 | true 107 | true 108 | true 109 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 110 | true 111 | NotUsing 112 | pch.h 113 | stdcpplatest 114 | MultiThreaded 115 | true 116 | 117 | 118 | 119 | 120 | true 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | Level4 128 | true 129 | _DEBUG;_LIB;%(PreprocessorDefinitions) 130 | true 131 | NotUsing 132 | pch.h 133 | stdcpplatest 134 | MultiThreadedDebug 135 | true 136 | 137 | 138 | 139 | 140 | true 141 | 142 | 143 | 144 | 145 | Level4 146 | true 147 | true 148 | true 149 | NDEBUG;_LIB;%(PreprocessorDefinitions) 150 | true 151 | NotUsing 152 | pch.h 153 | stdcpplatest 154 | MultiThreaded 155 | true 156 | 157 | 158 | 159 | 160 | true 161 | true 162 | true 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /source/Raccine/Raccine.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {e402fceb-a95b-44ff-bc00-b24ce6daf0ab} 25 | Raccine 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | false 35 | 36 | 37 | Application 38 | false 39 | v142 40 | true 41 | Unicode 42 | false 43 | 44 | 45 | Application 46 | true 47 | v142 48 | Unicode 49 | false 50 | 51 | 52 | Application 53 | false 54 | v142 55 | true 56 | Unicode 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level4 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | stdcpplatest 96 | MultiThreadedDebug 97 | true 98 | $(SolutionDir)source;%(AdditionalIncludeDirectories) 99 | 100 | 101 | Console 102 | true 103 | 104 | 105 | 106 | 107 | Level4 108 | true 109 | true 110 | true 111 | true 112 | _UNICODE;UNICODE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 113 | stdcpplatest 114 | MultiThreaded 115 | true 116 | $(SolutionDir)source;%(AdditionalIncludeDirectories) 117 | 118 | 119 | Console 120 | true 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | Level4 128 | true 129 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | true 131 | stdcpplatest 132 | MultiThreadedDebug 133 | true 134 | $(SolutionDir)source;%(AdditionalIncludeDirectories) 135 | 136 | 137 | Console 138 | true 139 | 140 | 141 | 142 | 143 | Level4 144 | true 145 | true 146 | true 147 | true 148 | _UNICODE;UNICODE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS 149 | stdcpplatest 150 | MultiThreaded 151 | true 152 | $(SolutionDir)source;%(AdditionalIncludeDirectories) 153 | 154 | 155 | Console 156 | true 157 | true 158 | true 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | {1e00bdf5-f2b2-4a59-8e3a-58edbfe0e420} 178 | false 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /RaccineGUI/RaccineCfg/RaccineElevatedCfg/RaccineCfg.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Diagnostics; 6 | using System.Diagnostics.Eventing.Reader; 7 | using System.Drawing; 8 | using System.Linq; 9 | using System.IO; 10 | using System.Text; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | using System.Windows.Forms; 14 | using Microsoft.Win32; 15 | using System.Runtime.CompilerServices; 16 | 17 | /// Raccine settings launcher 18 | /// Initial code by @JohnLaTwC 19 | namespace RaccineElevatedCfg 20 | { 21 | 22 | public partial class RaccineCfg : Form 23 | { 24 | public static RaccineCfg thisForm = null; 25 | RaccineRegistrySettings settings = null; 26 | bool fDirty = false; 27 | public RaccineCfg() 28 | { 29 | InitializeComponent(); 30 | RaccineCfg.thisForm = this; 31 | 32 | this.settings = new RaccineRegistrySettings(); 33 | txtRulesDir.Text = settings.RulesDir; 34 | if (settings.LogOnly == 0x1) 35 | { 36 | chkSimulationMode.Checked = true; 37 | } 38 | else 39 | { 40 | chkSimulationMode.Checked = false; 41 | } 42 | if (settings.ScanMemory == 0x1) 43 | { 44 | chkScanMemory.Checked = true; 45 | } 46 | else 47 | { 48 | chkScanMemory.Checked = false; 49 | } 50 | 51 | } 52 | 53 | private void btnRuleBrowse_Click(object sender, EventArgs e) 54 | { 55 | string dir = settings.RulesDir; 56 | folderBrowserDialog1.ShowNewFolderButton = true; 57 | if (dir.Contains('%')) 58 | { 59 | dir = Environment.ExpandEnvironmentVariables(dir); 60 | } 61 | folderBrowserDialog1.SelectedPath = dir; 62 | if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) 63 | { 64 | fDirty = true; 65 | txtRulesDir.Text = folderBrowserDialog1.SelectedPath; 66 | } 67 | } 68 | 69 | private void btnCancel_Click(object sender, EventArgs e) 70 | { 71 | Close(); 72 | } 73 | 74 | private void btnOK_Click(object sender, EventArgs e) 75 | { 76 | if (fDirty) 77 | { 78 | if (chkSimulationMode.Checked) 79 | { 80 | settings.LogOnly = 0x1; 81 | } 82 | else 83 | { 84 | settings.LogOnly = 0; 85 | } 86 | 87 | if (chkScanMemory.Checked) 88 | { 89 | settings.ScanMemory= 0x1; 90 | } 91 | else 92 | { 93 | settings.ScanMemory = 0; 94 | } 95 | string szFolder = txtRulesDir.Text; 96 | settings.RulesDir = szFolder; 97 | } 98 | Close(); 99 | 100 | } 101 | 102 | private void btnViewLog_Click(object sender, EventArgs e) 103 | { 104 | if (File.Exists(settings.LogFilePath)) 105 | { 106 | ProcessStartInfo psi = new ProcessStartInfo(settings.LogFilePath); 107 | psi.UseShellExecute = true; 108 | Process.Start(psi); 109 | } 110 | } 111 | 112 | private void tabControl1_Selected(object sender, TabControlEventArgs e) 113 | { 114 | if (tabControl1.SelectedIndex == 1 && dataGridView1.Rows.Count == 0) 115 | { 116 | Cursor.Current = Cursors.WaitCursor; 117 | 118 | EventLogQuery elQuery = new EventLogQuery("Application", PathType.LogName, "*[System/Provider/@Name=\"Raccine\"]"); 119 | elQuery.ReverseDirection = true; 120 | 121 | using (var elReader = new System.Diagnostics.Eventing.Reader.EventLogReader(elQuery)) 122 | { 123 | 124 | List eventList = new List(); 125 | EventRecord eventInstance = elReader.ReadEvent(); 126 | try 127 | { 128 | while (eventInstance != null) 129 | { 130 | eventInstance = elReader.ReadEvent(); 131 | if (eventInstance != null) 132 | { 133 | if (eventInstance.TimeCreated != null) 134 | { 135 | TimeSpan ts = ((DateTime)eventInstance.TimeCreated - DateTime.Now); 136 | if (ts.TotalDays < 1) 137 | { 138 | eventList.Add(eventInstance); 139 | } 140 | else 141 | { 142 | break; 143 | } 144 | } 145 | } 146 | } 147 | } 148 | finally 149 | { 150 | if (eventInstance != null) 151 | eventInstance.Dispose(); 152 | } 153 | dataGridView1.Columns.Add("TimeCreated", "TimeCreated"); 154 | dataGridView1.Columns.Add("EventData", "EventData"); 155 | foreach (EventRecord evt in eventList) 156 | { 157 | int rowId = dataGridView1.Rows.Add(); 158 | 159 | // Grab the new row! 160 | DataGridViewRow row = dataGridView1.Rows[rowId]; 161 | 162 | // Add the data 163 | row.Cells["TimeCreated"].Value = evt.TimeCreated; 164 | row.Cells["EventData"].Value = evt.FormatDescription(); 165 | } 166 | } 167 | Cursor.Current = Cursors.Default; 168 | } 169 | } 170 | 171 | private void chkSimulationMode_CheckStateChanged(object sender, EventArgs e) 172 | { 173 | fDirty = true; 174 | } 175 | 176 | private void mnuSettings_Click(object sender, EventArgs e) 177 | { 178 | RaccineCfg.thisForm.Show(); 179 | } 180 | 181 | private void mnuExit_Click(object sender, EventArgs e) 182 | { 183 | Close(); 184 | } 185 | 186 | private void btnRulesFolder_Click(object sender, EventArgs e) 187 | { 188 | string folder_name = settings.RulesDir; 189 | folder_name = Environment.ExpandEnvironmentVariables(folder_name); 190 | if (Directory.Exists(folder_name)) 191 | { 192 | if (!folder_name.EndsWith("\\")) 193 | folder_name += "\\"; 194 | ProcessStartInfo psi = new ProcessStartInfo(folder_name); 195 | psi.UseShellExecute = true; 196 | psi.Verb = "open"; 197 | Process.Start(psi); 198 | } 199 | } 200 | 201 | private void chkScanMemory_CheckedChanged(object sender, EventArgs e) 202 | { 203 | fDirty = true; 204 | } 205 | 206 | } 207 | 208 | 209 | public class RaccineRegistrySettings 210 | { 211 | public RaccineRegistrySettings() 212 | { 213 | 214 | } 215 | 216 | public uint LogOnly 217 | { 218 | get 219 | { 220 | uint setting = Convert.ToUInt32(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "LogOnly", 1)); 221 | return setting; 222 | } 223 | set 224 | { 225 | Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "LogOnly", value ,RegistryValueKind.DWord); 226 | } 227 | } 228 | public uint ScanMemory 229 | { 230 | get 231 | { 232 | uint setting = Convert.ToUInt32(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "ScanMemory", 0)); 233 | return setting; 234 | } 235 | set 236 | { 237 | Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "ScanMemory", value, RegistryValueKind.DWord); 238 | } 239 | } 240 | 241 | 242 | public string RulesDir 243 | { 244 | get 245 | { 246 | 247 | // Windows App ProgramFiles PROGRAMFILES(X86) ProgramW6432 248 | // ------ ----- ----------------------------------------------------------------- 249 | // 32 - bit 32 - bit C:\Program Files [empty string] [empty string] 250 | // 64 - bit 32 - bit C:\Program Files(x86) C:\Program Files(x86) C:\Program Files 251 | // 64 - bit 64 - bit C:\Program Files C:\Program Files(x86) C:\Program Files 252 | string dir_name = ""; 253 | if (Environment.Is64BitOperatingSystem) 254 | { 255 | dir_name = "%ProgramW6432%\\Raccine\\yarac64.exe"; 256 | } 257 | else 258 | { 259 | dir_name = "%ProgramFiles%\\Raccine\\yarac32.exe"; 260 | } 261 | dir_name = Environment.ExpandEnvironmentVariables(dir_name); 262 | 263 | string setting = Convert.ToString(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "RulesDir", dir_name)); 264 | return setting; 265 | } 266 | set 267 | { 268 | Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Raccine", "RulesDir", value, RegistryValueKind.String); 269 | } 270 | } 271 | public string LogFilePath 272 | { 273 | get 274 | { 275 | string logpath = Environment.ExpandEnvironmentVariables(@"%ProgramData%\Raccine\Raccine_log.txt"); 276 | return logpath; 277 | } 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /install-raccine.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | SET __COMPAT_LAYER=RunAsInvoker 3 | SETLOCAL EnableDelayedExpansion 4 | CLS 5 | 6 | :: Command Line Param 7 | SET SELECTED_OPTION=%1 8 | 9 | SET ARCHITECTURE_SUFFIX=64 10 | SET ARCHITECTURE_SUFFIX_X=64 11 | IF "%PROCESSOR_ARCHITECTURE%" EQU "AMD64" ( 12 | SET ARCHITECTURE_SUFFIX=64 13 | ) ELSE ( 14 | SET ARCHITECTURE_SUFFIX=32 15 | SET ARCHITECTURE_SUFFIX_X=86 16 | ) 17 | 18 | :: BatchGotAdmin 19 | :: Source: https://stackoverflow.com/a/10052222 20 | :------------------------------------- 21 | :: Check for permissions 22 | IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" ( 23 | >nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system" 24 | ) ELSE ( 25 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" 26 | ) 27 | 28 | :: Not Admin 29 | :: If error flag set, we do not have admin. 30 | IF '%errorlevel%' NEQ '0' ( 31 | :: Make sure that the release package with the compiled binaries has been downloaded and not just the source code 32 | IF NOT EXIST Raccine.exe GOTO PACKAGE_ERROR 33 | IF NOT EXIST Raccine_x86.exe GOTO PACKAGE_ERROR 34 | IF NOT EXIST RaccineRulesSync.exe GOTO PACKAGE_ERROR 35 | IF NOT EXIST RaccineElevatedCfg.exe GOTO PACKAGE_ERROR 36 | IF NOT EXIST RaccineSettings.exe GOTO PACKAGE_ERROR 37 | :: Now escalate privileges 38 | ECHO Requesting administrative privileges... 39 | GOTO UACPrompt 40 | ) ELSE ( GOTO gotAdmin ) 41 | 42 | :: UAC Prompt 43 | :UACPrompt 44 | ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" 45 | SET params= %* 46 | ECHO UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs" 47 | 48 | "%temp%\getadmin.vbs" 49 | DEL "%temp%\getadmin.vbs" 50 | EXIT /B 51 | 52 | :: Actual Script 53 | :gotAdmin 54 | PUSHD "%CD%" 55 | CD /D "%~dp0" 56 | 57 | :: Check Architecture and set postfix 58 | SET ARCH= 59 | IF "%PROCESSOR_ARCHITECTURE%" EQU "x86" ( 60 | ECHO Detected x86 architecture 61 | SET ARCH=_x86 62 | ) 63 | 64 | :MENU 65 | CLS 66 | ECHO. 67 | ECHO .............................................................................. 68 | ::: ___ _ 69 | ::: / _ \___ _________(_)__ ___ 70 | ::: / , _/ _ `/ __/ __/ / _ \/ -_) 71 | ::: /_/|_|\_,_/\__/\__/_/_//_/\__/ 72 | ::: 73 | for /f "delims=: tokens=*" %%A in ('findstr /b ::: "%~f0"') do @echo(%%A 74 | ECHO A Simple Ransomware and Emotet Vaccine 75 | ECHO Installer by Florian Roth, March 2021 76 | ECHO. 77 | ECHO ------------------------------------------------------------------------------ 78 | ECHO WARNING! Raccine could break your backup solution 79 | ECHO .............................................................................. 80 | ECHO. 81 | ECHO 1 - Install Raccine for all possible methods 82 | ECHO 2 - Install Raccine for all possible methods (simulation mode, logging only) 83 | ECHO 3 - Install Raccine interception for less often used executables only (soft) 84 | ECHO. 85 | ECHO 5 - Disable automatic rule updates 86 | ECHo 6 - Run Windows Hardening Script 87 | ECHO U - Uninstall Raccine 88 | ECHO E - EXIT 89 | ECHO. 90 | 91 | :: Option set via ENV variables 92 | IF "%SELECTED_OPTION%"=="FULL" GOTO FULL 93 | IF "%SELECTED_OPTION%"=="SOFT" GOTO SOFT 94 | IF "%SELECTED_OPTION%"=="FULL_SIMU" GOTO FULL_SIMU 95 | IF "%SELECTED_OPTION%"=="UNINSTALL" GOTO UNINSTALL 96 | 97 | :: Options set by user 98 | SET /P M=" Select an option and then press ENTER: " 99 | IF %M%==1 GOTO FULL 100 | IF %M%==2 GOTO FULL_SIMU 101 | IF %M%==3 GOTO SOFT 102 | IF %M%==5 GOTO DISABLEUPDATES 103 | IF %M%==6 GOTO HARDENING 104 | IF %M%==U GOTO UNINSTALL 105 | IF %M%==u GOTO UNINSTALL 106 | IF %M%==E GOTO EOF 107 | IF %M%==e GOTO EOF 108 | GOTO MENU 109 | 110 | :: Installer actions 111 | 112 | :UNINSTALL 113 | CALL :UNINSTALL_TASKS 114 | :: in case of automation, directly got to EOF 115 | IF NOT "%SELECTED_OPTION%"=="" GOTO EOF 116 | TIMEOUT /t 30 117 | GOTO MENU 118 | 119 | :: Actions to run in all modes 120 | :INSTALL 121 | ECHO. 122 | :: Requirements 123 | :: Visual C++ Runtime 124 | IF NOT EXIST C:\Windows\System32\vcruntime140.dll ( 125 | ECHO Installing Visual C++ Redistributable Package ... 126 | start /wait preqeq\vc_redist.x%ARCHITECTURE_SUFFIX_X%.exe /q /norestart 127 | ) 128 | :: .NET Framework 129 | REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs\.NETFramework,Version=v4.5" 2>nul 130 | IF ERRORLEVEL 1 ( 131 | ECHO Installing .NET Framework ... 132 | start /wait preqeq\NDP462-KB3151800-x86-x64-AllOS-ENU.exe /q /norestart 133 | ) 134 | :: Raccine GUI Elements 135 | ECHO Creating data directory "%ProgramFiles%\Raccine" ... 136 | MKDIR "%ProgramFiles%\Raccine" 137 | COPY RaccineElevatedCfg.exe "%ProgramFiles%\Raccine\" 138 | COPY RaccineSettings.exe "%ProgramFiles%\Raccine\" 139 | COPY RaccineRulesSync.exe "%ProgramFiles%\Raccine\" 140 | :: Raccine Program Files 141 | COPY Raccine%ARCH%.exe "%ProgramFiles%\Raccine\Raccine.exe" 142 | COPY yara\yara%ARCHITECTURE_SUFFIX%.exe "%ProgramFiles%\Raccine\" 143 | COPY yara\yarac%ARCHITECTURE_SUFFIX%.exe "%ProgramFiles%\Raccine\" 144 | :: YARA Rules 145 | MKDIR "%ProgramFiles%\Raccine\yara" 146 | MKDIR "%ProgramFiles%\Raccine\yara\in-memory" 147 | ECHO Copying YARA rules to the directory ... 148 | COPY yara\*.yar "%ProgramFiles%\Raccine\yara" 149 | COPY yara\in-memory\*.yar "%ProgramFiles%\Raccine\yara\in-memory" 150 | :: Setting the Path 151 | SETX /M Path "%PATH%;%ProgramFiles%\Raccine" 152 | :: Raccine Data 153 | ECHO Creating data directory "%ProgramData%\Raccine" ... 154 | MKDIR "%ProgramData%\Raccine" 155 | ECHO Creating empty log file ... 156 | echo. 2>"%ProgramData%\Raccine\Raccine_log.txt" 157 | icacls "%ProgramData%\Raccine\Raccine_log.txt" /grant Users:F 158 | ECHO Registering Eventlog Events 159 | eventcreate.exe /L Application /T Information /id 1 /so Raccine /d "Raccine Setup: Registration of Event ID 1 - Used for Informational Messages" 2> nul 160 | eventcreate.exe /L Application /T Information /id 2 /so Raccine /d "Raccine Setup: Registration of Event ID 2 - Used for Malicious Actitivty" 2> nul 161 | eventcreate.exe /L Application /T Information /id 3 /so Raccine /d "Raccine Setup: Registration of Event ID 3 - Used for Benign Activity" 2> nul 162 | :: Registry Settings 163 | REG.EXE ADD HKLM\Software\Raccine /v ShowGui /t REG_DWORD /d 1 /F 164 | REG.EXE ADD HKLM\Software\Raccine /v ScanMemory /t REG_DWORD /d 1 /F 165 | REG.EXE ADD HKLM\Software\Raccine /v RulesDir /t REG_SZ /d "%ProgramFiles%\Raccine\yara" /F 166 | :: Registering and starting the GUI elements 167 | REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "Raccine Tray" /t REG_SZ /F /D "%ProgramFiles%\Raccine\RaccineSettings.exe" 168 | START "" "%ProgramFiles%\Raccine\RaccineSettings.exe" 169 | :: Scheduled Task 170 | ECHO Adding scheduled task for rule updates 171 | SCHTASKS /create /tn "Raccine Rules Updater" /tr "\"%PROGRAMFILES%\Raccine\RaccineRulesSync.exe\"" /sc DAILY /mo 1 /f /RL highest /RU "NT AUTHORITY\SYSTEM" /NP 172 | SCHTASKS /RUN /TN "Raccine Rules Updater" 173 | :: in case of automation, directly got to EOF 174 | IF NOT "%SELECTED_OPTION%"=="" GOTO EOF 175 | TIMEOUT /t 30 176 | GOTO MENU 177 | 178 | :: Full 179 | :FULL 180 | CALL :UNINSTALL_TASKS 181 | ECHO. 182 | :: Registry Patches 183 | ECHO Installing Registry patches ... 184 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-vssadmin.reg 185 | IF '%errorlevel%' NEQ '0' ( 186 | ECHO Something went wrong. Sorry. Installation failed. 187 | GOTO MENU 188 | ) 189 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-wmic.reg 190 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-wbadmin.reg 191 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-bcdedit.reg 192 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-powershell.reg 193 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-diskshadow.reg 194 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-net.reg 195 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-taskkill.reg 196 | :: Not Simulation only 197 | REG.EXE ADD HKLM\Software\Raccine /v LogOnly /t REG_DWORD /d 0 /F 198 | GOTO INSTALL 199 | 200 | :: Simulation Mode 201 | :FULL_SIMU 202 | CALL :UNINSTALL_TASKS 203 | ECHO. 204 | :: Registry Patches 205 | ECHO Installing Registry patches ... 206 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-vssadmin.reg 207 | IF '%errorlevel%' NEQ '0' ( 208 | ECHO Something went wrong. Sorry. Installation failed. 209 | GOTO MENU 210 | ) 211 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-wmic.reg 212 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-wbadmin.reg 213 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-bcdedit.reg 214 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-powershell.reg 215 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-diskshadow.reg 216 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-net.reg 217 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-taskkill.reg 218 | :: Simulation only 219 | REG.EXE ADD HKLM\Software\Raccine /v LogOnly /t REG_DWORD /d 1 /F 220 | GOTO INSTALL 221 | 222 | :: Soft 223 | :SOFT 224 | CALL :UNINSTALL_TASKS 225 | ECHO. 226 | :: Registry Patches 227 | ECHO Installing Registry patches ... 228 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-vssadmin.reg 229 | IF '%errorlevel%' NEQ '0' ( 230 | ECHO Something went wrong. Sorry. Installation failed. 231 | GOTO MENU 232 | ) 233 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-wbadmin.reg 234 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-bcdedit.reg 235 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-diskshadow.reg 236 | :: Simulation only 237 | REG.EXE ADD HKLM\Software\Raccine /v LogOnly /t REG_DWORD /d 0 /F 238 | GOTO INSTALL 239 | 240 | :: Disable Updates 241 | :DISABLEUPDATES 242 | ECHO. 243 | ECHO Disabling automatic updates ... 244 | ECHO. 245 | SCHTASKS /DELETE /TN "Raccine Rules Updater" /F 246 | IF '%errorlevel%' NEQ '0' ( 247 | ECHO Something went wrong. Sorry. 248 | GOTO MENU 249 | ) 250 | TIMEOUT /t 30 251 | GOTO MENU 252 | 253 | :: Run Hardening Script 254 | :HARDENING 255 | ECHO. 256 | ECHO Running the Hardening script ... 257 | ECHO. 258 | CALL scripts\windows-hardening.bat 259 | IF '%errorlevel%' NEQ '0' ( 260 | ECHO Something went wrong. Sorry. 261 | GOTO MENU 262 | ) 263 | TIMEOUT /t 30 264 | GOTO MENU 265 | 266 | :: Uninstall 267 | :UNINSTALL_TASKS 268 | ECHO. 269 | ECHO Uninstalling Registry patches ... 270 | REGEDIT.EXE /S reg-patches\raccine-reg-patch-uninstall.reg 271 | ECHO Killing the Raccine related processes 272 | TASKKILL /F /IM Raccine.exe 273 | TASKKILL /F /IM RaccineSettings.exe 274 | TASKKILL /F /IM RaccineRulesSync.exe 275 | ECHO Removing Raccine folders ... 276 | @RD /S /Q "%ProgramData%\Raccine" 277 | @RD /S /Q "%ProgramFiles%\Raccine" 278 | ECHO LEGACY: Removing Raccine.exe from the Windows folder (succeeds only if previously installed) ... 279 | DEL /Q C:\Windows\Raccine.exe 280 | IF '%errorlevel%' NEQ '0' ( 281 | ECHO Something went wrong. Sorry. 282 | ) ELSE ( 283 | ECHO. 284 | ECHO Successfully uninstalled! 285 | ) 286 | TASKKILL /F /IM RaccineSettings.exe 287 | TASKKILL /F /IM RaccineRulesSync.exe 288 | REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /V "Raccine Tray" /F 289 | :: Uninstall update task 290 | SCHTASKS /DELETE /TN "Raccine Rules Updater" /F 291 | EXIT /B %ERRORLEVEL% 292 | 293 | :PACKAGE_ERROR 294 | ECHO WARNING: you may have downloaded the source code only or an Antivirus has deleted an important part of the package 295 | ECHO Make sure to download a package that contains the compiled binaries by downloading a package from the RELEASE section. 296 | ECHO. 297 | ECHO https://github.com/Neo23x0/Raccine/releases 298 | ECHO. 299 | ECHO The installer will exit now .. 300 | TIMEOUT /t 30 301 | EXIT /B 1 302 | 303 | :EOF 304 | EXIT /B %ERRORLEVEL% 305 | --------------------------------------------------------------------------------