├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── images ├── icon.ico ├── icon64.png └── taskbar.ico ├── installer ├── bootstrapper.wxs ├── create_installer.bat ├── installer.wxs ├── setVersion.py └── srepp.inf ├── quietdragon.sln ├── signing.txt ├── src ├── common │ ├── drivercomm.h │ ├── log.h │ └── srkcomm.h ├── control │ ├── control.vcxproj │ ├── main.cpp │ ├── pch.h │ ├── pchsrc.cpp │ └── readme.txt ├── driver │ ├── Resource.aps │ ├── Resource.rc │ ├── driver.c │ ├── driver.h │ ├── driver.vcxproj │ ├── pch.h │ ├── pchsrc.c │ ├── processNotification.c │ └── resource.h ├── srkcomm │ ├── dllmain.cpp │ ├── manageService.cpp │ ├── manageService.h │ ├── resource.h │ ├── srkcomm.aps │ ├── srkcomm.cpp │ ├── srkcomm.rc │ ├── srkcomm.vcxproj │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── srsvc │ ├── Arbiter.cs │ ├── Beacon.cs │ ├── Commands │ │ ├── GetCatalogByHash.cs │ │ ├── GetFileByHash.cs │ │ ├── NOP.cs │ │ ├── SetSystemUUID.cs │ │ ├── Stall.cs │ │ └── Update.cs │ ├── CommunicateWithUI.cs │ ├── Database.cs │ ├── Events │ │ ├── Catalogfile.cs │ │ ├── Events.cs │ │ ├── Heartbeat.cs │ │ ├── ProcessEvent.cs │ │ └── Register.cs │ ├── Helpers.cs │ ├── Log.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SystemConfig.cs │ ├── WinTrustVerify.cs │ ├── WindowsService.cs │ ├── app.config │ ├── srsvc.cs │ └── srsvc.csproj └── srui │ ├── Log.cs │ ├── Program.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx │ ├── TrayIcon.cs │ ├── TrayIcon.resx │ ├── app.config │ ├── srui.csproj │ └── ui_comm.cs └── srepp_cs.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.tlog 3 | *.opensdf 4 | *.sdf 5 | *.suo 6 | *.Filters 7 | *.user 8 | ipch 9 | bins/ 10 | build/ 11 | docs/* 12 | *.msi 13 | *.wixobj 14 | *.wixpdb 15 | /src/srsvc/obj 16 | /src/srui/obj 17 | /utils/sigcheck/sigcheck/bin/Debug 18 | /utils/sigcheck/sigcheck/obj/Debug 19 | /utils/sigcheck/sigcheck/bin/x86/Debug 20 | /utils/sigcheck/sigcheck/obj/x86/Debug 21 | /installer/*.exe 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For Summit Route End Point Protection 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name Summit Route nor the names of its contributors may be used to 16 | endorse or promote products derived from this software without specific 17 | prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Project Abandoned 2 | ================= 3 | This is a code dump of what I had hoped to turn into a business, but walked away from. No support or maintenance will be provided. 4 | 5 | Summit Route End Point Protection (SREPP) - Client code 6 | =============================================== 7 | 8 | See the [Server code](https://github.com/SummitRoute/srepp_server) for a description of the project. 9 | 10 | "quietdragon" is the working name I was using for some of the code for a while as this was an ETDR (end-point threat detect and response) solution, and "quiETDRagon" contains those letters. So you'll see references to "qd" throughout the project. 11 | 12 | 13 | How the driver works: 14 | - Registers process notification callback: MyCreateProcessNotifyRoutine 15 | - Userland controller calls ProcessIoctl_GetNewProcesses, which responds with pending, and stores the IRP 16 | - Whenever a process is created, MyCreateProcessNotifyRoutine stores some info about it in a _CONTROL_PROC_INTERNAL struct in an array and tells the controller about it via the IRP, then it waits on an event that will be signalled. 17 | - The controller decides if the process should be allowed or denied by calling ProcessIoctl_ControllerProcessDecision which then sets more info in that _CONTROL_PROC_INTERNAL struct and signals the event to tell MyCreateProcessNotifyRoutine that a decision has been made 18 | - MyCreateProcessNotifyRoutine then looks up and acts on the decision 19 | 20 | 21 | 22 | General fixes needed: 23 | - Need to better deal with string sizes, currently most strings are set to 256 wchars, if over, they truncate. 24 | - Better stop service and driver + uninstall + update 25 | - Test many processes starting at once. Test races. Test multiple CPU. -------------------------------------------------------------------------------- /images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/images/icon.ico -------------------------------------------------------------------------------- /images/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/images/icon64.png -------------------------------------------------------------------------------- /images/taskbar.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/images/taskbar.ico -------------------------------------------------------------------------------- /installer/bootstrapper.wxs: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /installer/create_installer.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | SET WIXDIR="C:\Program Files (x86)\WiX Toolset v3.8\bin" 3 | SET OPTIONS=-nologo -wx -ext WixUtilExtension -ext WiXNetFxExtension -ext %WIXDIR%\WixDifxAppExtension.dll 4 | 5 | REM Remove last installer created 6 | del srepp_installer.exe > NUL 2>&1 7 | 8 | REM --------------------------------------------------------------------------- 9 | REM Collect Files 10 | REM --------------------------------------------------------------------------- 11 | rmdir bins /S /Q > NUL 2>&1 12 | mkdir bins > NUL 2>&1 13 | 14 | copy srepp.inf bins\. > NUL 15 | if %errorlevel% neq 0 ( 16 | echo !!! ERROR Copying srepp.inf failed 17 | exit /b %errorlevel% 18 | ) 19 | 20 | copy "..\bins\Win7 Debug\Win32\srepp.sys" bins\. > NUL 21 | if %errorlevel% neq 0 ( 22 | echo !!! ERROR Copying srepp.sys failed 23 | exit /b %errorlevel% 24 | ) 25 | 26 | copy "..\bins\Win7 Debug\Win32\srkcomm.dll" bins\. > NUL 27 | if %errorlevel% neq 0 ( 28 | echo !!! ERROR Copying srkcomm.dll failed 29 | exit /b %errorlevel% 30 | ) 31 | 32 | copy ..\bins\Debug\srsvc.exe bins\. > NUL 33 | if %errorlevel% neq 0 ( 34 | echo !!! ERROR Copying srsvc.exe failed 35 | exit /b %errorlevel% 36 | ) 37 | 38 | copy ..\bins\Debug\srui.exe bins\. > NUL 39 | if %errorlevel% neq 0 ( 40 | echo !!! ERROR Copying srui.exe failed 41 | exit /b %errorlevel% 42 | ) 43 | 44 | echo *** Collected compiled files 45 | 46 | REM --------------------------------------------------------------------------- 47 | REM Get rid of any old gunk 48 | REM --------------------------------------------------------------------------- 49 | del *.msi installer.wix* *.wixpdb > NUL 2>&1 50 | 51 | 52 | REM --------------------------------------------------------------------------- 53 | REM "Sign" driver with fake cert 54 | REM --------------------------------------------------------------------------- 55 | REM Must run the following on test boxes 56 | REM CertMgr /add SR_test.cer /s root 57 | REM CertMgr /add SR_test.cer /s trustedpublisher 58 | REM Also need to set the _DFX_INSTALL_UNSIGNED_DRIVER environment variable to 1. 59 | 60 | REM SR_test.cer was created with: MakeCert -r -pe -ss SRTestCert -n "CN=SR_Test" SR_test.cer 61 | 62 | Signtool sign /q /ac SR_test.cer /s SRTestCert bins\srepp.sys >NUL 63 | if %errorlevel% neq 0 ( 64 | echo !!! ERROR Signing the driver failed 65 | exit /b %errorlevel% 66 | ) 67 | 68 | echo *** Signed driver with fake cert 69 | 70 | REM --------------------------------------------------------------------------- 71 | REM Create .cat 72 | REM --------------------------------------------------------------------------- 73 | inf2cat /driver:.\bins /os:Vista_X86,Vista_X64,Server2008_X86,Server2008_X64,7_X86,7_X64,Server2008R2_X64,Server8_X64,8_X86,8_X64,Server6_3_X64,6_3_X64,6_3_X86 >NUL 74 | if %errorlevel% neq 0 ( 75 | echo !!! ERROR Creating the catalog failed 76 | exit /b %errorlevel% 77 | ) 78 | 79 | Signtool sign /q /ac SR_test.cer /s SRTestCert bins\srepp.cat >NUL 80 | if %errorlevel% neq 0 ( 81 | echo !!! ERROR Signing the catalog failed 82 | exit /b %errorlevel% 83 | ) 84 | 85 | echo *** Created catalog file 86 | 87 | REM --------------------------------------------------------------------------- 88 | REM Collect Third-Party libraries 89 | REM --------------------------------------------------------------------------- 90 | copy ..\lib\win32\FluentNHibernate.1.4.0.0\lib\net35\FluentNHibernate.dll bins\. > NUL 91 | if %errorlevel% neq 0 ( 92 | echo "!!! ERROR Unable to copy FluentNHibernate.dll" 93 | exit /b %errorlevel% 94 | ) 95 | 96 | copy ..\lib\win32\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll bins\. > NUL 97 | if %errorlevel% neq 0 ( 98 | echo !!! ERROR Unable to copy Iesi.Collections.dll 99 | exit /b %errorlevel% 100 | ) 101 | 102 | copy ..\lib\win32\NHibernate.3.3.1.4000\lib\Net35\NHibernate.dll bins\. > NUL 103 | if %errorlevel% neq 0 ( 104 | echo !!! ERROR Unable to copy NHibernate.dll 105 | exit /b %errorlevel% 106 | ) 107 | 108 | copy ..\lib\win32\sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.94.0\System.Data.SQLite.dll bins\. > NUL 109 | if %errorlevel% neq 0 ( 110 | echo !!! ERROR Unable to copy System.Data.SQLite.dll 111 | exit /b %errorlevel% 112 | ) 113 | 114 | copy ..\lib\win32\System.Web.Helpers\System.Web.Helpers.dll bins\. > NUL 115 | if %errorlevel% neq 0 ( 116 | echo !!! ERROR Unable to copy System.Web.Helpers.dll 117 | exit /b %errorlevel% 118 | ) 119 | 120 | copy ..\lib\msvcr120d.dll bins\. > NUL 121 | if %errorlevel% neq 0 ( 122 | echo !!! ERROR Unable to copy msvcr120d.dll 123 | exit /b %errorlevel% 124 | ) 125 | 126 | echo *** Collected third-party libraries 127 | 128 | REM --------------------------------------------------------------------------- 129 | REM Create msi 130 | REM --------------------------------------------------------------------------- 131 | %WIXDIR%\candle.exe %OPTIONS% installer.wxs -arch x86 132 | if %errorlevel% neq 0 ( 133 | echo !!! ERROR candle failed on installer.wxs 134 | exit /b %errorlevel% 135 | ) 136 | 137 | %WIXDIR%\light.exe %OPTIONS% installer.wixobj %WIXDIR%\difxapp_x86.wixlib -o SummitRoute_x86.msi 138 | if %errorlevel% neq 0 ( 139 | echo !!! ERROR light failed on installer.wixobj 140 | exit /b %errorlevel% 141 | ) 142 | 143 | echo *** Created SummitRoute_x86.msi 144 | 145 | REM --------------------------------------------------------------------------- 146 | REM Sign MSI 147 | REM --------------------------------------------------------------------------- 148 | 149 | rem %WIXDIR%\insignia -im SummitRoute_x86.msi -nologo 150 | rem if %errorlevel% neq 0 ( 151 | rem echo !!! ERROR insignia failed on SummitRoute_x86.msi 152 | rem exit /b %errorlevel% 153 | rem ) 154 | 155 | osslsigncode\osslsigncode.exe sign -pkcs12 osslsigncode/test.pfx -pass password -in SummitRoute_x86.msi -out SummitRoute_x86_signed.msi >NUL 156 | if %errorlevel% neq 0 ( 157 | echo !!! ERROR osslsigncode failed on SummitRoute_x86.msi 158 | exit /b %errorlevel% 159 | ) 160 | 161 | del SummitRoute_x86.msi > NUL 2>&1 162 | move SummitRoute_x86_signed.msi SummitRoute_x86.msi >NUL 163 | 164 | echo *** Signed SummitRoute_x86.msi 165 | 166 | REM --------------------------------------------------------------------------- 167 | REM Create boostrapper exe 168 | REM --------------------------------------------------------------------------- 169 | 170 | %WIXDIR%\candle.exe %OPTIONS% bootstrapper.wxs -arch x86 -ext WixBalExtension >NUL 171 | if %errorlevel% neq 0 ( 172 | echo !!! ERROR candle failed on bootstrapper.wxs 173 | exit /b %errorlevel% 174 | ) 175 | 176 | %WIXDIR%\light.exe %OPTIONS% bootstrapper.wixobj -ext WixBalExtension -o srepp_installer.exe 177 | if %errorlevel% neq 0 ( 178 | echo !!! ERROR light failed on bootstrapper.wixobj 179 | exit /b %errorlevel% 180 | ) 181 | 182 | echo *** Created srepp_installer.exe 183 | 184 | REM --------------------------------------------------------------------------- 185 | REM Sign it 186 | REM --------------------------------------------------------------------------- 187 | 188 | %WIXDIR%\insignia -ib srepp_installer.exe -o engine.exe -nologo 189 | if %errorlevel% neq 0 ( 190 | echo !!! ERROR insignia failed on srepp_installer.exe 191 | exit /b %errorlevel% 192 | ) 193 | 194 | 195 | osslsigncode\osslsigncode.exe sign -pkcs12 osslsigncode/test.pfx -pass password -addBlob -in engine.exe -out engine_signed.exe >NUL 196 | if %errorlevel% neq 0 ( 197 | echo !!! ERROR osslsigncode failed on engine.exe 198 | exit /b %errorlevel% 199 | ) 200 | 201 | echo *** Signed engine.exe 202 | 203 | %WIXDIR%\insignia -ab engine_signed.exe srepp_installer.exe -o srepp_installer.exe -nologo 204 | if %errorlevel% neq 0 ( 205 | echo !!! ERROR insignia failed on signed srepp_installer.exe 206 | exit /b %errorlevel% 207 | ) 208 | 209 | osslsigncode\osslsigncode.exe sign -pkcs12 osslsigncode/test.pfx -pass password -addBlob -in srepp_installer.exe -out srepp_installer_signed.exe >NUL 210 | if %errorlevel% neq 0 ( 211 | echo !!! ERROR osslsigncode add blob failed on srepp_installer.exe 212 | exit /b %errorlevel% 213 | ) 214 | 215 | echo *** Added config blob area in srepp_installer.exe 216 | 217 | del engine.exe > NUL 2>&1 218 | del engine_signed.exe > NUL 2>&1 219 | del srepp_installer.wixpdb > NUL 2>&1 220 | del SummitRoute_x86.wixpdb > NUL 2>&1 221 | del SummitRoute_x86.msi > NUL 2>&1 222 | del bootstrapper.wixobj > NUL 2>&1 223 | 224 | del srepp_installer.exe > NUL 2>&1 225 | move srepp_installer_signed.exe srepp_installer.exe >NUL 226 | 227 | del installer.wix* > NUL 2>&1 228 | echo *** SUCCESS: Installer created *** 229 | -------------------------------------------------------------------------------- /installer/installer.wxs: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | = 600)]]> 24 | 25 | 26 | 27 | Privileged 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 85 | 87 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 108 | 109 | 110 | 111 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /installer/setVersion.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | ############################################################################### 3 | # 4 | # Summit Route End Point Protection 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | # 9 | ############################################################################### 10 | 11 | 12 | from tempfile import mkstemp 13 | from shutil import move 14 | from os import remove, close 15 | import re 16 | import sys 17 | 18 | 19 | 20 | def replace(file, pattern, subst): 21 | print (file) 22 | #Create temp file 23 | fh, abs_path = mkstemp() 24 | new_file = open(abs_path,'w') 25 | old_file = open(file) 26 | for line in old_file: 27 | new_file.write(re.sub(pattern, subst, line)) 28 | #close temp file 29 | new_file.close() 30 | close(fh) 31 | old_file.close() 32 | #Remove original file 33 | remove(file) 34 | #Move new file 35 | move(abs_path, file) 36 | 37 | # Main program 38 | if (len(sys.argv) == 1): 39 | sys.exit("Specify the version. Example: %s 1.0.0.0\n" % sys.argv[0]) 40 | 41 | version = sys.argv[1] 42 | versionnumber = re.sub("\.", ",", version) 43 | print ("Setting the following files to use version %s\n" % version) 44 | 45 | replace("../ohipsfs/firststage.rc", "#define VERSION_NUMBER [\d\,]*", "#define VERSION_NUMBER %s" % versionnumber); 46 | replace("../ohipsfs/firststage.rc", "#define VERSION_STRING \"[\d\.]*\"", "#define VERSION_STRING \"%s\"" % version); 47 | 48 | 49 | replace("../ohipsp/protector.rc", "#define VERSION_NUMBER [\d\,]*", "#define VERSION_NUMBER %s" % versionnumber); 50 | replace("../ohipsp/protector.rc", "#define VERSION_STRING \"[\d\.]*\"", "#define VERSION_STRING \"%s\"" % version); 51 | 52 | 53 | replace("../installer/installer.wxs", " Version=\"[\d\.]*\"", " Version=\"%s\"" % version); 54 | replace("../ohipssvc/Properties/AssemblyInfo.cs", "\[assembly: AssemblyVersion(\"[\d\.]*\")\]", "\[assembly: AssemblyVersion(\"%s\")\]" % version); 55 | replace("../ohipssvc/Properties/AssemblyInfo.cs", "\[assembly: AssemblyFileVersion(\"[\d\.]*\")\]", "\[assembly: AssemblyFileVersion(\"%s\")\]" % version); 56 | 57 | replace("../ohipsui/Properties/AssemblyInfo.cs", "\[assembly: AssemblyVersion(\"[\d\.]*\")\]", "\[assembly: AssemblyVersion(\"%s\")\]" % version); 58 | replace("../ohipsui/Properties/AssemblyInfo.cs", "\[assembly: AssemblyFileVersion(\"[\d\.]*\")\]", "\[assembly: AssemblyFileVersion(\"%s\")\]" % version); 59 | replace("../ohipsui/TrayIcon.cs", "private string szVersion = \"[\d\.]*\";", "private string szVersion = \"%s\";" % version); 60 | -------------------------------------------------------------------------------- /installer/srepp.inf: -------------------------------------------------------------------------------- 1 | [Version] 2 | Signature = "$Windows NT$" 3 | Class = System 4 | ClassGuid = {b053b988-c433-4f97-a066-606bdd4b0cce} ; Random guid. 5 | ; Normally you specify a known class guid, but this doesn't fit in any normal class. 6 | 7 | Provider = %SummitRoute% 8 | DriverVer = 09/16/2014,1.0.0.0 ; TODO CHANGME 9 | CatalogFile = srepp.cat 10 | DriverPackageType=KernelService 11 | 12 | [DestinationDirs] 13 | DefaultDestDir = %DIRID_DRIVERS% 14 | 15 | [DefaultInstall] 16 | OptionDesc = %ServiceDescription% 17 | CopyFiles = srepp.DriverFiles 18 | 19 | [DefaultInstall.Services] 20 | AddService = %ServiceName%,,srepp.Service 21 | 22 | [DefaultUninstall] 23 | DelFiles = srepp.DriverFiles 24 | 25 | [DefaultUninstall.Services] 26 | DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting 27 | 28 | ; ############################################################################# 29 | ; # Service description 30 | [srepp.Service] 31 | DisplayName = %ServiceName% 32 | Description = %ServiceDescription% 33 | ServiceBinary = %12%\%DriverName%.sys 34 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 35 | StartType = 3 ; SERVICE_DEMAND_START 36 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 37 | 38 | ; ############################################################################# 39 | ; # Files 40 | [srepp.DriverFiles] 41 | %DriverName%.sys 42 | [SourceDisksFiles] 43 | srepp.sys = 1 44 | [SourceDisksNames] 45 | 1 = %DiskId1% 46 | 47 | ; ############################################################################# 48 | ; # Strings 49 | 50 | [Strings] 51 | SummitRoute = Summit Route 52 | DIRID_DRIVERS = 12 53 | ServiceDescription = "Monitors for new processes" 54 | ServiceName = "Summit Route EPP driver" 55 | DriverName = "srepp" 56 | DiskId1 = "Summit Route EPP installation media" 57 | -------------------------------------------------------------------------------- /quietdragon.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 12.0 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "src\driver\driver.vcxproj", "{933979A5-8C77-4E92-9070-A474158D9024}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "control", "src\control\control.vcxproj", "{204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {72D8D796-1865-4C8C-8D4A-8700171D6745} = {72D8D796-1865-4C8C-8D4A-8700171D6745} 11 | EndProjectSection 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "srkcomm", "src\srkcomm\srkcomm.vcxproj", "{72D8D796-1865-4C8C-8D4A-8700171D6745}" 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Win7 Debug|Win32 = Win7 Debug|Win32 18 | Win7 Debug|x64 = Win7 Debug|x64 19 | Win7 Release|Win32 = Win7 Release|Win32 20 | Win7 Release|x64 = Win7 Release|x64 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 24 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 25 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 26 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 27 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 28 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 29 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 30 | {933979A5-8C77-4E92-9070-A474158D9024}.Win7 Release|x64.Build.0 = Win7 Release|x64 31 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 32 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 33 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 34 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 35 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 36 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 37 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 38 | {204C73F2-2D1C-4DA7-968C-FC8D1615E0BB}.Win7 Release|x64.Build.0 = Win7 Release|x64 39 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 40 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 41 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Debug|x64.ActiveCfg = Win7 Release|x64 42 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Debug|x64.Build.0 = Win7 Release|x64 43 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 44 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 45 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 46 | {72D8D796-1865-4C8C-8D4A-8700171D6745}.Win7 Release|x64.Build.0 = Win7 Release|x64 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /signing.txt: -------------------------------------------------------------------------------- 1 | # Sign with: 2 | signtool.exe sign /ac DigiCert.crt * 3 | 4 | # Timestamp: 5 | signtool.exe timestamp /t http://timestamp.digicert.com * 6 | 7 | # Add unauthenticated blob 8 | ../../osslsigncode-1.7.1/osslsigncode sign -pkcs12 test.pfx -pass password -n "SREPP" -i https://SummitRoute.com/ -t http://timestamp.verisign.com/scripts/timstamp.dll -in srepp.msi -out srepp_added.msi 9 | 10 | 11 | # Dual signing: 12 | - http://msdn.microsoft.com/en-us/library/windows/hardware/hh967734(v=vs.85).aspx 13 | Signtool sign /fd sha256 /ph /as /sha1 14 | 15 | 16 | 17 | Proper ordering (http://www.osronline.com/showthread.cfm?link=224009): 18 | - stamp 19 | - sign 20 | - generate cat 21 | - sign cat 22 | - verify both files (cat and sys) 23 | 24 | 25 | Slugger (main laptop), and Fortress (signer, no Internet) 26 | 27 | 1. Slugger: Compile 28 | 2. Slugger: Timestamp 29 | -> 30 | 3. Fortress: Sign 31 | <- 32 | 4. Slugger: Generate .cat 33 | 5. Slugger: Timestamp cat 34 | -> 35 | 5. Fortress: Sign .cat 36 | <- 37 | 6. Slugger: Generate .msi 38 | 7. Slugger: Timestamp .msi 39 | -> 40 | 8. Fortress: Sign .msi 41 | <- 42 | 9. Slugger: Deploy 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | ---- 73 | Other notes 74 | # Extract sig 75 | python disitool.py extract accesschk.exe accesschk.pkcs7 76 | 77 | # Convert to text 78 | openssl pkcs7 -in accesschk.pkcs7 -print_certs -text -inform der > accesschk.pkcs7.txt 79 | 80 | # Save each cert manually into files 81 | 82 | # Recreate from certificates 83 | openssl crl2pkcs7 -nocrl -certfile c1.pem -certfile c2.pem -certfile c3.pem -certfile c4.pem -out generated.pkcs7 84 | 85 | # Convert to text 86 | openssl pkcs7 -in generated.pkcs7 -print_certs -text -inform der > generated.pkcs7.txt 87 | 88 | # Ensure it matches what we extracted before 89 | sha1sum *.txt 90 | # 2d39ce2a68c6584413723352f5ccdec93caa296c accesschk.pkcs7.txt 91 | # 2d39ce2a68c6584413723352f5ccdec93caa296c generated.pkcs7.txt 92 | 93 | 94 | 95 | # Verify 96 | signtool.exe verify /pa newsig.exe 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Registries of object identifiers 105 | - http://www.alvestrand.no/objectid/1.2.840.113549.2.5.html 106 | - http://www.oid-info.com/cgi-bin/display?oid=1.3.14.3.2.26&action=display 107 | 108 | 109 | 110 | Gutman's authenticode reversing: 111 | - https://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt 112 | 113 | 114 | C code for signing a file: 115 | - http://blogs.msdn.com/b/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx 116 | 117 | When calling SignerSignEx, need to have SIGNER_SIGNATURE_INFO set to a blob of psUnauthenticated. 118 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa387734(v=vs.85).aspx 119 | HRESULT WINAPI SignerSignEx( 120 | _In_ DWORD dwFlags, 121 | _In_ SIGNER_SUBJECT_INFO *pSubjectInfo, 122 | _In_ SIGNER_CERT *pSignerCert, 123 | _In_ SIGNER_SIGNATURE_INFO *pSignatureInfo, 124 | _In_opt_ SIGNER_PROVIDER_INFO *pProviderInfo, 125 | _In_opt_ LPCWSTR pwszHttpTimeStamp, 126 | _In_opt_ PCRYPT_ATTRIBUTES psRequest, 127 | _In_opt_ LPVOID pSipData, 128 | _Out_ SIGNER_CONTEXT **ppSignerContext 129 | ); 130 | 131 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa387753(v=vs.85).aspx 132 | typedef struct _SIGNER_SIGNATURE_INFO { 133 | DWORD cbSize; 134 | ALG_ID algidHash; 135 | DWORD dwAttrChoice; 136 | union { 137 | SIGNER_ATTR_AUTHCODE *pAttrAuthcode; 138 | }; 139 | PCRYPT_ATTRIBUTES psAuthenticated; 140 | PCRYPT_ATTRIBUTES psUnauthenticated; 141 | } SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO; 142 | 143 | 144 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa381146(v=vs.85).aspx 145 | typedef struct _CRYPT_ATTRIBUTES { 146 | DWORD cAttr; 147 | PCRYPT_ATTRIBUTE rgAttr; 148 | } CRYPT_ATTRIBUTES, *PCRYPT_ATTRIBUTES, CMSG_ATTR; 149 | 150 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa381139(v=vs.85).aspx 151 | typedef struct _CRYPT_ATTRIBUTE { 152 | LPSTR pszObjId; 153 | DWORD cValue; 154 | PCRYPT_ATTR_BLOB rgValue; 155 | } CRYPT_ATTRIBUTE, *PCRYPT_ATTRIBUTE; 156 | 157 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380238(v=vs.85).aspx 158 | typedef struct _CRYPTOAPI_BLOB { 159 | DWORD cbData; 160 | BYTE *pbData; 161 | } CRYPT_INTEGER_BLOB, 162 | 163 | ############### 164 | Using new SignerSignEx2 165 | http://msdn.microsoft.com/en-us/library/windows/desktop/jj835834(v=vs.85).aspx 166 | 167 | 168 | 169 | 170 | Could use osslsigncode 171 | - https://github.com/mkrautz/osslsigncode or http://sourceforge.net/projects/osslsigncode/ 172 | - Using it: http://development.adaptris.net/users/lchan/blog/2013/06/07/signing-windows-installers-on-linux/ 173 | 174 | 175 | Dual signing: 176 | - http://msdn.microsoft.com/en-us/library/windows/hardware/hh967734(v=vs.85).aspx 177 | Signtool sign /fd sha256 /ph /as /sha1 178 | 179 | 180 | 181 | Dropbox uses the type 1.3.6.1.4.1.42921.1.2.1 182 | OBJ_Enterprises is 1.3.6.1.4.1 183 | 184 | 185 | Timestamp separate: 186 | http://stackoverflow.com/questions/2872105/alternative-timestamping-services-for-authenticode 187 | -------------------------------------------------------------------------------- /src/common/drivercomm.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | #pragma warning(disable:4214) // bit field types other than int 13 | #pragma warning(disable:4201) // nameless struct/union 14 | 15 | // 16 | // TD_ASSERT 17 | // 18 | // This macro is identical to NT_ASSERT but works in fre builds as well. 19 | // 20 | // It is used for error checking in the driver in cases where 21 | // we can't easily report the error to the user mode app, or the 22 | // error is so severe that we should break in immediately to 23 | // investigate. 24 | // 25 | // It's better than DbgBreakPoint because it provides additional info 26 | // that can be dumped with .exr -1, and individual asserts can be disabled 27 | // from kd using 'ahi' command. 28 | // 29 | 30 | // 31 | // Driver and device names 32 | // 33 | 34 | #define QD_DRIVER_NAME L"srepp" 35 | #define QD_DRIVER_NAME_WITH_EXT L"srepp.sys" 36 | 37 | #define QD_NT_DEVICE_NAME L"\\Device\\SummitRouteEPP" 38 | #define QD_DOS_DEVICES_LINK_NAME L"\\DosDevices\\SummitRouteEPP" 39 | #define QD_WIN32_DEVICE_NAME L"\\\\.\\SummitRouteEPP" 40 | 41 | // 42 | // Driver and User communication 43 | // 44 | typedef struct _COMM_CONTROL_REQUEST { 45 | // The request ID is used to match up the response to the original request 46 | ULONG RequestID; 47 | 48 | // The request type indicates the operation to be performed 49 | ULONG RequestType; 50 | 51 | // This specifies the size of the request buffer 52 | ULONG RequestBufferLength; 53 | 54 | // The data buffer allows the application to receive arbitrary data 55 | // Note that this is done OUT OF BOUNDS from the IOCTL. Thus, the driver 56 | // is responsible for managing this. 57 | PVOID RequestBuffer; 58 | } COMM_CONTROL_REQUEST, *PCOMM_CONTROL_REQUEST; 59 | 60 | 61 | typedef struct _Comm_Request { 62 | COMM_CONTROL_REQUEST CommControlRequest; 63 | CHAR CommRequestBuffer[5120]; 64 | } COMM_REQUEST, *PCOMM_REQUEST; 65 | 66 | 67 | typedef struct _COMM_CREATE_PROC { 68 | SIZE_T Size; // 4 + 4 + 4 + 4 + 4 + 2 + 4 + 1024(2) + 2 + 4 + 1024(2) = 4128 69 | union { 70 | ULONG Flags; 71 | struct { 72 | ULONG ImageFileNameIsAccurate: 1; // If FileOpenNameAvailable is TRUE or not 73 | ULONG Reserved : 31; 74 | }; 75 | }; 76 | ULONG pid; // Process ID 77 | 78 | ULONG ppid; // Parent Process ID 79 | ULONG ptid; // Parent Thread ID (the creating thread) 80 | 81 | USHORT ImageFileNameLength; 82 | ULONG ImageFileNameFullLength; 83 | WCHAR ImageFileNameBuf[1024]; 84 | 85 | USHORT CommandLineLength; 86 | ULONG CommandLineFullLength; 87 | WCHAR CommandLineBuf[1024]; 88 | 89 | USHORT ProcIndex; // When the userland controller wants to respond, it needs this so it can tell the driver what process it is deciding on 90 | USHORT IntegrityCheck; // Tell the userland controller a value that we'll check when it responds to ensure we got our request from the correct place 91 | } COMM_CREATE_PROC, *PCOMM_CREATE_PROC; 92 | 93 | 94 | 95 | // Used for communicating with the userland controller so it can decide on a process 96 | typedef struct _COMM_CONTROL_PROC { 97 | USHORT ProcIndex; // When the user controller responds, we need to know where to 98 | USHORT Decision; // Allow (1) or Deny (2) 99 | USHORT IntegrityCheck; 100 | } COMM_CONTROL_PROC, *PCOMM_CONTROL_PROC; 101 | 102 | 103 | // DeviceType is an arbitrary value between 32768 and 65535 104 | #define QD_CTL_CODE_DEVICE_TYPE 33333 105 | // Function must be between 2048 and 4095 106 | #define QD_CTL_CODE_FUNCTION 3333 107 | 108 | // 109 | // Service IOCTLs to driver 110 | // 111 | #define QD_IOCTL_GET_NEW_PROCESSES (DWORD)CTL_CODE(QD_CTL_CODE_DEVICE_TYPE, QD_CTL_CODE_FUNCTION, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 112 | #define QD_IOCTL_CONTROLLER_PROCESS_DECISION (DWORD)CTL_CODE(QD_CTL_CODE_DEVICE_TYPE, QD_CTL_CODE_FUNCTION+1, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 113 | 114 | #define QD_COMM_READ_REQUEST 0x10 115 | #define QD_COMM_WRITE_REQUEST 0x20 116 | 117 | 118 | #define TD_ASSERT(_exp) \ 119 | ((!(_exp)) ? \ 120 | (__annotation(L"Debug", L"AssertFail", L#_exp), \ 121 | DbgRaiseAssertionFailure(), FALSE) : \ 122 | TRUE) 123 | 124 | // 125 | // Responses for controller 126 | // 127 | #define CONTROLLER_RESPONSE_NO_RESPONSE 0 128 | #define CONTROLLER_RESPONSE_ALLOW 1 129 | #define CONTROLLER_RESPONSE_DENY 2 -------------------------------------------------------------------------------- /src/common/log.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | // 13 | // Logging support macros. 14 | // 15 | // LOG_INFO 16 | // LOG_INFO_FAILURE 17 | // LOG_PASSED 18 | // LOG_ERROR 19 | // 20 | 21 | 22 | #define LOG_LEVEL_TRACE 4 23 | #define LOG_LEVEL_INFO 3 24 | #define LOG_LEVEL_WARN 2 25 | #define LOG_LEVEL_ERROR 1 26 | #define LOG_LEVEL_CRITICAL 0 27 | 28 | void qdlog(DWORD level, TCHAR * format, ...); 29 | 30 | #ifdef _DEBUG 31 | #define LOG_TRACE(fmt, ...) \ 32 | qdlog(LOG_LEVEL_TRACE, _T("%hs: ") fmt _T("\n"), __FUNCTION__, __VA_ARGS__); 33 | #else 34 | #define LOG_TRACE(FormatString, ...) 35 | #endif 36 | 37 | #define LOG_INFO(fmt, ...) \ 38 | qdlog(LOG_LEVEL_INFO, _T("%hs: ") fmt _T("\n"), __FUNCTION__, __VA_ARGS__); 39 | 40 | #define LOG_WARN(fmt, ...) \ 41 | qdlog(LOG_LEVEL_WARN, _T("%hs: ") fmt _T("\n"), __FUNCTION__, __VA_ARGS__); 42 | 43 | #define LOG_ERROR(fmt, ...) \ 44 | qdlog(LOG_LEVEL_ERROR, _T("%hs: ") fmt _T("\n"), __FUNCTION__, __VA_ARGS__); 45 | 46 | #define LOG_CRITICAL(fmt, ...) \ 47 | qdlog(LOG_LEVEL_CRITICAL, _T("%hs: ") fmt _T("\n"), __FUNCTION__, __VA_ARGS__); 48 | 49 | 50 | #define TD_ASSERT(_exp) \ 51 | ((!(_exp)) ? \ 52 | (__annotation(L"Debug", L"AssertFail", L#_exp), \ 53 | DbgRaiseAssertionFailure(), FALSE) : \ 54 | TRUE) 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/common/srkcomm.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | #include "..\common\drivercomm.h" 12 | #include 13 | 14 | extern "C" 15 | { 16 | // Define callback for QdMonitor 17 | typedef DWORD(*t_processMonitorCallback)(PCOMM_CREATE_PROC pComm_Create_Proc); 18 | 19 | 20 | /////////////////////////////////////////////////////////////////////////////// 21 | /// 22 | /// Retrieve info about new processes being created from the driver 23 | /// 24 | /////////////////////////////////////////////////////////////////////////////// 25 | __declspec(dllexport) BOOL QdMonitor(t_processMonitorCallback processMonitorCallback); 26 | 27 | 28 | /////////////////////////////////////////////////////////////////////////////// 29 | /// 30 | /// Tell the driver to allow or deny a process 31 | /// 32 | /////////////////////////////////////////////////////////////////////////////// 33 | __declspec(dllexport) BOOL QdControl(USHORT decision, USHORT integrityCheck); 34 | 35 | 36 | /////////////////////////////////////////////////////////////////////////////// 37 | /// 38 | /// Installs the kernel driver 39 | /// 40 | /////////////////////////////////////////////////////////////////////////////// 41 | __declspec(dllexport) BOOL QdInstallDriver(); 42 | 43 | 44 | /////////////////////////////////////////////////////////////////////////////// 45 | /// 46 | /// Uninstalls the kernel driver 47 | /// 48 | /////////////////////////////////////////////////////////////////////////////// 49 | __declspec(dllexport) BOOL QdUninstallDriver(); 50 | 51 | 52 | /////////////////////////////////////////////////////////////////////////////// 53 | /// 54 | /// Initialize globals 55 | /// 56 | /////////////////////////////////////////////////////////////////////////////// 57 | __declspec(dllexport) BOOL QdInitialize(); 58 | 59 | 60 | /////////////////////////////////////////////////////////////////////////////// 61 | /// 62 | /// Cleanup 63 | /// 64 | /////////////////////////////////////////////////////////////////////////////// 65 | __declspec(dllexport) BOOL QdUnInitialize(); 66 | } -------------------------------------------------------------------------------- /src/control/main.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #include "pch.h" 11 | #include "..\common\log.h" 12 | #include "..\common\drivercomm.h" 13 | #include "..\common\srkcomm.h" 14 | 15 | /////////////////////////////////////////////////////////////////////////////// 16 | /// 17 | /// PrintUsage 18 | /// 19 | /////////////////////////////////////////////////////////////////////////////// 20 | void TcPrintUsage() 21 | { 22 | puts("Usage:"); 23 | puts(""); 24 | puts("control.exe -install -uninstall -monitor [-?]"); 25 | puts(" -install install driver"); 26 | puts(" -uninstall uninstall driver"); 27 | puts(" -monitor reecieves info about processes being loaded"); 28 | } 29 | 30 | DWORD TcProcessMonitorCallback(PCOMM_CREATE_PROC pCreateProcStruct) { 31 | _tprintf(_T("New Process\n")); 32 | _tprintf(_T(" Image: %ls\n"), pCreateProcStruct->ImageFileNameBuf); 33 | _tprintf(_T(" Cmd: %ls\n"), pCreateProcStruct->CommandLineBuf); 34 | _tprintf(_T(" ppid: %lu\n"), pCreateProcStruct->ppid); 35 | 36 | // Decide 37 | 38 | /* 39 | // Here's an example of denying calc 40 | USHORT decision = CONTROLLER_RESPONSE_ALLOW; 41 | if (wcsstr(pCreateProcStruct->ImageFileNameBuf, L"calc") != 0) { 42 | puts("Deny calc from running"); 43 | decision = CONTROLLER_RESPONSE_DENY; 44 | } 45 | */ 46 | 47 | QdControl(decision, pCreateProcStruct->IntegrityCheck); 48 | 49 | return 0; 50 | } 51 | 52 | 53 | /////////////////////////////////////////////////////////////////////////////// 54 | /// 55 | /// wmain() 56 | /// 57 | /////////////////////////////////////////////////////////////////////////////// 58 | int _cdecl 59 | wmain( 60 | _In_ int argc, 61 | _In_reads_(argc) LPCWSTR argv[] 62 | ) 63 | { 64 | int ExitCode = ERROR_SUCCESS; 65 | 66 | // Ensure we have a command 67 | if (argc <= 1) 68 | { 69 | TcPrintUsage(); 70 | goto Exit; 71 | } 72 | 73 | const wchar_t * arg = argv[1]; 74 | 75 | // Initialize globals and logging 76 | if (!QdInitialize()) 77 | { 78 | puts("Initialization failed - program exiting"); 79 | ExitCode = ERROR_FUNCTION_FAILED; 80 | goto Exit; 81 | } 82 | 83 | if (0 == wcscmp(arg, L"-install")) 84 | { 85 | QdInstallDriver(); 86 | } 87 | else if (0 == wcscmp(arg, L"-uninstall")) 88 | { 89 | QdUninstallDriver(); 90 | } 91 | else if (0 == wcscmp(arg, L"-monitor")) 92 | { 93 | // Loop as long as the device exists 94 | while (QdMonitor(TcProcessMonitorCallback)) { 95 | continue; 96 | } 97 | } 98 | else 99 | { 100 | puts("Unknown command!"); 101 | TcPrintUsage(); 102 | } 103 | 104 | 105 | Exit: 106 | 107 | if (!QdUnInitialize()) 108 | { 109 | puts("UnInitialization failed"); 110 | ExitCode = ERROR_FUNCTION_FAILED; 111 | } 112 | 113 | return ExitCode; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /src/control/pch.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | -------------------------------------------------------------------------------- /src/control/pchsrc.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" -------------------------------------------------------------------------------- /src/control/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/control/readme.txt -------------------------------------------------------------------------------- /src/driver/Resource.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/driver/Resource.aps -------------------------------------------------------------------------------- /src/driver/Resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/driver/Resource.rc -------------------------------------------------------------------------------- /src/driver/driver.c: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #include "pch.h" 11 | #include "driver.h" 12 | 13 | // 14 | // Process notify routines. 15 | // 16 | BOOLEAN gProcessNotifyRoutine_isSet = FALSE; 17 | 18 | // Reference to device object struct that maintains globals 19 | PDEVICE_OBJECT g_CommDeviceObject; 20 | 21 | 22 | // 23 | // Function declarations 24 | // 25 | DRIVER_INITIALIZE DriverEntry; 26 | 27 | _Dispatch_type_(IRP_MJ_CREATE) DRIVER_DISPATCH TdDeviceCreate; 28 | _Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH TdDeviceClose; 29 | _Dispatch_type_(IRP_MJ_CLEANUP) DRIVER_DISPATCH TdDeviceCleanup; 30 | _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH TdDeviceControl; 31 | 32 | DRIVER_UNLOAD TdDeviceUnload; 33 | 34 | 35 | /////////////////////////////////////////////////////////////////////////////// 36 | /// 37 | /// Driver entry 38 | /// 39 | /////////////////////////////////////////////////////////////////////////////// 40 | NTSTATUS 41 | DriverEntry( 42 | _In_ PDRIVER_OBJECT DriverObject, 43 | _In_ PUNICODE_STRING RegistryPath 44 | ) 45 | { 46 | NTSTATUS Status; 47 | UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING(QD_NT_DEVICE_NAME); 48 | UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME); 49 | BOOLEAN SymLinkCreated = FALSE; 50 | PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt; 51 | 52 | UNREFERENCED_PARAMETER(RegistryPath); 53 | 54 | // Request NX Non-Paged Pool when available 55 | ExInitializeDriverRuntime(DrvRtPoolNxOptIn); 56 | 57 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: DriverEntry: Driver loaded\n"); 58 | 59 | // 60 | // Initialize globals. 61 | // 62 | 63 | // 64 | // Create our device object. 65 | // 66 | // TODO Consider using IoCreateDeviceSecure 67 | Status = IoCreateDevice( 68 | DriverObject, // pointer to driver object 69 | sizeof(QD_COMM_CONTROL_DEVICE_EXTENSION), // device extension size 70 | &NtDeviceName, // device name 71 | FILE_DEVICE_UNKNOWN, // device type 72 | 0, // device characteristics 73 | FALSE, // not exclusive 74 | &g_CommDeviceObject); // returned device object pointer 75 | if (!NT_SUCCESS(Status)) 76 | { 77 | goto Exit; 78 | } 79 | 80 | TD_ASSERT(g_CommDeviceObject == DriverObject->DeviceObject); 81 | 82 | // 83 | // Set dispatch routines. 84 | // 85 | DriverObject->MajorFunction[IRP_MJ_CREATE] = TdDeviceCreate; 86 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = TdDeviceClose; 87 | DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TdDeviceCleanup; 88 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TdDeviceControl; 89 | DriverObject->DriverUnload = TdDeviceUnload; 90 | 91 | 92 | // 93 | // Set up the device extension 94 | // 95 | controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension; 96 | controlExt->MagicNumber = QD_COMM_CONTROL_EXTENSION_MAGIC_NUMBER; 97 | InitializeListHead(&controlExt->ProcessQueue); 98 | ExInitializeFastMutex(&controlExt->ProcessQueueLock); 99 | InitializeListHead(&controlExt->RequestQueue); 100 | ExInitializeFastMutex(&controlExt->RequestQueueLock); 101 | ExInitializeFastMutex(&controlExt->DecisionDataLock); 102 | 103 | controlExt->DecisionData = (PCONTROL_PROC_INTERNAL)ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS, 'SRdd'); 104 | RtlZeroMemory(controlExt->DecisionData, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS); 105 | 106 | // Init DecisionData 107 | for (USHORT i = 0; i < QD_MAX_PROCS; i++) { 108 | PCONTROL_PROC_INTERNAL control_proc = &(controlExt->DecisionData[i]); 109 | control_proc->StartTime.QuadPart = 0; 110 | KeInitializeEvent(&(control_proc->DecisionEvent), NotificationEvent, FALSE); 111 | } 112 | 113 | // 114 | // Create a link in the Win32 namespace. 115 | // 116 | Status = IoCreateSymbolicLink(&DosDevicesLinkName, &NtDeviceName); 117 | if (!NT_SUCCESS(Status)) 118 | { 119 | goto Exit; 120 | } 121 | 122 | SymLinkCreated = TRUE; 123 | 124 | // 125 | // Set process create routines. 126 | // 127 | Status = PsSetCreateProcessNotifyRoutineEx( 128 | MyCreateProcessNotifyRoutine, 129 | FALSE 130 | ); 131 | if (!NT_SUCCESS(Status)) 132 | { 133 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "QuietDragon: DriverEntry: PsSetCreateProcessNotifyRoutineEx returned 0x%x\n", Status); 134 | goto Exit; 135 | } 136 | 137 | gProcessNotifyRoutine_isSet = TRUE; 138 | 139 | 140 | Exit: 141 | 142 | if (!NT_SUCCESS(Status)) 143 | { 144 | if (gProcessNotifyRoutine_isSet == TRUE) 145 | { 146 | Status = PsSetCreateProcessNotifyRoutineEx( 147 | MyCreateProcessNotifyRoutine, 148 | TRUE 149 | ); 150 | TD_ASSERT(Status == STATUS_SUCCESS); 151 | 152 | gProcessNotifyRoutine_isSet = FALSE; 153 | } 154 | 155 | if (SymLinkCreated == TRUE) 156 | { 157 | IoDeleteSymbolicLink(&DosDevicesLinkName); 158 | } 159 | 160 | if (g_CommDeviceObject != NULL) 161 | { 162 | IoDeleteDevice(g_CommDeviceObject); 163 | } 164 | } 165 | 166 | return Status; 167 | } 168 | 169 | 170 | /////////////////////////////////////////////////////////////////////////////// 171 | /// 172 | /// Handle driver unloading. All this driver needs to do 173 | /// is to delete the device object and the symbolic link between our 174 | /// device name and the Win32 visible name. 175 | /// 176 | /////////////////////////////////////////////////////////////////////////////// 177 | VOID 178 | TdDeviceUnload( 179 | _In_ PDRIVER_OBJECT DriverObject 180 | ) 181 | { 182 | NTSTATUS Status = STATUS_SUCCESS; 183 | UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME); 184 | 185 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: TdDeviceUnload\n"); 186 | 187 | // Unregister process notify routines. 188 | if (gProcessNotifyRoutine_isSet == TRUE) 189 | { 190 | Status = PsSetCreateProcessNotifyRoutineEx( 191 | MyCreateProcessNotifyRoutine, 192 | TRUE 193 | ); 194 | 195 | TD_ASSERT(Status == STATUS_SUCCESS); 196 | 197 | gProcessNotifyRoutine_isSet = FALSE; 198 | } 199 | 200 | // TODO Need to clean up lists and locks 201 | 202 | // Free allocated mem 203 | PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension; 204 | ExFreePoolWithTag(controlExt->DecisionData, 'SRdd'); 205 | 206 | // Delete the link from our device name to a name in the Win32 namespace. 207 | Status = IoDeleteSymbolicLink(&DosDevicesLinkName); 208 | if (Status != STATUS_INSUFFICIENT_RESOURCES) 209 | { 210 | // IoDeleteSymbolicLink can fail with STATUS_INSUFFICIENT_RESOURCES. 211 | TD_ASSERT(NT_SUCCESS(Status)); 212 | } 213 | 214 | // Delete our device object. 215 | IoDeleteDevice(DriverObject->DeviceObject); 216 | } 217 | 218 | 219 | /////////////////////////////////////////////////////////////////////////////// 220 | /// 221 | /// This function handles the 'create' irp. 222 | /// 223 | /////////////////////////////////////////////////////////////////////////////// 224 | NTSTATUS 225 | TdDeviceCreate( 226 | IN PDEVICE_OBJECT DeviceObject, 227 | IN PIRP Irp 228 | ) 229 | { 230 | UNREFERENCED_PARAMETER(DeviceObject); 231 | 232 | Irp->IoStatus.Status = STATUS_SUCCESS; 233 | Irp->IoStatus.Information = 0; 234 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 235 | 236 | return STATUS_SUCCESS; 237 | } 238 | 239 | 240 | /////////////////////////////////////////////////////////////////////////////// 241 | /// 242 | /// Handles the 'close' irp. 243 | /// 244 | /////////////////////////////////////////////////////////////////////////////// 245 | NTSTATUS 246 | TdDeviceClose( 247 | IN PDEVICE_OBJECT DeviceObject, 248 | IN PIRP Irp 249 | ) 250 | { 251 | UNREFERENCED_PARAMETER(DeviceObject); 252 | 253 | Irp->IoStatus.Status = STATUS_SUCCESS; 254 | Irp->IoStatus.Information = 0; 255 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 256 | 257 | return STATUS_SUCCESS; 258 | } 259 | 260 | /////////////////////////////////////////////////////////////////////////////// 261 | /// 262 | /// Handles the 'cleanup' irp. 263 | /// 264 | /////////////////////////////////////////////////////////////////////////////// 265 | NTSTATUS 266 | TdDeviceCleanup( 267 | IN PDEVICE_OBJECT DeviceObject, 268 | IN PIRP Irp 269 | ) 270 | { 271 | UNREFERENCED_PARAMETER(DeviceObject); 272 | 273 | Irp->IoStatus.Status = STATUS_SUCCESS; 274 | Irp->IoStatus.Information = 0; 275 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 276 | 277 | return STATUS_SUCCESS; 278 | } 279 | 280 | 281 | /////////////////////////////////////////////////////////////////////////////// 282 | /// 283 | /// This function handles 'control' irp. 284 | /// 285 | /////////////////////////////////////////////////////////////////////////////// 286 | NTSTATUS 287 | TdDeviceControl( 288 | IN PDEVICE_OBJECT DeviceObject, 289 | IN PIRP Irp 290 | ) 291 | { 292 | PIO_STACK_LOCATION IrpStack; 293 | ULONG Ioctl; 294 | NTSTATUS Status; 295 | 296 | UNREFERENCED_PARAMETER(DeviceObject); 297 | 298 | 299 | Status = STATUS_SUCCESS; 300 | 301 | IrpStack = IoGetCurrentIrpStackLocation(Irp); 302 | Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; 303 | 304 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: entering - ioctl code 0x%x\n", Ioctl); 305 | 306 | // Sanity check: Check the size of the request 307 | if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(COMM_REQUEST)) { 308 | // Wrong size 309 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "TdDeviceControl: Wrong size request\n"); 310 | Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; 311 | Irp->IoStatus.Information = sizeof(COMM_REQUEST); 312 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 313 | return STATUS_BUFFER_OVERFLOW; 314 | } 315 | 316 | switch (Ioctl) 317 | { 318 | case QD_IOCTL_GET_NEW_PROCESSES: 319 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: recieved QD_IOCTL_GET_NEW_PROCESSES\n"); 320 | 321 | // Process it 322 | Status = ProcessIoctl_GetNewProcesses(Irp); 323 | 324 | // 325 | // Complete the irp and return. 326 | // 327 | Irp->IoStatus.Status = Status; 328 | if (STATUS_PENDING != Status) { 329 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 330 | } 331 | 332 | break; 333 | case QD_IOCTL_CONTROLLER_PROCESS_DECISION: 334 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: recieved QD_IOCTL_CONTROLLER_PROCESS_DECISION\n"); 335 | 336 | // Process it 337 | Status = ProcessIoctl_ControllerProcessDecision(Irp); 338 | 339 | // 340 | // Complete the irp and return. 341 | // 342 | Irp->IoStatus.Status = Status; 343 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 344 | 345 | break; 346 | default: 347 | // 348 | // Invalid request operation 349 | // 350 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "TdDeviceControl: unrecognized ioctl code 0x%x\n", Ioctl); 351 | 352 | Status = STATUS_INVALID_DEVICE_REQUEST; 353 | Irp->IoStatus.Status = Status; 354 | Irp->IoStatus.Information = 0; 355 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 356 | } 357 | 358 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl leaving - status 0x%x\n", Status); 359 | return Status; 360 | } -------------------------------------------------------------------------------- /src/driver/driver.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | #include "..\common\drivercomm.h" 13 | 14 | // 15 | // Internal use 16 | // 17 | #define QD_MAX_PROCS 16 18 | 19 | // KeQuerySystemTime returns number of 100 nanoseconds, so the timeout is 3 seconds 20 | #define QD_TIMEOUT (10000000 * 3) 21 | 22 | // 1. Driver tells userland controller about the process being started. 23 | // 2. Controller tells the driver it's decision via decision ioctl. 24 | // 3. Decision ioctl signals to process callback that a decision was made. 25 | typedef struct _CONTROL_PROC_INTERNAL { 26 | LARGE_INTEGER StartTime; // Keep track of when this occurred so we can clear it out if anything goes wrong 27 | KEVENT DecisionEvent; // For signalling within the driver 28 | USHORT Decision; // Allow (1) or Deny (2) 29 | USHORT IntegrityCheck; // Simple check to ensure something evil in userland isn't happening 30 | } CONTROL_PROC_INTERNAL, *PCONTROL_PROC_INTERNAL; 31 | 32 | 33 | // 34 | // Device extension 35 | // 36 | typedef struct _QD_COMM_CONTROL_DEVICE_EXTENSION { 37 | // Data structure magic # 38 | ULONG MagicNumber; 39 | 40 | // Queue of new processes to be sent to userland 41 | LIST_ENTRY ProcessQueue; 42 | 43 | // Control Thread Service Queue Lock 44 | FAST_MUTEX ProcessQueueLock; 45 | 46 | // Control Request Queue - Userland requests for new info 47 | LIST_ENTRY RequestQueue; 48 | 49 | // Control Request Queue Lock 50 | FAST_MUTEX RequestQueueLock; 51 | 52 | // Control Decision Queue Lock 53 | FAST_MUTEX DecisionDataLock; 54 | 55 | // Pointer to array of stucts to store decision data when controller makes decisions for communicating around driver 56 | PCONTROL_PROC_INTERNAL DecisionData; 57 | 58 | } QD_COMM_CONTROL_DEVICE_EXTENSION, *PQD_COMM_CONTROL_DEVICE_EXTENSION; 59 | 60 | #define QD_COMM_CONTROL_EXTENSION_MAGIC_NUMBER 0x1d88f403 61 | 62 | // 63 | // Globals 64 | // 65 | extern PDEVICE_OBJECT g_CommDeviceObject; 66 | 67 | // 68 | // Function declarations 69 | // 70 | NTSTATUS 71 | ProcessIoctl_GetNewProcesses( 72 | _Inout_ PIRP Irp 73 | ); 74 | 75 | NTSTATUS 76 | ProcessIoctl_ControllerProcessDecision( 77 | _Inout_ PIRP Irp 78 | ); 79 | 80 | 81 | VOID 82 | MyCreateProcessNotifyRoutine( 83 | _Inout_ PEPROCESS Process, 84 | _In_ HANDLE ProcessId, 85 | _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo 86 | ); 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/driver/driver.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Win7 Debug 6 | Win32 7 | 8 | 9 | Win7 Release 10 | Win32 11 | 12 | 13 | Win7 Debug 14 | x64 15 | 16 | 17 | Win7 Release 18 | x64 19 | 20 | 21 | 22 | {933979A5-8C77-4E92-9070-A474158D9024} 23 | $(MSBuildProjectName) 24 | Win7 Debug 25 | Win32 26 | {4F705967-BFEE-4A9C-B19E-46ADBDFC89A1} 27 | driver 28 | 29 | 30 | 31 | Win7 32 | False 33 | WDM 34 | WindowsKernelModeDriver8.1 35 | Driver 36 | 37 | 38 | Win7 39 | True 40 | WDM 41 | WindowsKernelModeDriver8.1 42 | Driver 43 | 44 | 45 | Win7 46 | False 47 | WDM 48 | WindowsKernelModeDriver8.1 49 | Driver 50 | 51 | 52 | Win7 53 | True 54 | WDM 55 | WindowsKernelModeDriver8.1 56 | Driver 57 | 58 | 59 | 60 | ..\..\bins\$(Configuration)\$(Platform)\ 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | srepp 79 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 80 | 81 | 82 | srepp 83 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 84 | 85 | 86 | srepp 87 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 88 | 89 | 90 | srepp 91 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 92 | 93 | 94 | srepp 95 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 96 | 97 | 98 | srepp 99 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 100 | 101 | 102 | 103 | %(AdditionalIncludeDirectories) 104 | 105 | 106 | %(AdditionalIncludeDirectories) 107 | Disabled 108 | true 109 | Level4 110 | 111 | 112 | POOL_NX_OPTIN;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions) 113 | 114 | 115 | %(AdditionalIncludeDirectories) 116 | 117 | 118 | %(AdditionalDependencies) 119 | %(AdditionalOptions) /INTEGRITYCHECK 120 | 121 | 122 | 123 | 124 | %(AdditionalIncludeDirectories) 125 | 126 | 127 | %(AdditionalIncludeDirectories) 128 | Disabled 129 | true 130 | Level4 131 | 132 | 133 | POOL_NX_OPTIN;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions) 134 | 135 | 136 | %(AdditionalIncludeDirectories) 137 | 138 | 139 | %(AdditionalDependencies) 140 | %(AdditionalOptions) /INTEGRITYCHECK 141 | 142 | 143 | 144 | 145 | %(AdditionalIncludeDirectories) 146 | 147 | 148 | %(AdditionalIncludeDirectories) 149 | Disabled 150 | true 151 | Level4 152 | 153 | 154 | POOL_NX_OPTIN;_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions); 155 | 156 | 157 | %(AdditionalIncludeDirectories) 158 | 159 | 160 | %(AdditionalDependencies) 161 | %(AdditionalOptions) /INTEGRITYCHECK 162 | 163 | 164 | 165 | 166 | %(AdditionalIncludeDirectories) 167 | 168 | 169 | %(AdditionalIncludeDirectories) 170 | Disabled 171 | true 172 | Level4 173 | 174 | 175 | POOL_NX_OPTIN;_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions);DEBUG 176 | 177 | 178 | %(AdditionalIncludeDirectories) 179 | 180 | 181 | %(AdditionalDependencies) 182 | %(AdditionalOptions) /INTEGRITYCHECK 183 | 184 | 185 | 186 | 187 | ;%(AdditionalIncludeDirectories) 188 | pch.h 189 | Create 190 | $(IntDir)\pch.h.pch 191 | 192 | 193 | ;%(AdditionalIncludeDirectories) 194 | pch.h 195 | Use 196 | $(IntDir)\pch.h.pch 197 | 198 | 199 | ;%(AdditionalIncludeDirectories) 200 | pch.h 201 | Use 202 | $(IntDir)\pch.h.pch 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /src/driver/pch.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/driver/pchsrc.c: -------------------------------------------------------------------------------- 1 | #include "pch.h" -------------------------------------------------------------------------------- /src/driver/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Resource.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 | -------------------------------------------------------------------------------- /src/srkcomm/dllmain.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #include "stdafx.h" 11 | #include "..\common\log.h" 12 | #include "manageService.h" 13 | 14 | 15 | void qdlog(DWORD level, TCHAR * format, ...) 16 | { 17 | const SIZE_T numChars = 256; 18 | TCHAR buffer[numChars]; 19 | va_list args; 20 | va_start(args, format); 21 | _vstprintf(buffer, numChars, format, args); 22 | OutputDebugString(buffer); 23 | va_end(args); 24 | } 25 | 26 | BOOL APIENTRY DllMain( HMODULE hModule, 27 | DWORD ul_reason_for_call, 28 | LPVOID lpReserved 29 | ) 30 | { 31 | switch (ul_reason_for_call) 32 | { 33 | case DLL_PROCESS_ATTACH: 34 | g_hModule = hModule; 35 | OutputDebugString(_T("qdsvc: Loaded")); // TODO make log msg 36 | break; 37 | case DLL_THREAD_ATTACH: 38 | case DLL_THREAD_DETACH: 39 | case DLL_PROCESS_DETACH: 40 | break; 41 | } 42 | return TRUE; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/srkcomm/manageService.h: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | #pragma once 11 | 12 | // 13 | // Globals 14 | // 15 | extern HANDLE g_QdDeviceHandle; 16 | extern HMODULE g_hModule; 17 | 18 | // 19 | // Commands 20 | // 21 | BOOL QdInstallDriver(); 22 | BOOL QdUninstallDriver(); 23 | BOOL QdMonitor(); 24 | 25 | // 26 | // Utility functions 27 | // 28 | BOOL QdInitialize(); 29 | BOOL QdUnInitialize(); 30 | BOOL QdCleanupSCM(); 31 | 32 | BOOL QdInitializeGlobals(); 33 | BOOL QdLoadDriver(); 34 | BOOL QdUnloadDriver(); 35 | 36 | BOOL QdCreateService(); 37 | BOOL QdDeleteService(); 38 | BOOL QdStartService(); 39 | BOOL QdStopService(); 40 | 41 | BOOL QdOpenDevice(); 42 | BOOL QdCloseDevice(); 43 | -------------------------------------------------------------------------------- /src/srkcomm/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/srkcomm/resource.h -------------------------------------------------------------------------------- /src/srkcomm/srkcomm.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/srkcomm/srkcomm.aps -------------------------------------------------------------------------------- /src/srkcomm/srkcomm.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | // srsvc.cpp : Defines the exported functions for the DLL application. 11 | // 12 | 13 | #include "stdafx.h" 14 | #include "..\common\log.h" 15 | #include "..\common\srkcomm.h" 16 | #include "..\common\drivercomm.h" 17 | #include "manageService.h" 18 | 19 | static HANDLE CommRequestEvent = NULL; 20 | static bool bRunning = true; 21 | 22 | /////////////////////////////////////////////////////////////////////////////// 23 | /// 24 | /// Retrieve info about new processes being created from the driver 25 | /// 26 | /////////////////////////////////////////////////////////////////////////////// 27 | __declspec(dllexport) 28 | BOOL 29 | QdMonitor(t_processMonitorCallback processMonitorCallback) 30 | { 31 | BOOL ReturnValue = FALSE; 32 | OVERLAPPED CommRequestOverlapped = { 0 }; 33 | COMM_REQUEST CommRequest = { 0 }; 34 | 35 | // Open a handle to the device. 36 | ReturnValue = QdOpenDevice(); 37 | if (ReturnValue != TRUE) 38 | { 39 | LOG_ERROR(_T("QdOpenDevice failed")); 40 | goto Exit; 41 | } 42 | 43 | // 44 | // Init overlapped structured 45 | // 46 | CommRequestOverlapped.hEvent = CommRequestEvent; 47 | ResetEvent(CommRequestEvent); 48 | 49 | CommRequest.CommControlRequest.RequestBuffer = &CommRequest.CommRequestBuffer[0]; 50 | // TODO Set CommRequest.CommControlRequest.RequestID 51 | CommRequest.CommControlRequest.RequestBufferLength = sizeof(CommRequest.CommRequestBuffer); 52 | 53 | BOOL status; 54 | DWORD bytesReturned; 55 | DWORD dwLastError; 56 | 57 | status = DeviceIoControl(g_QdDeviceHandle, QD_IOCTL_GET_NEW_PROCESSES, 58 | &(CommRequest), sizeof(COMM_REQUEST), 59 | &(CommRequest), sizeof(COMM_REQUEST), 60 | &bytesReturned, 61 | &CommRequestOverlapped); 62 | dwLastError = GetLastError(); 63 | 64 | // 65 | // Ensure the request is either completed or pending 66 | // 67 | if (status) { 68 | // Completed 69 | LOG_INFO(_T("DeviceIoControl returned success immediately")); 70 | } 71 | else if (dwLastError == ERROR_IO_PENDING) { 72 | // Pending 73 | LOG_INFO(_T("DeviceIoControl Pending")); 74 | } 75 | else { 76 | // An error occurred 77 | LOG_ERROR(_T("DeviceIoControl failed - Status %x"), GetLastError()); 78 | 79 | // TODO handle failure 80 | ReturnValue = FALSE; 81 | goto Exit; 82 | } 83 | 84 | // GetOverlappedResult waits infinitely. 85 | // Alternatively, could use HasOverlappedIoCompleted and Sleep in a loop 86 | // so I could terminate more easily 87 | // TODO EVENTUALLY Use GetOverlappedResultEx for Win 8 which allows timeouts 88 | 89 | DWORD bytesTransferred; 90 | status = GetOverlappedResult( 91 | g_QdDeviceHandle, 92 | &CommRequestOverlapped, 93 | &bytesTransferred, 94 | TRUE); // bWait 95 | if (!status) { 96 | LOG_ERROR(_T("GetOverlappedResult failed - Status %x"), GetLastError()); 97 | // Handle failure 98 | ReturnValue = FALSE; 99 | goto Exit; 100 | } 101 | 102 | if (!bRunning) { 103 | LOG_INFO(_T("We've been signalled to stop running")); 104 | ReturnValue = TRUE; 105 | goto Exit; 106 | } 107 | 108 | LOG_INFO(_T("GetOverlappedResult completed: Id= %08x, Type = %08x, CommRequest RequestBuffer %08x, CommRequestBuffer %08x, Length %x"), 109 | CommRequest.CommControlRequest.RequestID, 110 | CommRequest.CommControlRequest.RequestType, 111 | CommRequest.CommControlRequest.RequestBuffer, 112 | CommRequest.CommRequestBuffer, 113 | CommRequest.CommControlRequest.RequestBufferLength); 114 | 115 | // 116 | // Call the callback 117 | // 118 | PCOMM_CREATE_PROC pCreateProcStruct = (PCOMM_CREATE_PROC)CommRequest.CommRequestBuffer; 119 | processMonitorCallback(pCreateProcStruct); 120 | 121 | 122 | ResetEvent(CommRequestOverlapped.hEvent); 123 | Exit: 124 | // Close our handle to the device. 125 | if (QdCloseDevice() != TRUE) 126 | { 127 | LOG_ERROR(_T("TcCloseDevice failed")); 128 | } 129 | 130 | return ReturnValue; 131 | } 132 | 133 | 134 | /////////////////////////////////////////////////////////////////////////////// 135 | /// 136 | /// Retrieve info about new processes being created from the driver 137 | /// 138 | /////////////////////////////////////////////////////////////////////////////// 139 | __declspec(dllexport) 140 | BOOL 141 | QdControl(USHORT decision, USHORT integrityCheck) 142 | { 143 | BOOL ReturnValue = FALSE; 144 | OVERLAPPED CommRequestOverlapped = { 0 }; 145 | COMM_REQUEST CommRequest = { 0 }; 146 | 147 | LOG_INFO(_T("Sending control decision of %d"), decision); 148 | 149 | // Open a handle to the device. 150 | ReturnValue = QdOpenDevice(); 151 | if (ReturnValue != TRUE) 152 | { 153 | LOG_ERROR(_T("QdOpenDevice failed")); 154 | goto Exit; 155 | } 156 | 157 | // 158 | // Init overlapped structured 159 | // 160 | CommRequestOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 161 | if (CommRequestOverlapped.hEvent == INVALID_HANDLE_VALUE) { 162 | LOG_ERROR(_T("Unable to create overlapped event")); 163 | // TODO handle failure 164 | } 165 | 166 | CommRequest.CommControlRequest.RequestBuffer = &CommRequest.CommRequestBuffer[0]; 167 | // TODO Set CommRequest.CommControlRequest.RequestID 168 | CommRequest.CommControlRequest.RequestBufferLength = sizeof(CommRequest.CommRequestBuffer); 169 | 170 | PCOMM_CONTROL_PROC pCommControlProc = (PCOMM_CONTROL_PROC)CommRequest.CommRequestBuffer; 171 | pCommControlProc->Decision = decision; 172 | pCommControlProc->IntegrityCheck = integrityCheck; 173 | 174 | BOOL status; 175 | DWORD bytesReturned; 176 | DWORD dwLastError; 177 | 178 | status = DeviceIoControl(g_QdDeviceHandle, QD_IOCTL_CONTROLLER_PROCESS_DECISION, 179 | &(CommRequest), sizeof(COMM_REQUEST), 180 | &(CommRequest), sizeof(COMM_REQUEST), 181 | &bytesReturned, 182 | &CommRequestOverlapped); 183 | dwLastError = GetLastError(); 184 | 185 | // 186 | // Ensure the request is either completed 187 | // 188 | if (status) { 189 | // Completed 190 | LOG_INFO(_T("DeviceIoControl returned success immediately")); 191 | } 192 | else { 193 | // An error occurred 194 | LOG_ERROR(_T("DeviceIoControl failed - Status %x"), GetLastError()); 195 | 196 | // TODO handle failure 197 | CloseHandle(CommRequestOverlapped.hEvent); 198 | ReturnValue = FALSE; 199 | goto Exit; 200 | } 201 | 202 | ResetEvent(CommRequestOverlapped.hEvent); 203 | CloseHandle(CommRequestOverlapped.hEvent); 204 | 205 | Exit: 206 | // Close our handle to the device. 207 | if (QdCloseDevice() != TRUE) 208 | { 209 | LOG_ERROR(_T("TcCloseDevice failed")); 210 | } 211 | 212 | LOG_TRACE(_T("Exiting")); 213 | return ReturnValue; 214 | } 215 | 216 | 217 | 218 | 219 | 220 | /////////////////////////////////////////////////////////////////////////////// 221 | /// 222 | /// Installs the kernel driver 223 | /// 224 | /////////////////////////////////////////////////////////////////////////////// 225 | __declspec(dllexport) 226 | BOOL 227 | QdInstallDriver() 228 | { 229 | BOOL bRC = TRUE; 230 | 231 | LOG_TRACE(L"Entering"); 232 | BOOL Result = QdLoadDriver(); 233 | if (Result != TRUE) 234 | { 235 | LOG_ERROR(L"QdLoadDriver failed, exiting"); 236 | bRC = FALSE; 237 | goto Exit; 238 | } 239 | 240 | Exit: 241 | LOG_TRACE(L"Exiting"); 242 | return bRC; 243 | } 244 | 245 | 246 | /////////////////////////////////////////////////////////////////////////////// 247 | /// 248 | /// Uninstalls the kernel driver 249 | /// 250 | /////////////////////////////////////////////////////////////////////////////// 251 | __declspec(dllexport) 252 | BOOL QdUninstallDriver() 253 | { 254 | BOOL bRC = TRUE; 255 | 256 | LOG_TRACE(L"Entering"); 257 | BOOL Result = QdUnloadDriver(); 258 | 259 | if (Result != TRUE) 260 | { 261 | LOG_ERROR(L"QdUnloadDriver failed, exiting"); 262 | bRC = FALSE; 263 | goto Exit; 264 | } 265 | 266 | Exit: 267 | LOG_TRACE(L"Exiting"); 268 | return bRC; 269 | } 270 | 271 | 272 | /////////////////////////////////////////////////////////////////////////////// 273 | /// 274 | /// Initialize globals 275 | /// 276 | /////////////////////////////////////////////////////////////////////////////// 277 | __declspec(dllexport) 278 | BOOL QdInitialize() 279 | { 280 | CommRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 281 | if (CommRequestEvent == INVALID_HANDLE_VALUE) { 282 | LOG_ERROR(_T("Unable to create overlapped event")); 283 | return FALSE; 284 | } 285 | 286 | BOOL Result = QdInitializeGlobals(); 287 | if (Result != TRUE) 288 | { 289 | LOG_ERROR(L"QdInitializeGlobals failed, exiting"); 290 | return FALSE; 291 | } 292 | return TRUE; 293 | } 294 | 295 | 296 | /////////////////////////////////////////////////////////////////////////////// 297 | /// 298 | /// Cleanup 299 | /// 300 | /////////////////////////////////////////////////////////////////////////////// 301 | __declspec(dllexport) 302 | BOOL QdUnInitialize() 303 | { 304 | if (bRunning) { 305 | bRunning = false; 306 | // Set the monitor's event so it wakes up so we can tell it to stop running 307 | SetEvent(CommRequestEvent); 308 | 309 | if (QdCleanupSCM() == FALSE) 310 | { 311 | LOG_ERROR(L"QdUnInitialize failed cleanup of SCM"); 312 | } 313 | } 314 | else { 315 | LOG_INFO(L"Already uninitialized once"); 316 | // Clean up event 317 | if (CommRequestEvent != NULL) { 318 | CloseHandle(CommRequestEvent); 319 | CommRequestEvent = NULL; 320 | } 321 | } 322 | return TRUE; 323 | } 324 | -------------------------------------------------------------------------------- /src/srkcomm/srkcomm.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SummitRoute/srepp_client/262bc6fd779d929d461ae5409b54ed0e439b6cf8/src/srkcomm/srkcomm.rc -------------------------------------------------------------------------------- /src/srkcomm/srkcomm.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Win7 Debug 6 | Win32 7 | 8 | 9 | Win7 Release 10 | Win32 11 | 12 | 13 | Win7 Debug 14 | x64 15 | 16 | 17 | Win7 Release 18 | x64 19 | 20 | 21 | 22 | {72D8D796-1865-4C8C-8D4A-8700171D6745} 23 | srkcomm 24 | srkcomm 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | DynamicLibrary 35 | true 36 | v120 37 | Unicode 38 | 39 | 40 | DynamicLibrary 41 | false 42 | v120 43 | true 44 | Unicode 45 | 46 | 47 | DynamicLibrary 48 | false 49 | v120 50 | true 51 | Unicode 52 | 53 | 54 | 55 | ..\..\bins\$(Configuration)\$(Platform)\ 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | true 65 | ..\..\build\$(Configuration)\$(Platform)\$(MSBuildProjectName)\ 66 | 67 | 68 | 69 | Use 70 | Level3 71 | Disabled 72 | WIN32;_DEBUG;_WINDOWS;_USRDLL;QDSVC_EXPORTS;%(PreprocessorDefinitions) 73 | true 74 | 75 | 76 | Windows 77 | true 78 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Shlwapi.lib;%(AdditionalDependencies) 79 | 80 | 81 | 82 | 83 | Use 84 | Level3 85 | Disabled 86 | WIN32;_DEBUG;_WINDOWS;_USRDLL;QDSVC_EXPORTS;%(PreprocessorDefinitions) 87 | true 88 | 89 | 90 | Windows 91 | true 92 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Shlwapi.lib;%(AdditionalDependencies) 93 | 94 | 95 | 96 | 97 | Level3 98 | Use 99 | MaxSpeed 100 | true 101 | true 102 | WIN32;NDEBUG;_WINDOWS;_USRDLL;QDSVC_EXPORTS;%(PreprocessorDefinitions) 103 | true 104 | 105 | 106 | Windows 107 | true 108 | true 109 | true 110 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Shlwapi.lib;%(AdditionalDependencies) 111 | 112 | 113 | 114 | 115 | Level3 116 | Use 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_WINDOWS;_USRDLL;QDSVC_EXPORTS;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Windows 125 | true 126 | true 127 | true 128 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Shlwapi.lib;%(AdditionalDependencies) 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | false 142 | 143 | 144 | 145 | 146 | Create 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /src/srkcomm/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // qdsvc.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/srkcomm/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include -------------------------------------------------------------------------------- /src/srkcomm/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /src/srsvc/Arbiter.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.IO; 15 | using System.Text.RegularExpressions; 16 | 17 | namespace srsvc 18 | { 19 | public enum Decision { NO_RESPONSE = 0, ALLOW = 1, DENY = 2 } 20 | 21 | public static class Arbiter 22 | { 23 | /// 24 | /// Stips unnecessary preffixes from the path string 25 | /// 26 | /// 27 | /// 28 | private static string CleanPath(string filePath) 29 | { 30 | // TODO Clean up path in a cleaner way, c# is apparently really brittle 31 | // Can open the file then use GetFinalPathNameByHandle http://msdn.microsoft.com/en-us/library/windows/desktop/aa364962(v=vs.85).aspx 32 | // Also useful would be GetFileInformationByHandle 33 | filePath = filePath.Trim(); 34 | filePath = filePath.Replace("\0", ""); 35 | filePath = filePath.Replace("\\??\\", ""); 36 | 37 | filePath = Path.GetFullPath(filePath); 38 | return filePath; 39 | } 40 | 41 | private static bool ExeMatchesAttribute(RuleAttribute attr, Executable exe) 42 | { 43 | Log.Info("Checking with rule: {0},{1}", attr.AttributeType, attr.Attribute); 44 | if (attr.AttributeType == "path" && (new Regex(attr.Attribute)).Match(exe.Path).Success) 45 | { 46 | return true; 47 | } 48 | else if (attr.AttributeType == "md5" && Helpers.HexStringToByteArray(attr.Attribute) == exe.Md5) 49 | { 50 | return true; 51 | } 52 | else if (attr.AttributeType == "sha1" && Helpers.HexStringToByteArray(attr.Attribute) == exe.Sha1) 53 | { 54 | return true; 55 | } 56 | else if (attr.AttributeType == "sha256" && Helpers.HexStringToByteArray(attr.Attribute) == exe.Sha256) 57 | { 58 | return true; 59 | } 60 | else if (exe.Signed) 61 | { 62 | foreach (var signer in exe.Signers) 63 | { 64 | if (attr.AttributeType == "SignerName" && attr.Attribute == signer.Name) 65 | { 66 | return true; 67 | } 68 | else if (attr.AttributeType == "Issuer" && attr.Attribute == signer.SigningCert.Issuer) 69 | { 70 | return true; 71 | } 72 | else if (attr.AttributeType == "SerialNumber" && Helpers.HexStringToByteArray(attr.Attribute) == signer.SigningCert.SerialNumber) 73 | { 74 | return true; 75 | } 76 | } 77 | } 78 | 79 | 80 | return false; 81 | } 82 | 83 | private static Decision MakeDecisionFromRules(Executable exe) 84 | { 85 | Decision decision = Decision.ALLOW; 86 | 87 | var sessionFactory = Database.getSessionFactory(); 88 | using (var session = sessionFactory.OpenSession()) 89 | { 90 | var rules = session.QueryOver() 91 | .Where(e => e.Enabled == true) 92 | .OrderBy(e => e.Rank).Asc 93 | .List(); 94 | foreach (var rule in rules) 95 | { 96 | bool match = true; 97 | foreach (var attr in rule.Attrs) 98 | { 99 | match = match & ExeMatchesAttribute(attr, exe); 100 | } 101 | if (match) 102 | { 103 | if (rule.Allow) 104 | { 105 | decision = Decision.ALLOW; 106 | } 107 | else 108 | { 109 | decision = Decision.DENY; 110 | } 111 | } 112 | } 113 | } 114 | 115 | return decision; 116 | } 117 | 118 | private static Decision FinalDecisionBasedOnMode(Decision decision) 119 | { 120 | // TODO MUST set audit mode to false so we can be locked down 121 | bool AuditMode = true; 122 | if (AuditMode) 123 | { 124 | return Decision.ALLOW; 125 | } 126 | else 127 | { 128 | return decision; 129 | } 130 | } 131 | 132 | /// 133 | /// This function is called when a new process is being started. It return the decision if the process should be allowed to run. 134 | /// It stores some data in the DB about this executable (such as the computed hashes). 135 | /// 136 | /// 137 | /// Database ID for the executable 138 | /// Decision on if the process should be allowed to run 139 | public static Decision DecideOnProcess(string filePath, out long ExecutableId) 140 | { 141 | Log.Info("Arbiter deciding on process"); 142 | Decision decision = Decision.ALLOW; 143 | List signers = null; 144 | ExecutableId = 0; // TODO Must do something where there is an error in this function so we don't record that something with ExecutableID 0 happened 145 | 146 | try 147 | { 148 | filePath = CleanPath(filePath); 149 | Log.Info("Deciding on process: {0}", filePath); 150 | 151 | // 152 | // Check if we've seen this before 153 | // 154 | DateTime lastWriteTime = File.GetLastWriteTime(filePath); 155 | lastWriteTime = lastWriteTime.ToUniversalTime(); 156 | 157 | var sessionFactory = Database.getSessionFactory(); 158 | using (var session = sessionFactory.OpenSession()) 159 | { 160 | var exes = session.QueryOver() 161 | .Where(e => e.Path == filePath) 162 | .And(e =>e.LastWriteTime == lastWriteTime) 163 | .List(); 164 | if (exes.Count() != 0) 165 | { 166 | Executable foundExe = exes[0]; 167 | Log.Debug("Exe has been seen before"); 168 | ExecutableId = foundExe.Id; 169 | // TODO need to use a rule engine 170 | if (!foundExe.Trusted) 171 | { 172 | Log.Info("Deny it"); 173 | decision = Decision.DENY; 174 | } 175 | else 176 | { 177 | Log.Info("Allow it"); 178 | } 179 | return decision; 180 | } 181 | } 182 | 183 | 184 | // 185 | // If we're here then this is new, so verify it 186 | // 187 | bool isVerified = WinTrustVerify.WinTrust.Verify(filePath, out signers); 188 | string SignerName = ""; 189 | if (isVerified) 190 | { 191 | if (signers != null && signers.Count >= 1 && signers[0] != null) 192 | { 193 | SignerName = signers[0].Name; 194 | } 195 | Log.Info("File is signed by {0}", SignerName); 196 | } 197 | else 198 | { 199 | Log.Info("File is not signed (or not trusted)"); 200 | } 201 | 202 | // Compute hashes 203 | byte[] md5Hash, sha1Hash, sha256Hash; 204 | Helpers.ComputeHashes(filePath, out md5Hash, out sha1Hash, out sha256Hash); 205 | 206 | 207 | // Gather all this data 208 | var exe = new Executable 209 | { 210 | Path = filePath, 211 | LastWriteTime = lastWriteTime, 212 | LastSeen = DateTime.UtcNow, 213 | FirstSeen = DateTime.UtcNow, 214 | LastChecked = DateTime.UtcNow, 215 | Signed = (signers != null), 216 | Blocked = false, // TODO Change this based on if we are in audit mode 217 | Md5 = md5Hash, 218 | Sha1 = sha1Hash, 219 | Sha256 = sha256Hash, 220 | }; 221 | 222 | 223 | // 224 | // Record this info to the DB 225 | // 226 | using (var session = sessionFactory.OpenSession()) 227 | { 228 | using (var transaction = session.BeginTransaction()) 229 | { 230 | // I don't really need to check again, but I'm worried about a race 231 | var exes = session.QueryOver() 232 | .Where(e => e.Path == filePath) 233 | .And(e => e.LastWriteTime == lastWriteTime) 234 | .List(); 235 | if (exes.Count() == 0) 236 | { 237 | // Ensure we don't add certs to the DB if they already exist there 238 | if (signers != null) 239 | { 240 | foreach (var signer in signers) 241 | { 242 | var certs = session.QueryOver() 243 | .Where(e => e.SerialNumber == signer.SigningCert.SerialNumber) 244 | .And(e => e.Issuer == signer.SigningCert.Issuer) 245 | .List(); 246 | if (certs.Count() != 0) 247 | { 248 | signer.SigningCert = certs[0]; 249 | break; 250 | } 251 | } 252 | 253 | Database.AddSignersToExe(exe, signers); 254 | } 255 | 256 | // 257 | // Make a decision on it 258 | // 259 | decision = MakeDecisionFromRules(exe); 260 | exe.Trusted = (decision == Decision.ALLOW); 261 | 262 | session.Save(exe); 263 | transaction.Commit(); 264 | 265 | ExecutableId = exe.Id; 266 | } 267 | } 268 | } 269 | } 270 | catch (Exception e) 271 | { 272 | Log.Exception(e, "Exception in DecideOnProcess"); 273 | } 274 | 275 | return FinalDecisionBasedOnMode(decision); 276 | } 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /src/srsvc/Commands/GetCatalogByHash.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | public partial class Command 26 | { 27 | public static dynamic GetCatalogFileByHash(dynamic serverMsg) 28 | { 29 | dynamic response = null; 30 | 31 | string sha256 = serverMsg.Arguments.Sha256; 32 | Log.Info("Command GetCatalogFileByHash: Hash {0}", sha256); 33 | 34 | var sessionFactory = Database.getSessionFactory(); 35 | using (var session = sessionFactory.OpenSession()) 36 | { 37 | var catalogs = session.QueryOver() 38 | .Where(e => e.Sha256 == Helpers.HexStringToByteArray(sha256)) 39 | .List(); 40 | if (catalogs.Count() != 0) 41 | { 42 | CatalogFile catalog = catalogs[0]; 43 | Log.Info("Found file {0}", catalog.FilePath); 44 | 45 | response = UploadFile(catalog.Sha256, catalog.FilePath, "catalog"); 46 | } 47 | else 48 | { 49 | // TODO Need to throw error 50 | Log.Error("GetCatalogFileByHash requested unknown hash {0}", sha256); 51 | } 52 | } 53 | 54 | return response; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/srsvc/Commands/GetFileByHash.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | public partial class Command 26 | { 27 | [DataContract] 28 | internal class UploadFilePost : Event.EventPost 29 | { 30 | [DataMember] 31 | internal string Sha256 = ""; 32 | 33 | [DataMember] 34 | internal string FileType = ""; 35 | } 36 | 37 | /// 38 | /// This function is wrapped by other calls in order to upload files 39 | /// 40 | /// 41 | /// 42 | /// 43 | /// 44 | public static dynamic UploadFile(byte[] Sha256ByteArray, string FilePath, string type) 45 | { 46 | UploadFilePost eventPost = new UploadFilePost(); 47 | string sha256HexString = Helpers.ByteArrayToHexString(Sha256ByteArray); 48 | eventPost.Sha256 = sha256HexString; 49 | eventPost.FileType = type; 50 | 51 | string postMessage = Helpers.SerializeToJson(eventPost, typeof(UploadFilePost)); 52 | 53 | // Read file data 54 | // TODO Need to be smarter about avoiding reading the entire file into memory at once 55 | FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read); 56 | byte[] data = new byte[fs.Length]; 57 | fs.Read(data, 0, data.Length); 58 | fs.Close(); 59 | 60 | // Generate post objects 61 | Dictionary postParameters = new Dictionary(); 62 | postParameters.Add("event_data", postMessage); 63 | postParameters.Add("file", new Beacon.FileParameter(data, sha256HexString, "application/octet-stream")); 64 | 65 | string response = Beacon.MultipartFormDataPost("/api/v1/UploadFile", postParameters); 66 | 67 | return Json.Decode(response); 68 | } 69 | 70 | public static dynamic GetFileByHash(dynamic serverMsg) 71 | { 72 | dynamic response = null; 73 | 74 | // Test with: insert into tasks (systemid, creationdate, deployedtoagentdate, command) values (1, 1415308642, 0, '{"Command":"GetFileByHash","Arguments":{"Sha256":"0a8ce026714e03e72c619307bd598add5f9b639cfd91437cb8d9c847bf9f6894"}}'); 75 | string sha256 = serverMsg.Arguments.Sha256; 76 | Log.Info("Command GetFileByHash: Hash {0}", sha256); 77 | 78 | var sessionFactory = Database.getSessionFactory(); 79 | using (var session = sessionFactory.OpenSession()) 80 | { 81 | var exes = session.QueryOver() 82 | .Where(e => e.Sha256 == Helpers.HexStringToByteArray(sha256)) 83 | .List(); 84 | if (exes.Count() != 0) 85 | { 86 | Executable exe = exes[0]; 87 | Log.Info("Found file {0}", exe.Path); 88 | 89 | response = UploadFile(exe.Sha256, exe.Path, "exe"); 90 | } 91 | else 92 | { 93 | // TODO Need to throw error 94 | Log.Error("GetFileByHash requested unknown hash: {0}", sha256); 95 | } 96 | } 97 | 98 | return response; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/srsvc/Commands/NOP.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | public partial class Command 26 | { 27 | /// 28 | /// Do nothing 29 | /// 30 | /// 31 | /// 32 | public static dynamic NOP(dynamic serverMsg) 33 | { 34 | Log.Info("Command NOP"); 35 | 36 | return null; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/srsvc/Commands/SetSystemUUID.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | public partial class Command 26 | { 27 | /// 28 | /// Set the SystemUUID. Normally only set during registration, but just in case the user clones a VM, we'll allow this to be changed 29 | /// 30 | /// 31 | /// 32 | public static dynamic SetSystemUUID(dynamic serverMsg) 33 | { 34 | string newSystemUUID = serverMsg.Arguments.SystemUUID; 35 | Log.Info("Command SetSystemUUID setting UUID to: {0}", newSystemUUID); 36 | SRSvc.conf.SystemUUID = newSystemUUID; 37 | 38 | return null; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/srsvc/Commands/Stall.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | public partial class Command 26 | { 27 | /// 28 | /// Delay so we don't try contacting the server again for a while 29 | /// 30 | /// 31 | /// 32 | public static dynamic Stall(dynamic serverMsg) 33 | { 34 | Log.Info("Command Stall"); 35 | 36 | int Delay = serverMsg.Arguments.DelayInSeconds; 37 | 38 | // Sanity check, don't allow us to delay for less than 5 minutes 39 | if (Delay < 60 * 5) 40 | { 41 | Delay = 60 * 5; 42 | } 43 | 44 | System.Threading.Thread.Sleep(Delay * 1000); 45 | 46 | return null; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/srsvc/Commands/Update.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | using System.Diagnostics; 17 | 18 | using System.Runtime.Serialization; 19 | using System.Runtime.Serialization.Json; 20 | 21 | using System.Web.Helpers; 22 | using Microsoft.CSharp.RuntimeBinder; 23 | 24 | namespace srsvc 25 | { 26 | public partial class Command 27 | { 28 | 29 | [DataContract] 30 | internal class GetUpdatePost : Event.EventPost 31 | { 32 | [DataMember] 33 | internal string Version = ""; 34 | 35 | public GetUpdatePost(string CurrentVersion) 36 | { 37 | Version = CurrentVersion; 38 | } 39 | } 40 | 41 | 42 | 43 | /// 44 | /// Update this agent 45 | /// 46 | /// Ignored, but provides what the new version will be 47 | /// 48 | public static dynamic Update(dynamic serverMsg) 49 | { 50 | // Tell the server what version we currently have and it will return an exe that will update this agent to the next version 51 | GetUpdatePost getUpdatePost = new GetUpdatePost(SRSvc.conf.Version); 52 | 53 | string postMessage = Helpers.SerializeToJson(getUpdatePost, typeof(GetUpdatePost)); 54 | byte[] filedata = Beacon.PostForm(Encoding.UTF8.GetBytes(postMessage), "/api/v1/GetUpdate", "text/json"); 55 | 56 | //string updateName = String.Format("srepp_update-{0}.exe", SRSvc.conf.Version); 57 | string updateFilePath = Path.GetTempFileName(); 58 | try 59 | { 60 | using (FileStream fs = File.Create(updateFilePath)) 61 | { 62 | using (System.IO.BinaryWriter file = new System.IO.BinaryWriter(fs)) 63 | { 64 | file.Write(filedata); 65 | } 66 | } 67 | 68 | Log.Info("Update file written to: {0}", updateFilePath); 69 | 70 | // Check it 71 | List signers = null; 72 | bool isVerified = WinTrustVerify.WinTrust.Verify(updateFilePath, out signers); 73 | if (!isVerified) 74 | { 75 | Log.Error("Update file could not be verified"); 76 | return null; 77 | } 78 | 79 | // File is signed and can be verified, but make sure it's signed by me 80 | string SignerName = ""; 81 | byte[] SerialNumber = null; 82 | if (signers != null && signers.Count >= 1 && signers[0] != null) 83 | { 84 | SignerName = signers[0].Name; 85 | SerialNumber = signers[0].SigningCert.SerialNumber; 86 | } 87 | else 88 | { 89 | Log.Error("Could not extract signer info from file"); 90 | return null; 91 | } 92 | 93 | bool isSignedByMe = false; 94 | // TODO Should also check the chain (the root) and some other info, in case a rogue CA granted someone a cert with my info 95 | 96 | #if DEBUG 97 | byte[] TestSerialNumber = new byte[] { 0x4c, 0x18, 0xd9, 0xaa, 0x26, 0x83, 0x36, 0x95, 0x4c, 0xc4, 0x35, 0x6d, 0xaa, 0xbe, 0x82, 0xc9 }; 98 | if (SignerName == "SR_Test" && Helpers.ByteArrayAreEqual(SerialNumber, TestSerialNumber)) 99 | { 100 | isSignedByMe = true; 101 | } 102 | #endif 103 | 104 | // TODO MUST Check Relase build requirements 105 | byte[] ReleaseSerialNumber = new byte[] { 0x4c, 0x18, 0xd9, 0xaa, 0x26, 0x83, 0x36, 0x95, 0x4c, 0xc4, 0x35, 0x6d, 0xaa, 0xbe, 0x82, 0xc9 }; 106 | if (SignerName == "SR_Test" && Helpers.ByteArrayAreEqual(SerialNumber, ReleaseSerialNumber)) 107 | { 108 | isSignedByMe = true; 109 | } 110 | 111 | if (!isSignedByMe) 112 | { 113 | Log.Error("Update file was not signed by the correct issuer! Bailing on update. Was signed by {0}, with serial number {1}", SignerName, Helpers.ByteArrayToHexString(SerialNumber)); 114 | return null; 115 | } 116 | 117 | // TODO Check the new file is a greater version than this file, or at least the date the file was signed is more recent 118 | 119 | // Execute it 120 | Process myProcess = new Process(); 121 | try 122 | { 123 | myProcess.StartInfo.UseShellExecute = false; 124 | myProcess.StartInfo.FileName = updateFilePath; 125 | myProcess.StartInfo.CreateNoWindow = true; 126 | myProcess.Start(); 127 | 128 | // TODO Should I kill this parent process so the child isn't trying kill it? 129 | } 130 | catch (Exception e) 131 | { 132 | Console.WriteLine(e.Message); 133 | } 134 | } 135 | finally 136 | { 137 | // Delete file, especially in case of errors. In theory an update should occcur. 138 | File.Delete(updateFilePath); 139 | } 140 | 141 | return null; 142 | } 143 | 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/srsvc/CommunicateWithUI.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.ServiceModel; 12 | using System.Collections.Generic; 13 | using System.Collections.Concurrent; 14 | 15 | namespace MessagingInterfaces 16 | { 17 | public class ClientPipes 18 | { 19 | public static ConcurrentDictionary callbackList = new ConcurrentDictionary(); 20 | } 21 | 22 | public interface IMessageServiceCallback 23 | { 24 | [OperationContract(IsOneWay = true)] 25 | void NotifyMsg(string msg); 26 | } 27 | 28 | [ServiceContract(CallbackContract = typeof(IMessageServiceCallback))] 29 | public interface IClientToServer 30 | { 31 | [OperationContract] 32 | void RegisterClient(string guid); 33 | } 34 | 35 | public class ClientRegistrar : IClientToServer 36 | { 37 | public void RegisterClient(string guid) 38 | { 39 | srsvc.Log.Info("Registering: {0}", guid); 40 | 41 | IMessageServiceCallback registeredUser = 42 | OperationContext.Current.GetCallbackChannel(); 43 | 44 | ClientPipes.callbackList.AddOrUpdate(guid, registeredUser, (i, v) => registeredUser); 45 | } 46 | } 47 | 48 | public class CommunicateWithUI 49 | { 50 | private ServiceHost host; 51 | 52 | /// 53 | /// Initialize our server, allows for clients to register themselves 54 | /// 55 | public CommunicateWithUI() 56 | { 57 | host = new ServiceHost( 58 | typeof(ClientRegistrar), 59 | new Uri[] { new Uri("net.pipe://localhost") } 60 | ); 61 | 62 | host.AddServiceEndpoint( 63 | typeof(IClientToServer), 64 | new NetNamedPipeBinding(), 65 | "SREPP_regc"); 66 | host.Open(); 67 | } 68 | 69 | ~CommunicateWithUI() 70 | { 71 | host.Close(); 72 | } 73 | 74 | 75 | /// 76 | /// Sends message to every client that has registered itself 77 | /// 78 | /// 79 | public void InformUI(string msg) 80 | { 81 | srsvc.Log.Info("SVC: InformUI"); 82 | List removalList = new List(); 83 | 84 | // Contact each client and if any can't be contacted, then remove them from our list 85 | foreach (string guid in ClientPipes.callbackList.Keys) 86 | { 87 | try 88 | { 89 | ClientPipes.callbackList[guid].NotifyMsg(msg); 90 | } 91 | catch (Exception e) 92 | { 93 | // Problem with client, so removing it 94 | srsvc.Log.Exception(e, "Exception sending to client"); 95 | removalList.Add(guid); 96 | } 97 | } 98 | 99 | // Clear out bad clients 100 | foreach (string guid in removalList) 101 | { 102 | IMessageServiceCallback ignore; 103 | ClientPipes.callbackList.TryRemove(guid, out ignore); 104 | } 105 | removalList.Clear(); 106 | } 107 | } 108 | 109 | public static class UIComm 110 | { 111 | public static CommunicateWithUI uiComm = null; 112 | 113 | public static void Init() 114 | { 115 | uiComm = new CommunicateWithUI(); 116 | } 117 | 118 | public static void InformUI(string msg) 119 | { 120 | uiComm.InformUI(msg); 121 | } 122 | 123 | } 124 | } -------------------------------------------------------------------------------- /src/srsvc/Events/Catalogfile.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Runtime.Serialization; 15 | 16 | namespace srsvc 17 | { 18 | partial class Event 19 | { 20 | 21 | [DataContract] 22 | internal class CatalogFilePost : EventPost 23 | { 24 | [DataMember] 25 | internal Int64 TimeOfEvent = 0; 26 | 27 | [DataMember] 28 | internal string Path = ""; 29 | 30 | [DataMember] 31 | internal string Sha256 = ""; 32 | 33 | [DataMember] 34 | internal Int32 Size = 0; 35 | } 36 | 37 | 38 | /// 39 | /// Response after sending a catalog file info 40 | /// 41 | [DataContract] 42 | internal class CatalogFileResponse 43 | { 44 | // nop 45 | } 46 | 47 | 48 | public static bool PostCatalogFile(CatalogFile catalogFile) 49 | { 50 | CatalogFilePost catalogFilePost = new CatalogFilePost(); 51 | catalogFilePost.TimeOfEvent = Helpers.ConvertToUnixTime(catalogFile.FirstAccessTime); 52 | catalogFilePost.Path = catalogFile.FilePath; 53 | catalogFilePost.Size = catalogFile.Size; 54 | catalogFilePost.Sha256 = Helpers.ByteArrayToHexString(catalogFile.Sha256); 55 | 56 | string postMessage = Helpers.SerializeToJson(catalogFilePost, typeof(CatalogFilePost)); 57 | string response = Beacon.PostToServer(postMessage, "/api/v1/CatalogFileEvent"); 58 | if (response == "") 59 | { 60 | // Remote server could not be reached or encountered an error 61 | return false; 62 | } 63 | CatalogFileResponse processEventResponse = (CatalogFileResponse)Helpers.DeserializeFromJson(response, typeof(CatalogFileResponse)); 64 | 65 | return true; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/srsvc/Events/Events.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | namespace srsvc 24 | { 25 | partial class Event 26 | { 27 | 28 | /// 29 | /// Base class for events posted to the server. All messages from the client to the server should contain at least this info 30 | /// 31 | [DataContract] 32 | internal class EventPost 33 | { 34 | [DataMember] 35 | internal string SystemUUID = ""; 36 | 37 | [DataMember] 38 | internal string CustomerUUID = ""; 39 | 40 | [DataMember] 41 | internal Int64 CurrentClientTime = 0; 42 | 43 | public EventPost() 44 | { 45 | SystemUUID = SRSvc.conf.SystemUUID; 46 | CustomerUUID = SRSvc.conf.GroupUUID; 47 | CurrentClientTime = Helpers.ConvertToUnixTime(DateTime.UtcNow); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/srsvc/Events/Heartbeat.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | 17 | using System.Runtime.Serialization; 18 | using System.Runtime.Serialization.Json; 19 | 20 | using System.Web.Helpers; 21 | using Microsoft.CSharp.RuntimeBinder; 22 | 23 | 24 | namespace srsvc 25 | { 26 | partial class Event 27 | { 28 | 29 | [DataContract] 30 | internal class HeartbeatEventPost : EventPost 31 | { 32 | // Nothing new 33 | } 34 | 35 | /// 36 | /// Posts a heartbeat to the server, just letting it know we're alive and giving the server a chance to task it 37 | /// 38 | /// 39 | public static dynamic PostHeartbeatEvent() 40 | { 41 | HeartbeatEventPost eventPost = new HeartbeatEventPost(); 42 | 43 | string postMessage = Helpers.SerializeToJson(eventPost, typeof(HeartbeatEventPost)); 44 | string response = Beacon.PostToServer(postMessage, "/api/v1/Heartbeat"); 45 | 46 | return Json.Decode(response); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/srsvc/Events/ProcessEvent.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Runtime.Serialization; 15 | 16 | namespace srsvc 17 | { 18 | partial class Event 19 | { 20 | /// 21 | /// Data sent to the server when a new process is created 22 | /// 23 | [DataContract] 24 | internal class ProcessEventPost : EventPost 25 | { 26 | [DataMember] 27 | internal Int64 TimeOfEvent = 0; 28 | 29 | [DataMember] 30 | internal Int32 Type = 0; 31 | 32 | [DataMember] 33 | internal Int64 PID = 0; 34 | 35 | [DataMember] 36 | internal Int64 PPID = 0; 37 | 38 | [DataMember] 39 | internal string Path = ""; 40 | 41 | [DataMember] 42 | internal string CommandLine = ""; 43 | 44 | [DataMember] 45 | internal string Md5 = ""; 46 | 47 | [DataMember] 48 | internal string Sha1 = ""; 49 | 50 | [DataMember] 51 | internal string Sha256 = ""; 52 | 53 | [DataMember] 54 | internal Int32 Size = 0; 55 | 56 | [DataMember] 57 | internal bool IsSigned = false; 58 | } 59 | 60 | /// 61 | /// Response after sending a process event 62 | /// 63 | [DataContract] 64 | internal class ProcessEventResponse 65 | { 66 | // nop 67 | } 68 | 69 | 70 | /// 71 | /// Sends info about a process event to the server, returns true on having successful informed the server 72 | /// 73 | /// 74 | /// 75 | public static bool PostProcessEvent(ProcessEvent processEvent, Executable executable) 76 | { 77 | ProcessEventPost processEventPost = new ProcessEventPost(); 78 | processEventPost.TimeOfEvent = Helpers.ConvertToUnixTime(processEvent.EventTime); 79 | processEventPost.Type = (Int32)processEvent.State; 80 | processEventPost.PID = processEvent.Pid; 81 | processEventPost.PPID = processEvent.Ppid; 82 | processEventPost.Path = executable.Path; 83 | processEventPost.CommandLine = processEvent.CommandLine; 84 | processEventPost.Md5 = Helpers.ByteArrayToHexString(executable.Md5); 85 | processEventPost.Sha1 = Helpers.ByteArrayToHexString(executable.Sha1); 86 | processEventPost.Sha256 = Helpers.ByteArrayToHexString(executable.Sha256); 87 | processEventPost.Size = (int)(new System.IO.FileInfo(executable.Path).Length); 88 | processEventPost.IsSigned = executable.Signed; 89 | 90 | string postMessage = Helpers.SerializeToJson(processEventPost, typeof(ProcessEventPost)); 91 | string response = Beacon.PostToServer(postMessage, "/api/v1/ProcessEvent"); 92 | if (response == "") 93 | { 94 | // Remote server could not be reached or encountered an error 95 | return false; 96 | } 97 | ProcessEventResponse processEventResponse = (ProcessEventResponse)Helpers.DeserializeFromJson(response, typeof(ProcessEventResponse)); 98 | 99 | return true; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/srsvc/Events/Register.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Runtime.Serialization; 15 | using System.Management; 16 | using System.Web.Helpers; 17 | 18 | namespace srsvc 19 | { 20 | partial class Event 21 | { 22 | 23 | /// 24 | /// Data to send to the server when registering. Tells the server about this client and this is used to request a system UUID 25 | /// 26 | [DataContract] 27 | internal class RegistrationEventPost 28 | { 29 | [DataMember] 30 | internal string CustomerUUID; 31 | 32 | [DataMember] 33 | internal string AgentVersion; 34 | 35 | [DataMember] 36 | internal string OSHumanName; 37 | 38 | [DataMember] 39 | internal string OSVersion; 40 | 41 | [DataMember] 42 | internal string Manufacturer; 43 | 44 | [DataMember] 45 | internal string Model; 46 | 47 | [DataMember] 48 | internal string Arch; 49 | 50 | [DataMember] 51 | internal string MachineName; 52 | 53 | [DataMember] 54 | internal string MachineGUID; 55 | } 56 | 57 | /// 58 | /// Retrieves the OS name as something like "Microsoft Windows 7 Enterprise" 59 | /// 60 | /// 61 | private static string GetOSFriendlyName() 62 | { 63 | string result = string.Empty; 64 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem"); 65 | foreach (ManagementObject os in searcher.Get()) 66 | { 67 | result = os["Caption"].ToString(); 68 | break; 69 | } 70 | return result.Trim(); 71 | } 72 | 73 | /// 74 | /// Gets the value from HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography 75 | /// 76 | /// 77 | private static string GetWindowsMachineGUID() 78 | { 79 | string result = string.Empty; 80 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_OperatingSystem"); 81 | foreach (ManagementObject os in searcher.Get()) 82 | { 83 | result = os["SerialNumber"].ToString(); 84 | break; 85 | } 86 | return result.Trim(); 87 | } 88 | 89 | 90 | private struct ManufacturerData 91 | { 92 | public string Manufacturer; 93 | public string Model; 94 | } 95 | 96 | private static ManufacturerData GetManufacturerData() 97 | { 98 | ManufacturerData md = new ManufacturerData(); 99 | 100 | // create management class object 101 | ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); 102 | //collection to store all management objects 103 | ManagementObjectCollection moc = mc.GetInstances(); 104 | if (moc.Count != 0) 105 | { 106 | foreach (ManagementObject mo in mc.GetInstances()) 107 | { 108 | // display general system information 109 | md.Manufacturer = mo["Manufacturer"].ToString(); 110 | md.Model = mo["Model"].ToString(); 111 | break; 112 | } 113 | } 114 | return md; 115 | } 116 | 117 | 118 | /// 119 | /// Register this agent with the server. Receives new System UUID. 120 | /// 121 | /// True when we've received a new System UUID 122 | public static bool RegisterWithServer() 123 | { 124 | Log.Info("Registering with the server"); 125 | 126 | // Register yourself in order to get a System GUID 127 | RegistrationEventPost registration = new RegistrationEventPost(); 128 | registration.CustomerUUID = SRSvc.conf.GroupUUID; 129 | registration.AgentVersion = SRSvc.conf.Version; 130 | 131 | registration.OSHumanName = GetOSFriendlyName(); 132 | registration.OSVersion = Environment.OSVersion.ToString(); 133 | registration.Arch = (Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit"); 134 | registration.MachineName = Environment.MachineName; 135 | 136 | ManufacturerData md = GetManufacturerData(); 137 | registration.Manufacturer = md.Manufacturer; 138 | registration.Model = md.Model; 139 | registration.MachineGUID = GetWindowsMachineGUID(); 140 | 141 | string postMessage = Helpers.SerializeToJson(registration, typeof(RegistrationEventPost)); 142 | 143 | string response = Beacon.PostToServer(postMessage, "/api/v1/Register"); 144 | if (response == "") 145 | { 146 | // Likely we were unable to contact the server 147 | return false; 148 | } 149 | 150 | dynamic serverMsg = Json.Decode(response); 151 | 152 | if (serverMsg.Command == "SetSystemUUID") 153 | { 154 | Command.SetSystemUUID(serverMsg); 155 | } 156 | else 157 | { 158 | throw new Exception("Registration response command not in correct format"); 159 | } 160 | 161 | return true; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/srsvc/Helpers.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Net; 15 | using System.IO; 16 | using System.Runtime.Serialization; 17 | using System.Runtime.Serialization.Json; 18 | using System.Security.Cryptography; 19 | 20 | namespace srsvc 21 | { 22 | class Helpers 23 | { 24 | /// 25 | /// Given a hex string, converts it to a byte array (ex. "4142" -> 0x41, 0x42) 26 | /// 27 | /// 28 | /// 29 | public static byte[] HexStringToByteArray(string hexString) 30 | { 31 | byte[] HexAsBytes = new byte[hexString.Length / 2]; 32 | for (int index = 0; index < HexAsBytes.Length; index++) 33 | { 34 | string byteValue = hexString.Substring(index * 2, 2); 35 | HexAsBytes[index] = byte.Parse(byteValue, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture); 36 | } 37 | return HexAsBytes; 38 | } 39 | 40 | /// 41 | /// Given a byte array, converts it to a hex string 42 | /// 43 | /// 44 | /// 45 | public static string ByteArrayToHexString(byte[] ba) 46 | { 47 | StringBuilder hex = new StringBuilder(ba.Length * 2); 48 | foreach (byte b in ba) 49 | hex.AppendFormat("{0:x2}", b); 50 | return hex.ToString(); 51 | } 52 | 53 | /// 54 | /// Given a file path, compute the file hashes. 55 | /// 56 | /// 57 | /// 58 | /// 59 | /// 60 | public static void ComputeHashes(string filePath, out byte[] md5Hash, out byte[] sha1Hash, out byte[] sha256Hash) 61 | { 62 | using (var md5 = MD5Cng.Create()) 63 | using (var sha1 = SHA1Cng.Create()) 64 | using (var sha256 = SHA256Cng.Create()) 65 | using (var input = File.OpenRead(filePath)) 66 | { 67 | byte[] buffer = new byte[8192]; 68 | int bytesRead; 69 | while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0) 70 | { 71 | md5.TransformBlock(buffer, 0, bytesRead, buffer, 0); 72 | sha1.TransformBlock(buffer, 0, bytesRead, buffer, 0); 73 | sha256.TransformBlock(buffer, 0, bytesRead, buffer, 0); 74 | } 75 | // We have to call TransformFinalBlock, but we don't have any 76 | // more data - just provide 0 bytes. 77 | md5.TransformFinalBlock(buffer, 0, 0); 78 | sha1.TransformFinalBlock(buffer, 0, 0); 79 | sha256.TransformFinalBlock(buffer, 0, 0); 80 | 81 | md5Hash = md5.Hash; 82 | sha1Hash = sha1.Hash; 83 | sha256Hash = sha256.Hash; 84 | } 85 | } 86 | 87 | /// 88 | /// Given a DateTime, converts it to seconds since the epoch 89 | /// 90 | /// 91 | /// 92 | public static Int32 ConvertToUnixTime(DateTime dt) 93 | { 94 | return (Int32)(dt.Subtract(new DateTime(1970, 1, 1).ToUniversalTime())).TotalSeconds; 95 | } 96 | 97 | /// 98 | /// Generates a stream object from the string, for JSON conversions 99 | /// 100 | /// 101 | /// 102 | public static Stream GenerateStreamFromString(string s) 103 | { 104 | MemoryStream stream = new MemoryStream(); 105 | StreamWriter writer = new StreamWriter(stream); 106 | writer.Write(s); 107 | writer.Flush(); 108 | stream.Position = 0; 109 | return stream; 110 | } 111 | 112 | /// 113 | /// Converts the object of the given type to a JSON string 114 | /// 115 | /// 116 | /// 117 | /// 118 | public static string SerializeToJson(object o, System.Type type) 119 | { 120 | MemoryStream memoryStream = new MemoryStream(); 121 | DataContractJsonSerializer ser = new DataContractJsonSerializer(type); 122 | ser.WriteObject(memoryStream, o); 123 | 124 | memoryStream.Position = 0; 125 | StreamReader sr = new StreamReader(memoryStream); 126 | return sr.ReadToEnd(); 127 | } 128 | 129 | /// 130 | /// Converts the JSON string to an object of the given type 131 | /// 132 | /// 133 | /// 134 | /// 135 | public static object DeserializeFromJson(string json, System.Type type) 136 | { 137 | object obj = Activator.CreateInstance(type); 138 | 139 | using (Stream s = GenerateStreamFromString(json)) 140 | { 141 | DataContractJsonSerializer ser = new DataContractJsonSerializer(type); 142 | obj = ser.ReadObject(s); 143 | } 144 | 145 | return obj; 146 | } 147 | 148 | 149 | /// 150 | /// Prints the hex bytes for a long string to logger output as INFO 151 | /// 152 | /// 153 | /// 154 | public static byte[] PrintBytes(string str) 155 | { 156 | byte[] bytes = new byte[str.Length * sizeof(char)]; 157 | System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); 158 | string line = ""; 159 | Log.Info(str); 160 | for (int i = 0; i < bytes.Length; i++) 161 | { 162 | line += String.Format("{0:X2} ", bytes[i]); 163 | if (i == 0) 164 | { 165 | // nop 166 | } 167 | else if ((i + 1) % 16 == 0) 168 | { 169 | Log.Info(line); 170 | line = ""; 171 | } 172 | else if ((i + 1) % 8 == 0) 173 | { 174 | line += " "; 175 | } 176 | } 177 | Log.Info(line); 178 | return bytes; 179 | } 180 | 181 | 182 | /// 183 | /// Search through byte array haystack for the needle and return it's index 184 | /// 185 | /// 186 | /// 187 | /// 188 | public static int Locate(byte[] haystack, byte[] needle) 189 | { 190 | int matchLocation = -1; 191 | for (int i = 0; i < haystack.Length - needle.Length; i++) 192 | { 193 | matchLocation = i; 194 | for (int j = 0; j < needle.Length; j++) 195 | { 196 | if (haystack[i + j] != needle[j]) 197 | { 198 | matchLocation = -1; 199 | break; 200 | } 201 | } 202 | if (matchLocation != -1) return matchLocation; 203 | } 204 | 205 | return -1; 206 | } 207 | 208 | 209 | /// 210 | /// Returns true if the byte arrays are equal 211 | /// 212 | /// 213 | /// 214 | /// 215 | public static bool ByteArrayAreEqual(byte[] a1, byte[] a2) 216 | { 217 | if (a1.Length != a2.Length) 218 | return false; 219 | 220 | for (int i = 0; i < a1.Length; i++) 221 | if (a1[i] != a2[i]) 222 | return false; 223 | 224 | return true; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/srsvc/Log.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Diagnostics; 15 | 16 | namespace srsvc 17 | { 18 | class Log 19 | { 20 | enum Level { DEBUG, INFO, WARN, ERROR, CRITICAL }; 21 | static string[] LevelName = new string[] { "DEBUG", "INFO", "WARN", "ERROR", "CRIT" }; 22 | const string APP_NAME = "SRSVC"; 23 | 24 | public static void Debug(string format, params object[] args) 25 | { 26 | LogMessage((int)Level.DEBUG, format, args); 27 | } 28 | 29 | public static void Info(string format, params object[] args) 30 | { 31 | LogMessage((int)Level.INFO, format, args); 32 | } 33 | 34 | public static void Warn(string format, params object[] args) 35 | { 36 | LogMessage((int)Level.WARN, format, args); 37 | } 38 | 39 | public static void Error(string format, params object[] args) 40 | { 41 | LogMessage((int)Level.ERROR, format, args); 42 | } 43 | 44 | public static void Exception(Exception e, string format, params object[] args) 45 | { 46 | LogMessage((int)Level.ERROR, String.Format("{0}: {1}", String.Format(format, args), e.ToString()), null); 47 | } 48 | 49 | public static void Critical(string format, params object[] args) 50 | { 51 | LogMessage((int)Level.CRITICAL, format, args); 52 | } 53 | 54 | private static void LogMessage(int level, string format, params object[] args) 55 | { 56 | System.Diagnostics.Debug.WriteLine(String.Format("[{0} ({1})] {2}", LevelName[level], APP_NAME, String.Format(format, args))); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/srsvc/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("Summit Route EPP Service")] 9 | [assembly: AssemblyDescription("Monitors for and blocks unwanted executables")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Summit Route")] 12 | [assembly: AssemblyProduct("Summit Route EPP")] 13 | [assembly: AssemblyCopyright("Copyright Summit Route LLC")] 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("868a653f-e232-447a-89ad-a0abe2580513")] 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 | [assembly: AssemblyVersion("0.0.0.1")] 33 | [assembly: AssemblyFileVersion("0.0.0.1")] 34 | -------------------------------------------------------------------------------- /src/srsvc/WindowsService.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Text; 13 | using System.ServiceProcess; 14 | using System.Threading; 15 | using System.IO; 16 | using Microsoft.Win32; 17 | using System.Reflection; 18 | 19 | namespace srsvc 20 | { 21 | [System.ComponentModel.DesignerCategory("")] 22 | class WindowsService : ServiceBase 23 | { 24 | public bool bRunning = true; 25 | static SRSvc srSvc = new SRSvc(); 26 | static Thread srSvcThread = null; 27 | 28 | /// 29 | /// Stop the spawned threads so this can exit 30 | /// 31 | private void StopService() 32 | { 33 | bRunning = false; 34 | srSvc.Stop(); 35 | // Wait for thread to stop 36 | while (srSvcThread.IsAlive); 37 | } 38 | 39 | /// 40 | /// Initialize the service (called after Main) 41 | /// 42 | public WindowsService() 43 | { 44 | Log.Info("Running WindowsService class"); 45 | 46 | this.ServiceName = "SREPP"; 47 | this.EventLog.Log = "Application"; 48 | 49 | // These Flags set whether or not to handle that specific 50 | // type of event. Set to true if you need it, false otherwise. 51 | this.CanHandlePowerEvent = false; 52 | this.CanHandleSessionChangeEvent = true; 53 | this.CanPauseAndContinue = true; 54 | this.CanShutdown = true; 55 | this.CanStop = true; 56 | } 57 | 58 | /// 59 | /// First code called when the service starts 60 | /// 61 | static void Main() 62 | { 63 | Log.Debug("WindowsService.Main Start"); 64 | 65 | // Create a monitoring thread 66 | srSvcThread = new Thread(new ThreadStart(srSvc.Run)); 67 | srSvcThread.Name = "SvcThread"; 68 | srSvcThread.IsBackground = true; 69 | 70 | srSvcThread.Start(); 71 | // Spin until the thread starts 72 | while (!srSvcThread.IsAlive); 73 | 74 | // Start service 75 | ServiceBase.Run(new WindowsService()); 76 | } 77 | 78 | /// 79 | /// OnSessionChange 80 | /// 81 | /// 82 | protected override void OnSessionChange( 83 | SessionChangeDescription changeDescription) 84 | { 85 | Log.Info("OnSessionChange event"); 86 | switch (changeDescription.Reason) 87 | { 88 | case SessionChangeReason.SessionLogon: 89 | Log.Info("Session change: New user logged in"); 90 | break; 91 | case SessionChangeReason.RemoteConnect: 92 | Log.Info("Session change: Remote connect"); 93 | break; 94 | case SessionChangeReason.ConsoleConnect: 95 | Log.Info("Session change: Console connect"); 96 | break; 97 | default: 98 | break; 99 | } 100 | 101 | base.OnSessionChange(changeDescription); 102 | } 103 | 104 | /// 105 | /// Dispose of objects that need it here. 106 | /// 107 | /// Whether 108 | /// or not disposing is going on. 109 | protected override void Dispose(bool disposing) 110 | { 111 | Log.Info("SREPP Dispose"); 112 | base.Dispose(disposing); 113 | } 114 | 115 | /// 116 | /// OnStop(): Put your stop code here 117 | /// - Stop threads, set final data, etc. 118 | /// 119 | protected override void OnStop() 120 | { 121 | Log.Info("SREPP Stop"); 122 | StopService(); 123 | base.OnStop(); 124 | } 125 | 126 | 127 | /// 128 | /// OnPause: Put your pause code here 129 | /// - Pause working threads, etc. 130 | /// 131 | protected override void OnPause() 132 | { 133 | Log.Info("SREPP Pause"); 134 | base.OnPause(); 135 | } 136 | 137 | /// 138 | /// OnContinue(): Put your continue code here 139 | /// - Un-pause working threads, etc. 140 | /// 141 | protected override void OnContinue() 142 | { 143 | Log.Info("SREPP Continue"); 144 | base.OnContinue(); 145 | } 146 | 147 | /// 148 | /// OnShutdown(): Called when the System is shutting down 149 | /// - Put code here when you need special handling 150 | /// of code that deals with a system shutdown, such 151 | /// as saving special data before shutdown. 152 | /// 153 | protected override void OnShutdown() 154 | { 155 | Log.Info("SREPP Shutdown"); 156 | StopService(); 157 | base.OnShutdown(); 158 | } 159 | 160 | /// 161 | /// OnCustomCommand(): If you need to send a command to your 162 | /// service without the need for Remoting or Sockets, use 163 | /// this method to do custom methods. 164 | /// 165 | /// Arbitrary Integer between 128 & 256 166 | protected override void OnCustomCommand(int command) 167 | { 168 | // A custom command can be sent to a service by using this method: 169 | //# int command = 128; //Some Arbitrary number between 128 & 256 170 | //# ServiceController sc = new ServiceController("NameOfService"); 171 | //# sc.ExecuteCommand(command); 172 | Log.Info("SREPP Custom Command"); 173 | 174 | base.OnCustomCommand(command); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/srsvc/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/srsvc/srsvc.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Text; 13 | using System.Threading; 14 | using System.Reflection; 15 | using System.IO; 16 | using System.Runtime.InteropServices; 17 | using System.Text.RegularExpressions; 18 | using System.Management; 19 | using System.Diagnostics; 20 | 21 | namespace srsvc 22 | { 23 | /// 24 | /// Communicates with the driver 25 | /// 26 | public class SRSvc 27 | { 28 | static Thread beaconThread = null; 29 | static Beacon beacon = null; 30 | 31 | public static bool bRunning = true; 32 | 33 | public void Stop() 34 | { 35 | bRunning = false; 36 | QdUnInitialize(); 37 | 38 | if (beaconThread != null) 39 | { 40 | beacon.Stop(); 41 | while (beaconThread.IsAlive); 42 | } 43 | } 44 | 45 | public static SystemConfig conf; 46 | 47 | public struct PROCESS_INFO 48 | { 49 | public UInt32 pid; 50 | public UInt32 ppid; 51 | 52 | public string ImageFileName; 53 | public string CommandLine; 54 | 55 | public PROCESS_INFO(COMM_CREATE_PROC comm_Create_Proc) 56 | { 57 | pid = comm_Create_Proc.pid; 58 | ppid = comm_Create_Proc.ppid; 59 | CommandLine = new string(comm_Create_Proc.CommandLineBuf, 0, comm_Create_Proc.CommandLineLength / 2); 60 | ImageFileName = new string(comm_Create_Proc.ImageFileNameBuf, 0, comm_Create_Proc.ImageFileNameLength / 2); 61 | } 62 | 63 | public PROCESS_INFO(Process process) 64 | { 65 | pid = (UInt32)process.Id; 66 | ppid = 0; 67 | CommandLine = ""; 68 | ImageFileName = process.MainModule.FileName; 69 | 70 | string query = String.Format("SELECT CommandLine, ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", pid); 71 | ManagementObjectSearcher searcher = new ManagementObjectSearcher(query); 72 | foreach (ManagementObject proc in searcher.Get()) 73 | { 74 | ppid = (UInt32)proc["ParentProcessId"]; 75 | CommandLine = (string)proc["CommandLine"].ToString(); 76 | break; 77 | } 78 | } 79 | } 80 | 81 | /// 82 | /// Struct passed from driver to userland to tell it what new process was created 83 | /// 84 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 85 | public struct COMM_CREATE_PROC 86 | { 87 | public UInt32 Size; 88 | 89 | // TODO Get bit flags 90 | public UInt32 Flags; 91 | 92 | public UInt32 pid; 93 | public UInt32 ppid; 94 | public UInt32 ptid; 95 | 96 | public UInt16 ImageFileNameLength; 97 | public UInt32 ImageFileNameFullLength; 98 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] 99 | public char[] ImageFileNameBuf; 100 | 101 | public UInt16 CommandLineLength; // Potentially truncated to 1024 102 | public UInt32 CommandLineFullLength; // Full length before truncation 103 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] 104 | public char[] CommandLineBuf; 105 | 106 | public UInt16 ProcIndex; 107 | public UInt16 IntegrityCheck; 108 | } 109 | 110 | // 111 | // srkcomm dll functions 112 | // 113 | 114 | // Initialize the dll 115 | [DllImport("srkcomm.dll")] 116 | [return: MarshalAs(UnmanagedType.Bool)] 117 | public static extern Boolean QdInitialize(); 118 | 119 | [DllImport("srkcomm.dll")] 120 | [return: MarshalAs(UnmanagedType.Bool)] 121 | public static extern Boolean QdUnInitialize(); 122 | 123 | // Installs the kernel driver 124 | [DllImport("srkcomm.dll")] 125 | [return: MarshalAs(UnmanagedType.Bool)] 126 | public static extern Boolean QdInstallDriver(); 127 | 128 | // Uninstalls the driver 129 | [DllImport("srkcomm.dll")] 130 | [return: MarshalAs(UnmanagedType.Bool)] 131 | public static extern Boolean QdUninstallDriver(); 132 | 133 | // Define callback for QdMonitor 134 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 135 | public delegate UInt32 processMonitorCallbackDelegate(ref COMM_CREATE_PROC data); 136 | 137 | // Retrieve info about new processes being created from the driver 138 | [DllImport("srkcomm.dll")] 139 | [return: MarshalAs(UnmanagedType.Bool)] 140 | public static extern Boolean QdMonitor(processMonitorCallbackDelegate cb); 141 | 142 | // Tell the driver to allow or deny a process 143 | [DllImport("srkcomm.dll")] 144 | [return: MarshalAs(UnmanagedType.Bool)] 145 | public static extern Boolean QdControl(UInt16 decision, UInt16 integrityCheck); 146 | 147 | // Global 148 | static processMonitorCallbackDelegate processMonitorCallback; // Ensure it doesn't get garbage collected 149 | 150 | /// 151 | /// Tell the driver to not run the process. Also tell the UI to inform the UI a process was blocked. 152 | /// 153 | /// 154 | /// 155 | /// 156 | public static void CommunicateProcessDecision(Decision d, ref COMM_CREATE_PROC createProc, string filePath) 157 | { 158 | if (d == Decision.DENY) 159 | { 160 | MessagingInterfaces.UIComm.InformUI(string.Format("Stopping process from running: {0}", filePath)); 161 | } 162 | QdControl((UInt16)d, createProc.IntegrityCheck); 163 | } 164 | 165 | /// 166 | /// Callback is called when a new process is created so we can log it and decide to block it. 167 | /// 168 | /// 169 | /// 170 | public static UInt32 ProcessMonitorCallback(ref COMM_CREATE_PROC createProc) 171 | { 172 | try 173 | { 174 | string imageFileName = new string(createProc.ImageFileNameBuf, 0, createProc.ImageFileNameLength/2); 175 | string cmdLine = new string(createProc.CommandLineBuf, 0, createProc.CommandLineLength/2); 176 | 177 | Log.Info("New process: {0}", imageFileName); 178 | Log.Info(" Cmd line: {0}", new string(createProc.CommandLineBuf)); 179 | 180 | long ExecutableId; 181 | 182 | Decision decision = Arbiter.DecideOnProcess(imageFileName, out ExecutableId); 183 | PROCESS_INFO processInfo = new PROCESS_INFO(createProc); 184 | Database.LogProcessEvent(processInfo, ExecutableId, Database.ProcessState.Started); 185 | 186 | CommunicateProcessDecision(decision, ref createProc, imageFileName); 187 | } 188 | catch (Exception e) 189 | { 190 | Log.Exception(e, "Exception in ProcessMonitorCallback"); 191 | } 192 | 193 | return 0; 194 | } 195 | 196 | 197 | /// 198 | /// Connect the kernel driver 199 | /// 200 | public SRSvc() 201 | { 202 | try 203 | { 204 | if (!QdInitialize()) 205 | { 206 | // TODO: Handle error better 207 | Log.Error("Failed to initialize srkcomm"); 208 | } 209 | } 210 | catch (Exception e) 211 | { 212 | Log.Exception(e, "Exception initializing srkcomm, likely srkcomm.dll is not available"); 213 | System.Environment.Exit(1); 214 | } 215 | } 216 | 217 | 218 | /// 219 | /// Run when this service is first started. Most useful for at install, or anything that starts before us on boot. 220 | /// Check the currently executing processes and records info about them and also checks them against our rules to note 221 | /// anything that should not have been running already (TODO Need to alert about that) 222 | /// 223 | public void AnalyzeRunningProcesses() 224 | { 225 | foreach(Process process in Process.GetProcesses()) { 226 | try 227 | { 228 | Log.Info("Process: {0} ID: {1}", process.ProcessName, process.Id); 229 | string fileName = process.Modules[0].FileName; 230 | Log.Info("File name: {0}", fileName); 231 | long ExecutableId; 232 | if (Arbiter.DecideOnProcess(fileName, out ExecutableId) == Decision.DENY) 233 | { 234 | Log.Warn("*** This file should not be running: {0}", fileName); 235 | // File running that should not be. 236 | // TODO Alert and/or Kill this process 237 | } 238 | 239 | PROCESS_INFO processInfo = new PROCESS_INFO(process); 240 | Database.LogProcessEvent(processInfo, ExecutableId, Database.ProcessState.Exists); 241 | 242 | } catch (Exception e) { 243 | if (process.Id == 0 || process.Id == 4) 244 | { 245 | // "System" (4) and "idle" (0) processes cannot have their modules enumerated, 246 | // so ignore them 247 | } 248 | else if (process.HasExited) 249 | { 250 | // no-op, just an exception because the process already exited 251 | } 252 | else 253 | { 254 | Log.Exception(e, "Exception reading process: {0}", process.ProcessName); 255 | } 256 | } 257 | } 258 | } 259 | 260 | public void Run() 261 | { 262 | Log.Info("Starting infinite loop"); 263 | try 264 | { 265 | conf = new SystemConfig(); 266 | MessagingInterfaces.UIComm.Init(); // Init static class 267 | AnalyzeRunningProcesses(); 268 | processMonitorCallback = new processMonitorCallbackDelegate(ProcessMonitorCallback); 269 | 270 | // Start thread that communites with our server 271 | beacon = new Beacon(); 272 | beaconThread = new Thread(new ThreadStart(beacon.Run)); 273 | beaconThread.Name = "BeaconThread"; 274 | beaconThread.IsBackground = true; 275 | beaconThread.Start(); 276 | 277 | while (QdMonitor(processMonitorCallback)) 278 | { 279 | if (!bRunning) return; // Using return instead of break so I can detect failures 280 | } 281 | 282 | Log.Info("Broke out of QdMonitor loop. This should not happen."); 283 | } 284 | catch (Exception e) 285 | { 286 | Log.Exception(e, "Exception in Service.Run"); 287 | // This is really bad, so rethrow the exception so we exit 288 | throw e; 289 | } 290 | } 291 | 292 | ~SRSvc() 293 | { 294 | Log.Info("SRSvc: cleanup"); 295 | if (!QdUnInitialize()) 296 | { 297 | // TODO: Handle error better 298 | Log.Error("SRSvc: Failed to uninitialize srkcomm"); 299 | } 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/srsvc/srsvc.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | x86 5 | 8.0.30703 6 | 2.0 7 | {84F110CD-CAB0-4AED-A660-7DCD30E71D62} 8 | Exe 9 | Properties 10 | srsvc 11 | srsvc 12 | v4.0 13 | 14 | 15 | 512 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | false 30 | true 31 | 32 | 33 | x86 34 | true 35 | full 36 | pdbonly 37 | true 38 | ..\..\bins\$(Configuration)\ 39 | 40 | 41 | prompt 42 | 4 43 | 44 | 45 | ..\..\images\icon.ico 46 | 47 | 48 | true 49 | 50 | 51 | TRACE;DEBUG 52 | false 53 | 54 | 55 | 56 | ..\..\lib\win32\FluentNHibernate.1.4.0.0\lib\net35\FluentNHibernate.dll 57 | 58 | 59 | ..\..\lib\win32\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll 60 | 61 | 62 | 63 | ..\..\lib\win32\NHibernate.3.3.1.4000\lib\Net35\NHibernate.dll 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | True 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 | False 103 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 104 | true 105 | 106 | 107 | False 108 | .NET Framework 3.5 SP1 Client Profile 109 | false 110 | 111 | 112 | False 113 | .NET Framework 3.5 SP1 114 | false 115 | 116 | 117 | False 118 | Windows Installer 3.1 119 | true 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /src/srui/Log.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Text; 14 | using System.Diagnostics; 15 | 16 | namespace srui 17 | { 18 | class Log 19 | { 20 | enum Level { DEBUG, INFO, WARN, ERROR, CRITICAL }; 21 | static string[] LevelName = new string[] { "DEBUG", "INFO", "WARN", "ERROR", "CRIT" }; 22 | const string APP_NAME = "SRUI"; 23 | 24 | public static void Debug(string format, params object[] args) 25 | { 26 | LogMessage((int)Level.DEBUG, format, args); 27 | } 28 | 29 | public static void Info(string format, params object[] args) 30 | { 31 | LogMessage((int)Level.INFO, format, args); 32 | } 33 | 34 | public static void Warn(string format, params object[] args) 35 | { 36 | LogMessage((int)Level.WARN, format, args); 37 | } 38 | 39 | public static void Error(string format, params object[] args) 40 | { 41 | LogMessage((int)Level.ERROR, format, args); 42 | } 43 | 44 | public static void Exception(Exception e, string format, params object[] args) 45 | { 46 | LogMessage((int)Level.ERROR, String.Format("{0}: {1}", String.Format(format, args), e.ToString()), null); 47 | } 48 | 49 | public static void Critical(string format, params object[] args) 50 | { 51 | LogMessage((int)Level.CRITICAL, format, args); 52 | } 53 | 54 | private static void LogMessage(int level, string format, params object[] args) 55 | { 56 | System.Diagnostics.Debug.WriteLine(String.Format("[{0} ({1})] {2}", LevelName[level], APP_NAME, String.Format(format, args))); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/srui/Program.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Windows.Forms; 13 | using System.Threading; 14 | 15 | namespace srui 16 | { 17 | static class Program 18 | { 19 | /// 20 | /// The main entry point for the application. 21 | /// 22 | [STAThread] 23 | static void Main() 24 | { 25 | Log.Debug("Starting"); 26 | 27 | Application.EnableVisualStyles(); 28 | Application.SetCompatibleTextRenderingDefault(false); 29 | TrayIcon trayIcon = new TrayIcon(); 30 | 31 | // Run thread for notifcations from the service 32 | Log.Debug("Checking for notifications"); 33 | Notifications notifications = new Notifications(trayIcon); 34 | Thread notificationsThread = new Thread(new ThreadStart(notifications.Run)); 35 | notificationsThread.Name = "NotificationsThread"; 36 | notificationsThread.IsBackground = true; 37 | 38 | notificationsThread.Start(); 39 | 40 | // Run the UI 41 | Application.Run(trayIcon); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/srui/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("Summit Route User Interface")] 9 | [assembly: AssemblyDescription("Enables interaction with the Summit Route EPP software")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Summit Route")] 12 | [assembly: AssemblyProduct("Summit Route EPP")] 13 | [assembly: AssemblyCopyright("Copyright Summit Route LLC")] 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("22b63e20-aec2-4695-928c-1b6e4a3059ae")] 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("0.0.0.1")] 36 | [assembly: AssemblyFileVersion("0.0.0.1")] 37 | -------------------------------------------------------------------------------- /src/srui/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1 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 srui.Properties { 12 | using System; 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 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("srui.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | internal static System.Drawing.Icon icon { 64 | get { 65 | object obj = ResourceManager.GetObject("icon", resourceCulture); 66 | return ((System.Drawing.Icon)(obj)); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/srui/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 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\..\..\images\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /src/srui/TrayIcon.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.ComponentModel; 13 | using System.Drawing; 14 | using System.Text; 15 | using System.Windows.Forms; 16 | using System.Diagnostics; 17 | 18 | namespace srui 19 | { 20 | public partial class TrayIcon : Form 21 | { 22 | private string szVersion = "0.0.0.1"; 23 | 24 | private System.ComponentModel.IContainer components = null; 25 | private System.Windows.Forms.NotifyIcon TrayNotifyIcon; 26 | private System.Windows.Forms.ContextMenuStrip TrayContextMenuStrip; 27 | private System.Windows.Forms.Button BtnClose; 28 | private System.Windows.Forms.ToolStripMenuItem SettingsToolStripMenuItem; 29 | private System.Windows.Forms.ToolStripMenuItem HelpToolStripMenuItem; 30 | private System.Windows.Forms.Label LblAbout; 31 | 32 | public TrayIcon() 33 | { 34 | this.components = new System.ComponentModel.Container(); 35 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TrayIcon)); 36 | this.TrayNotifyIcon = new System.Windows.Forms.NotifyIcon(this.components); 37 | 38 | // Context menu strip 39 | this.TrayContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); 40 | this.SettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 42 | 43 | this.TrayContextMenuStrip.SuspendLayout(); 44 | this.SuspendLayout(); 45 | 46 | // 47 | // Set up tray icon 48 | // 49 | this.TrayNotifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("taskbar.ico"))); 50 | this.TrayNotifyIcon.Text = "Summit Route End-Point Protection"; 51 | this.TrayNotifyIcon.Visible = true; 52 | // Attach menu strip 53 | this.TrayNotifyIcon.ContextMenuStrip = this.TrayContextMenuStrip; 54 | this.TrayNotifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.TrayNotifyIcon_MouseDoubleClick); 55 | 56 | // 57 | // Tool Strip Menu Items 58 | // 59 | // Settings 60 | this.SettingsToolStripMenuItem.Name = "SettingsToolStripMenuItem"; 61 | this.SettingsToolStripMenuItem.Text = "Settings..."; 62 | this.SettingsToolStripMenuItem.Click += new System.EventHandler(this.SettingsToolStripMenuItem_Click); 63 | 64 | // Help 65 | this.HelpToolStripMenuItem.Name = "HelpToolStripMenuItem"; 66 | this.HelpToolStripMenuItem.Text = "Help"; 67 | this.HelpToolStripMenuItem.Click += new System.EventHandler(this.HelpToolStripMenuItem_Click); 68 | 69 | 70 | // 71 | // TrayContextMenuStrip 72 | // 73 | this.TrayContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 74 | this.SettingsToolStripMenuItem, 75 | this.HelpToolStripMenuItem, 76 | }); 77 | this.TrayContextMenuStrip.Name = "TrayContextMenuStrip"; 78 | this.TrayContextMenuStrip.Size = new System.Drawing.Size(115, 70); 79 | 80 | InitializeComponent(); 81 | 82 | // Make sure nothing shows except the tray icon initially 83 | this.TrayContextMenuStrip.ResumeLayout(false); 84 | this.ResumeLayout(false); 85 | this.PerformLayout(); 86 | this.HideSettingsForm(); 87 | } 88 | 89 | protected override void Dispose(bool disposing) 90 | { 91 | // Clean up any components being used. 92 | if (disposing && components != null) 93 | { 94 | components.Dispose(); 95 | } 96 | 97 | base.Dispose(disposing); 98 | } 99 | 100 | private void HideSettingsForm() 101 | { 102 | this.WindowState = FormWindowState.Minimized; 103 | this.ShowInTaskbar = false; // Remove from taskbar 104 | base.Hide(); 105 | } 106 | 107 | private void ShowSettingsForm() 108 | { 109 | SetFormValues(); 110 | this.WindowState = FormWindowState.Normal; 111 | this.ShowInTaskbar = true; 112 | this.Show(); 113 | this.ResumeLayout(true); 114 | } 115 | 116 | /// 117 | /// Tray icon double click opens settings window 118 | /// 119 | /// 120 | /// 121 | private void TrayNotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) 122 | { 123 | ShowSettingsForm(); 124 | } 125 | 126 | private void SettingsToolStripMenuItem_Click(object sender, EventArgs e) 127 | { 128 | TrayContextMenuStrip.Hide(); 129 | ShowSettingsForm(); 130 | } 131 | 132 | private void HelpToolStripMenuItem_Click(object sender, EventArgs e) 133 | { 134 | TrayContextMenuStrip.Hide(); 135 | Process.Start(String.Format("https://app.summitroute.com/help?version={0}",szVersion)); 136 | } 137 | 138 | private void InitializeComponent() 139 | { 140 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TrayIcon)); 141 | this.SuspendLayout(); 142 | 143 | int formWidth = 500; 144 | int formHeight = 300; 145 | int margin = 15; 146 | 147 | // 148 | // BtnClose 149 | // 150 | this.BtnClose = new System.Windows.Forms.Button(); 151 | this.BtnClose.Text = "Close"; 152 | this.BtnClose.Width = 150; 153 | this.BtnClose.Location = new System.Drawing.Point(formWidth - this.BtnClose.Size.Width - margin, formHeight - this.BtnClose.Size.Height * 2 - margin); 154 | this.BtnClose.TabIndex = 0; 155 | this.BtnClose.Click += new System.EventHandler(this.CloseBtn_Click); 156 | 157 | // 158 | // LblAbout 159 | // 160 | this.LblAbout = new System.Windows.Forms.Label(); 161 | this.LblAbout.Text = "This version does not have any settings to display."; 162 | this.LblAbout.Width = formWidth; 163 | this.LblAbout.Location = new System.Drawing.Point(margin, margin); 164 | 165 | // 166 | // TrayIcon Settings Form 167 | // 168 | this.ClientSize = new System.Drawing.Size(formWidth, formHeight); 169 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("icon.ico"))); 170 | this.ControlBox = false; 171 | this.Controls.Add(this.BtnClose); 172 | this.Controls.Add(this.LblAbout); 173 | 174 | this.MinimumSize = new System.Drawing.Size(formWidth, formHeight); 175 | this.MaximumSize = new System.Drawing.Size(formWidth, formHeight); 176 | this.Name = "TrayIcon"; 177 | this.Text = "Summit Route EPP v"+szVersion+" Settings"; 178 | this.WindowState = System.Windows.Forms.FormWindowState.Minimized; 179 | this.ResumeLayout(false); 180 | 181 | } 182 | 183 | private void CloseBtn_Click(object sender, EventArgs e) 184 | { 185 | //Application.Exit(); 186 | HideSettingsForm(); 187 | } 188 | 189 | private void SaveCloseBtn_Click(object sender, EventArgs e) 190 | { 191 | // TODO Save 192 | } 193 | 194 | private void SetFormValues() 195 | { 196 | // TODO Set form 197 | } 198 | 199 | public void DisplayNotification(string msg) 200 | { 201 | this.TrayNotifyIcon.BalloonTipTitle = "Summit Route EPP"; 202 | this.TrayNotifyIcon.BalloonTipText = msg; 203 | this.TrayNotifyIcon.BalloonTipIcon = ToolTipIcon.Error; 204 | this.TrayNotifyIcon.Visible = true; 205 | this.TrayNotifyIcon.ShowBalloonTip(3000); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/srui/TrayIcon.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 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\..\images\taskbar.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\..\images\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | -------------------------------------------------------------------------------- /src/srui/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/srui/srui.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {843DC1CC-F7EB-4695-85A4-843D4522246B} 9 | WinExe 10 | Properties 11 | srui 12 | srui 13 | v4.0 14 | 15 | 16 | 512 17 | 18 | 19 | x86 20 | true 21 | full 22 | pdbonly 23 | true 24 | ..\..\bins\$(Configuration)\ 25 | 26 | 27 | prompt 28 | 4 29 | 30 | 31 | ..\..\images\icon.ico 32 | 33 | 34 | TRACE;DEBUG 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Form 48 | 49 | 50 | 51 | 52 | 53 | Designer 54 | 55 | 56 | Designer 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 73 | -------------------------------------------------------------------------------- /src/srui/ui_comm.cs: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Summit Route End Point Protection 4 | // 5 | // This source code is licensed under the BSD-style license found in the 6 | // LICENSE file in the root directory of this source tree. 7 | // 8 | ///////////////////////////////////////////////////////////////////////////// 9 | 10 | using System; 11 | using System.ServiceModel; 12 | 13 | 14 | namespace srui 15 | { 16 | /// 17 | /// Used to connect to the service 18 | /// 19 | [ServiceContract(CallbackContract = typeof(IMessageServiceCallback))] 20 | public interface IClientToServer 21 | { 22 | [OperationContract] 23 | void RegisterClient(string guid); 24 | } 25 | 26 | /// 27 | /// Used to receive messages from the service 28 | /// 29 | public interface IMessageServiceCallback 30 | { 31 | [OperationContract(IsOneWay = true)] 32 | void NotifyMsg(string msg); 33 | } 34 | 35 | [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)] 36 | public class ServiceCallback : IMessageServiceCallback 37 | { 38 | public void NotifyMsg(string msg) 39 | { 40 | Log.Info("Received msg: {0}", msg); 41 | UIDisplay.DisplayNotification(msg); 42 | 43 | return; 44 | } 45 | } 46 | 47 | public static class UIDisplay { 48 | public static TrayIcon trayIcon = null; 49 | 50 | public static void DisplayNotification(string msg) 51 | { 52 | try 53 | { 54 | if (trayIcon != null) 55 | { 56 | trayIcon.DisplayNotification(msg); 57 | } 58 | } 59 | catch (Exception e) 60 | { 61 | Log.Exception(e, "Exception in DisplayNotification"); 62 | } 63 | } 64 | } 65 | 66 | public class Notifications 67 | { 68 | public Notifications(TrayIcon _trayIcon) 69 | { 70 | UIDisplay.trayIcon = _trayIcon; 71 | } 72 | 73 | public void Run() 74 | { 75 | string guid = Guid.NewGuid().ToString(); 76 | Log.Info("Start client: {0}", guid); 77 | 78 | IClientToServer clientRegistrar; 79 | 80 | // Register client 81 | while (true) 82 | { 83 | try 84 | { 85 | var ctx = new InstanceContext(new ServiceCallback()); 86 | DuplexChannelFactory clientRegistrarFactory = 87 | new DuplexChannelFactory(ctx, 88 | new NetNamedPipeBinding(), 89 | new EndpointAddress("net.pipe://localhost/SREPP_regc") 90 | ); 91 | 92 | clientRegistrar = clientRegistrarFactory.CreateChannel(); 93 | 94 | clientRegistrar.RegisterClient(guid); 95 | break; 96 | } 97 | catch (Exception e) 98 | { 99 | 100 | if (e is System.ServiceModel.EndpointNotFoundException) 101 | { 102 | Log.Info("Problem connecting to server, will try again in 10 seconds"); 103 | System.Threading.Thread.Sleep(10000); // Sleep 10s 104 | } 105 | else 106 | { 107 | // Unknown exception, just bail 108 | Log.Exception(e, "Exception registering client"); 109 | break; 110 | } 111 | } 112 | } 113 | 114 | Log.Debug("Connected to the server"); 115 | 116 | // Sleep while we wait for new messages. Everything happens on a callback, so we just sleep constantly 117 | // TODO MAYBE: I should check if the server still knows about me, and if not, register again 118 | while (true) 119 | { 120 | System.Threading.Thread.Sleep(60000); // Sleep 60 seconds 121 | } 122 | 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /srepp_cs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "srsvc", "src\srsvc\srsvc.csproj", "{84F110CD-CAB0-4AED-A660-7DCD30E71D62}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "srui", "src\srui\srui.csproj", "{843DC1CC-F7EB-4695-85A4-843D4522246B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x86 = Debug|x86 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {84F110CD-CAB0-4AED-A660-7DCD30E71D62}.Debug|x86.ActiveCfg = Debug|x86 17 | {84F110CD-CAB0-4AED-A660-7DCD30E71D62}.Debug|x86.Build.0 = Debug|x86 18 | {84F110CD-CAB0-4AED-A660-7DCD30E71D62}.Release|x86.ActiveCfg = Release|x86 19 | {84F110CD-CAB0-4AED-A660-7DCD30E71D62}.Release|x86.Build.0 = Release|x86 20 | {843DC1CC-F7EB-4695-85A4-843D4522246B}.Debug|x86.ActiveCfg = Debug|x86 21 | {843DC1CC-F7EB-4695-85A4-843D4522246B}.Debug|x86.Build.0 = Debug|x86 22 | {843DC1CC-F7EB-4695-85A4-843D4522246B}.Release|x86.ActiveCfg = Release|x86 23 | {843DC1CC-F7EB-4695-85A4-843D4522246B}.Release|x86.Build.0 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | --------------------------------------------------------------------------------