├── .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 |
--------------------------------------------------------------------------------