├── packages.config ├── ProjectInstaller.cs ├── util └── KernelSymbolLookup.ps1 ├── SystemCallService.sln ├── SystemCallServiceSettings.cs ├── Properties ├── SystemCallServiceSettings.cs ├── AssemblyInfo.cs ├── SystemCallServiceSettings.settings └── SystemCallServiceSettings.Designer.cs ├── SystemCallService.Designer.cs ├── README.md ├── ProjectInstaller.Designer.cs ├── .gitignore ├── App.config ├── SystemCallService.resx ├── ProjectInstaller.resx ├── SystemCallServiceMain.cs ├── ntsensors.txt ├── SystemCallService.csproj ├── LICENSE └── SystemCallService.cs /packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ProjectInstaller.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2014 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | using System.ComponentModel; 22 | using System.Configuration.Install; 23 | 24 | namespace SystemCallService 25 | { 26 | [RunInstaller(true)] 27 | public partial class ProjectInstaller : Installer 28 | { 29 | public ProjectInstaller() 30 | { 31 | InitializeComponent(); 32 | } 33 | 34 | private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e) 35 | { 36 | 37 | } 38 | 39 | private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e) 40 | { 41 | 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /util/KernelSymbolLookup.ps1: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Ray Canzanese 2 | # email: rcanzanese@gmail.com 3 | # url: www.canzanese.com 4 | # 5 | # This file is part of SystemCallService. 6 | # 7 | # SystemCallService is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # SystemCallService is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with SystemCallService. If not, see . 19 | 20 | # Accepts a single command line argument that is the path to a kernel for 21 | # which to lookup the symbols. 22 | 23 | # Check for command line argument 24 | if($args.count -lt 1){ 25 | echo "Input the *.binary file output by the SyscallCounterService and get a *.symbol file in return." 26 | return 27 | } 28 | 29 | # Makes sure the debug tools are in the path. 30 | $env:Path += ";C:\Program Files (x86)\Windows Kits\8.1\bin\x64\" 31 | 32 | $inputfile = $args[0]; 33 | 34 | # Chekc to see if it is a binary file. 35 | if(-not $inputfile -match "\.binary$") 36 | { 37 | echo "Probably not a binary file. Make sure you are inputting the binary file SyscallCounterService died on." 38 | return 39 | } 40 | 41 | $outputfile = $inputfile -replace "\.binary$", ".symbols" 42 | 43 | dbh.exe $inputfile enum | out-file $outputfile -Encoding ASCII 44 | -------------------------------------------------------------------------------- /SystemCallService.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemCallService", "SystemCallService.csproj", "{7D3C3B13-8911-48C6-9B42-95DE79B34716}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x64.ActiveCfg = Debug|x64 21 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x64.Build.0 = Debug|x64 22 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x86.ActiveCfg = Debug|x86 23 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x86.Build.0 = Debug|x86 24 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x64.ActiveCfg = Release|x64 27 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x64.Build.0 = Release|x64 28 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x86.ActiveCfg = Release|x86 29 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x86.Build.0 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /SystemCallServiceSettings.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | using System.ComponentModel; 22 | using System.Configuration; 23 | 24 | namespace SystemCallService { 25 | 26 | // This class allows you to handle specific events on the settings class: 27 | // The SettingChanging event is raised before a setting's value is changed. 28 | // The PropertyChanged event is raised after a setting's value is changed. 29 | // The SettingsLoaded event is raised after the setting values are loaded. 30 | // The SettingsSaving event is raised before the setting values are saved. 31 | internal sealed class SystemCallServiceSettings { 32 | private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) { 33 | // Add code to handle the SettingChangingEvent event here. 34 | } 35 | 36 | private void SettingsSavingEventHandler(object sender, CancelEventArgs e) { 37 | // Add code to handle the SettingsSaving event here. 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Properties/SystemCallServiceSettings.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | 22 | using System.ComponentModel; 23 | using System.Configuration; 24 | 25 | namespace SystemCallService.Properties { 26 | 27 | 28 | // This class allows you to handle specific events on the settings class: 29 | // The SettingChanging event is raised before a setting's value is changed. 30 | // The PropertyChanged event is raised after a setting's value is changed. 31 | // The SettingsLoaded event is raised after the setting values are loaded. 32 | // The SettingsSaving event is raised before the setting values are saved. 33 | internal sealed partial class SystemCallServiceSettings { 34 | private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) { 35 | // Add code to handle the SettingChangingEvent event here. 36 | } 37 | 38 | private void SettingsSavingEventHandler(object sender, CancelEventArgs e) { 39 | // Add code to handle the SettingsSaving event here. 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SystemCallService.Designer.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | 22 | using System.ComponentModel; 23 | 24 | namespace SystemCallService 25 | { 26 | partial class SystemCallService 27 | { 28 | /// 29 | /// Required designer variable. 30 | /// 31 | private IContainer components = null; 32 | 33 | /// 34 | /// Clean up any resources being used. 35 | /// 36 | /// true if managed resources should be disposed; otherwise, false. 37 | protected override void Dispose(bool disposing) 38 | { 39 | if (disposing && (components != null)) 40 | { 41 | components.Dispose(); 42 | } 43 | base.Dispose(disposing); 44 | } 45 | 46 | #region Component Designer generated code 47 | 48 | /// 49 | /// Required method for Designer support - do not modify 50 | /// the contents of this method with the code editor. 51 | /// 52 | private void InitializeComponent() 53 | { 54 | // 55 | // SystemCallService 56 | // 57 | this.ServiceName = "Service1"; 58 | 59 | } 60 | 61 | #endregion 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | 22 | using System.Reflection; 23 | using System.Runtime.InteropServices; 24 | 25 | // General Information about an assembly is controlled through the following 26 | // set of attributes. Change these attribute values to modify the information 27 | // associated with an assembly. 28 | [assembly: AssemblyTitle("SystemCallService")] 29 | [assembly: AssemblyDescription("Performs system call tracing for research purposes. ")] 30 | [assembly: AssemblyConfiguration("")] 31 | [assembly: AssemblyCompany("")] 32 | [assembly: AssemblyProduct("SystemCallService")] 33 | [assembly: AssemblyCopyright("Copyright © Ray Canzanese 2015")] 34 | [assembly: AssemblyTrademark("")] 35 | [assembly: AssemblyCulture("")] 36 | 37 | // Setting ComVisible to false makes the types in this assembly not visible 38 | // to COM components. If you need to access a type in this assembly from 39 | // COM, set the ComVisible attribute to true on that type. 40 | [assembly: ComVisible(false)] 41 | 42 | // The following GUID is for the ID of the typelib if this project is exposed to COM 43 | [assembly: Guid("2d0ef725-105b-4981-b4ec-dd3ecd4c7017")] 44 | 45 | // Version information for an assembly consists of the following four values: 46 | // 47 | // Major Version 48 | // Minor Version 49 | // Build Number 50 | // Revision 51 | // 52 | // You can specify all the values or you can default the Build and Revision Numbers 53 | // by using the '*' as shown below: 54 | // [assembly: AssemblyVersion("1.0.*")] 55 | [assembly: AssemblyVersion("2014.01.0.0")] 56 | [assembly: AssemblyFileVersion("2014.01.0.0")] 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SystemCallService 2 | 3 | Host / process / thread-level system call tracer for Windows 7 / 8 / 2008 / 2012 4 | 5 | ## Prerequisites 6 | * Requires .NET Framework 4.5 or newer 7 | * Windows 7 / 2008 / 2008 R2 / 8 / 8.1 / 2012 / 2012 R2 8 | * TraceEvent 1.0.29 (can be installed using Nuget) 9 | * System.Data.SQLite 1.0.96.0 (can be installed using Nuget) 10 | 11 | ## Symbol tables 12 | Symbol tables change when new kernel versions are released. 13 | The current update process is manual and requires the Windows Debugging Tools. 14 | There is a tool in the utils/ directory to facilitate symbol lookup. 15 | 16 | ``` 17 | dbh.exe "kernel_file" enum | out-file "output symbols" -Encoding ASCII 18 | ``` 19 | 20 | ## Quick start instructions 21 | 22 | * Open an elevated command prompt or powershell by right clicking the icon and choosing "Run as Administrator" 23 | * Change to the folder where SystemCallService.exe is located 24 | * Install the service by running: 25 | ``` 26 | SystemCallService.exe -install 27 | ``` 28 | * To uninstall the service, run: 29 | ``` 30 | SystemCallService.exe -uninstall 31 | ``` 32 | 33 | ## Overview 34 | 35 | ### Data storage 36 | 37 | Data are stored in C:\Windows\Temp\SystemCallServiceData\ 38 | * database.sqlite is a sqlite database containing all of the logged data. 39 | * debug_log.txt is a log file containing information useful for debugging. 40 | * host_data_trace is a binary file containing the host data 41 | * the *_trace files are the process and thread traces, with GUIDs specified in the database.sqlite 42 | 43 | Major error messages are also logged to the Application Event Log. 44 | 45 | ### Usage 46 | There are three ways to control the service. All must be executed using "Run as Administrator": 47 | * sc.exe 48 | * SystemCallService.exe 49 | * net.exe ()for stopping and starting the service only) 50 | 51 | ####Installation 52 | ``` 53 | sc.exe create SystemCallService binPath= "C:\Full\Path\To\SystemCallService.exe" start= auto 54 | ``` 55 | or 56 | ``` 57 | SystemCallService.exe -install 58 | ``` 59 | 60 | ####Uninstallation 61 | ```sc.exe delete SystemCallService``` 62 | or 63 | ```SystemCallService.exe -uninstall ``` 64 | 65 | ####Start Logging 66 | 67 | ```sc.exe start SystemCallService``` 68 | 69 | or 70 | 71 | ```SystemCallService.exe -start ``` 72 | 73 | or 74 | 75 | ```net start SystemCallService``` 76 | 77 | ####Stop Logging 78 | ```sc.exe stop SystemCallService``` 79 | 80 | or 81 | 82 | ```SystemCallService.exe -stop ``` 83 | 84 | or 85 | 86 | ```net stop SystemCallService``` -------------------------------------------------------------------------------- /ProjectInstaller.Designer.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2014 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | 22 | using System.ComponentModel; 23 | using System.ServiceProcess; 24 | 25 | namespace SystemCallService 26 | { 27 | partial class ProjectInstaller 28 | { 29 | /// 30 | /// Required designer variable. 31 | /// 32 | private IContainer components = null; 33 | 34 | /// 35 | /// Clean up any resources being used. 36 | /// 37 | /// true if managed resources should be disposed; otherwise, false. 38 | protected override void Dispose(bool disposing) 39 | { 40 | if (disposing && (components != null)) 41 | { 42 | components.Dispose(); 43 | } 44 | base.Dispose(disposing); 45 | } 46 | 47 | #region Component Designer generated code 48 | 49 | /// 50 | /// Required method for Designer support - do not modify 51 | /// the contents of this method with the code editor. 52 | /// 53 | private void InitializeComponent() 54 | { 55 | this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller(); 56 | this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller(); 57 | // 58 | // serviceProcessInstaller1 59 | // 60 | this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; 61 | this.serviceProcessInstaller1.Password = null; 62 | this.serviceProcessInstaller1.Username = null; 63 | this.serviceProcessInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceProcessInstaller1_AfterInstall); 64 | // 65 | // serviceInstaller1 66 | // 67 | this.serviceInstaller1.Description = "Collects system call traces for research purposes. Contact Ray Canzanese -- rcanzanese@gmail.com"; 68 | this.serviceInstaller1.DisplayName = "System Call Service"; 69 | this.serviceInstaller1.ServiceName = "SystemCallService"; 70 | this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic; 71 | this.serviceInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceInstaller1_AfterInstall); 72 | this.serviceInstaller1.ServicesDependedOn = new string[] {"LanmanServer"}; 73 | // 74 | // ProjectInstaller 75 | // 76 | this.Installers.AddRange(new System.Configuration.Install.Installer[] { 77 | this.serviceProcessInstaller1, 78 | this.serviceInstaller1}); 79 | 80 | } 81 | 82 | #endregion 83 | 84 | private ServiceProcessInstaller serviceProcessInstaller1; 85 | private ServiceInstaller serviceInstaller1; 86 | } 87 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studo 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | # TODO: Comment the next line if you want to checkin your web deploy settings 133 | # but database connection strings (with potential passwords) will be unencrypted 134 | *.pubxml 135 | *.publishproj 136 | 137 | # NuGet Packages 138 | *.nupkg 139 | # The packages folder can be ignored because of Package Restore 140 | **/packages/* 141 | # except build/, which is used as an MSBuild target. 142 | !**/packages/build/ 143 | # Uncomment if necessary however generally it will be regenerated when needed 144 | #!**/packages/repositories.config 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | *.[Cc]ache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.dbproj.schemaview 161 | *.pfx 162 | *.publishsettings 163 | node_modules/ 164 | bower_components/ 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file 170 | # to a newer Visual Studio version. Backup files are not needed, 171 | # because we have git ;-) 172 | _UpgradeReport_Files/ 173 | Backup*/ 174 | UpgradeLog*.XML 175 | UpgradeLog*.htm 176 | 177 | # SQL Server files 178 | *.mdf 179 | *.ldf 180 | 181 | # Business Intelligence projects 182 | *.rdl.data 183 | *.bim.layout 184 | *.bim_*.settings 185 | 186 | # Microsoft Fakes 187 | FakesAssemblies/ 188 | 189 | # Node.js Tools for Visual Studio 190 | .ntvs_analysis.dat 191 | 192 | # Visual Studio 6 build log 193 | *.plg 194 | 195 | # Visual Studio 6 workspace options file 196 | *.opt 197 | -------------------------------------------------------------------------------- /Properties/SystemCallServiceSettings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SystemCallServiceData 7 | 8 | 9 | debug_log.txt 10 | 11 | 12 | Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, CommandLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey INTEGER, Md5 TEXT 13 | 14 | 15 | Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT 16 | 17 | 18 | NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DOUBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace INT, ThreadTrace INT 19 | 20 | 21 | 0 22 | 23 | 24 | 3600000 25 | 26 | 27 | symbols 28 | 29 | 30 | ntsensors.txt 31 | 32 | 33 | 120000 34 | 35 | 36 | 30000 37 | 38 | 39 | 30000 40 | 41 | 42 | 100 43 | 44 | 45 | True 46 | 47 | 48 | 10000 49 | 50 | 51 | None 52 | 53 | 54 | False 55 | 56 | 57 | True 58 | 59 | 60 | True 61 | 62 | 63 | True 64 | 65 | 66 | False 67 | 68 | 69 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | None 15 | 16 | 17 | 18 | 19 | 20 | 21 | SystemCallServiceData 22 | 23 | 24 | debug_log.txt 25 | 26 | 27 | Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, CommandLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey INTEGER, Md5 TEXT 28 | 29 | 30 | Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT 31 | 32 | 33 | NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DOUBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace INT, ThreadTrace INT 34 | 35 | 36 | 0 37 | 38 | 39 | 3600000 40 | 41 | 42 | symbols 43 | 44 | 45 | ntsensors.txt 46 | 47 | 48 | 120000 49 | 50 | 51 | 30000 52 | 53 | 54 | 30000 55 | 56 | 57 | 100 58 | 59 | 60 | True 61 | 62 | 63 | 10000 64 | 65 | 66 | False 67 | 68 | 69 | True 70 | 71 | 72 | True 73 | 74 | 75 | True 76 | 77 | 78 | False 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /SystemCallService.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 | False 122 | 123 | -------------------------------------------------------------------------------- /ProjectInstaller.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 | 17, 56 122 | 123 | 124 | 196, 17 125 | 126 | 127 | False 128 | 129 | -------------------------------------------------------------------------------- /SystemCallServiceMain.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | // TODO: Cleanup this code and provide feedback to the terminal 22 | 23 | using System; 24 | using System.Collections; 25 | using System.Configuration.Install; 26 | using System.ServiceProcess; 27 | 28 | namespace SystemCallService 29 | { 30 | static class SyscallCounterMain 31 | { 32 | private static readonly String _serviceName = "SystemCallService"; 33 | /// 34 | /// The main entry point for the application. 35 | /// 36 | static void Main(string[] args) 37 | { 38 | if (args.Length == 0) 39 | { 40 | ServiceBase[] servicesToRun; 41 | servicesToRun = new ServiceBase[] 42 | { 43 | new SystemCallService() 44 | }; 45 | ServiceBase.Run(servicesToRun); 46 | } 47 | else if (args.Length == 1) 48 | { 49 | switch (args[0]) 50 | { 51 | case "-install": 52 | InstallService(); 53 | StartService(); 54 | break; 55 | case "-uninstall": 56 | StopService(); 57 | UninstallService(); 58 | break; 59 | case "-start": 60 | StartService(); 61 | break; 62 | case "-stop": 63 | StopService(); 64 | break; 65 | default: 66 | Console.WriteLine("This is a service executable. Read the documentation or try one of the following command line options: -install -uninstall -start -stop"); 67 | break; 68 | } 69 | } 70 | } 71 | 72 | private static bool IsInstalled() 73 | { 74 | using (ServiceController controller = 75 | new ServiceController(_serviceName)) 76 | { 77 | try 78 | { 79 | ServiceControllerStatus status = controller.Status; 80 | } 81 | catch 82 | { 83 | return false; 84 | } 85 | return true; 86 | } 87 | } 88 | 89 | private static bool IsRunning() 90 | { 91 | using (ServiceController controller = 92 | new ServiceController(_serviceName)) 93 | { 94 | if (!IsInstalled()) return false; 95 | return (controller.Status == ServiceControllerStatus.Running); 96 | } 97 | } 98 | 99 | private static AssemblyInstaller GetInstaller() 100 | { 101 | AssemblyInstaller installer = new AssemblyInstaller( 102 | typeof(ProjectInstaller).Assembly, null); 103 | installer.UseNewContext = true; 104 | return installer; 105 | } 106 | 107 | private static void InstallService() 108 | { 109 | if (IsInstalled()) return; 110 | 111 | try 112 | { 113 | using (AssemblyInstaller installer = GetInstaller()) 114 | { 115 | IDictionary state = new Hashtable(); 116 | try 117 | { 118 | installer.Install(state); 119 | installer.Commit(state); 120 | } 121 | catch 122 | { 123 | try 124 | { 125 | installer.Rollback(state); 126 | } 127 | catch 128 | { 129 | 130 | } 131 | throw; 132 | } 133 | } 134 | } 135 | catch 136 | { 137 | throw; 138 | } 139 | } 140 | 141 | private static void UninstallService() 142 | { 143 | if (!IsInstalled()) return; 144 | try 145 | { 146 | using (AssemblyInstaller installer = GetInstaller()) 147 | { 148 | IDictionary state = new Hashtable(); 149 | try 150 | { 151 | installer.Uninstall(state); 152 | } 153 | catch 154 | { 155 | throw; 156 | } 157 | } 158 | } 159 | catch 160 | { 161 | throw; 162 | } 163 | } 164 | 165 | private static void StartService() 166 | { 167 | if (!IsInstalled()) return; 168 | 169 | using (ServiceController controller = 170 | new ServiceController(_serviceName)) 171 | { 172 | try 173 | { 174 | if (controller.Status != ServiceControllerStatus.Running) 175 | { 176 | controller.Start(); 177 | controller.WaitForStatus(ServiceControllerStatus.Running, 178 | TimeSpan.FromSeconds(10)); 179 | } 180 | } 181 | catch 182 | { 183 | throw; 184 | } 185 | } 186 | } 187 | 188 | private static void StopService() 189 | { 190 | if (!IsInstalled()) return; 191 | using (ServiceController controller = 192 | new ServiceController(_serviceName)) 193 | { 194 | try 195 | { 196 | if (controller.Status != ServiceControllerStatus.Stopped) 197 | { 198 | controller.Stop(); 199 | controller.WaitForStatus(ServiceControllerStatus.Stopped, 200 | TimeSpan.FromSeconds(10)); 201 | } 202 | } 203 | catch 204 | { 205 | throw; 206 | } 207 | } 208 | } 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /Properties/SystemCallServiceSettings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 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 SystemCallService.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class SystemCallServiceSettings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static SystemCallServiceSettings defaultInstance = ((SystemCallServiceSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new SystemCallServiceSettings()))); 19 | 20 | public static SystemCallServiceSettings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("SystemCallServiceData")] 29 | public string DataDirectory { 30 | get { 31 | return ((string)(this["DataDirectory"])); 32 | } 33 | } 34 | 35 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 36 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 37 | [global::System.Configuration.DefaultSettingValueAttribute("debug_log.txt")] 38 | public string DebugLogFilename { 39 | get { 40 | return ((string)(this["DebugLogFilename"])); 41 | } 42 | } 43 | 44 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 45 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 46 | [global::System.Configuration.DefaultSettingValueAttribute("Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Comma" + 47 | "ndLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey" + 48 | " INTEGER, Md5 TEXT")] 49 | public string ProcessTableStructure { 50 | get { 51 | return ((string)(this["ProcessTableStructure"])); 52 | } 53 | } 54 | 55 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 56 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 57 | [global::System.Configuration.DefaultSettingValueAttribute("Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec " + 58 | "DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT ")] 59 | public string ThreadTableStructure { 60 | get { 61 | return ((string)(this["ThreadTableStructure"])); 62 | } 63 | } 64 | 65 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 66 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 67 | [global::System.Configuration.DefaultSettingValueAttribute("NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DO" + 68 | "UBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace" + 69 | " INT, ThreadTrace INT")] 70 | public string SystemInfoTableStructure { 71 | get { 72 | return ((string)(this["SystemInfoTableStructure"])); 73 | } 74 | } 75 | 76 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 77 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 78 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 79 | public int Verbosity { 80 | get { 81 | return ((int)(this["Verbosity"])); 82 | } 83 | } 84 | 85 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 86 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 87 | [global::System.Configuration.DefaultSettingValueAttribute("3600000")] 88 | public double AutoResetMs { 89 | get { 90 | return ((double)(this["AutoResetMs"])); 91 | } 92 | } 93 | 94 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 95 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 96 | [global::System.Configuration.DefaultSettingValueAttribute("symbols")] 97 | public string SymbolSubfolder { 98 | get { 99 | return ((string)(this["SymbolSubfolder"])); 100 | } 101 | } 102 | 103 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 104 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 105 | [global::System.Configuration.DefaultSettingValueAttribute("ntsensors.txt")] 106 | public string NtSensorList { 107 | get { 108 | return ((string)(this["NtSensorList"])); 109 | } 110 | } 111 | 112 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 113 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 114 | [global::System.Configuration.DefaultSettingValueAttribute("120000")] 115 | public float CommitInterval { 116 | get { 117 | return ((float)(this["CommitInterval"])); 118 | } 119 | } 120 | 121 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 122 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 123 | [global::System.Configuration.DefaultSettingValueAttribute("30000")] 124 | public double ThreadDeletionDelay { 125 | get { 126 | return ((double)(this["ThreadDeletionDelay"])); 127 | } 128 | } 129 | 130 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 131 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 132 | [global::System.Configuration.DefaultSettingValueAttribute("30000")] 133 | public double ProcessDeletionDelay { 134 | get { 135 | return ((double)(this["ProcessDeletionDelay"])); 136 | } 137 | } 138 | 139 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 140 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 141 | [global::System.Configuration.DefaultSettingValueAttribute("100")] 142 | public double MinBackoff { 143 | get { 144 | return ((double)(this["MinBackoff"])); 145 | } 146 | } 147 | 148 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 149 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 150 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 151 | public bool TracePerProcess { 152 | get { 153 | return ((bool)(this["TracePerProcess"])); 154 | } 155 | } 156 | 157 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 158 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 159 | [global::System.Configuration.DefaultSettingValueAttribute("10000")] 160 | public long MaxTraceSyscalls { 161 | get { 162 | return ((long)(this["MaxTraceSyscalls"])); 163 | } 164 | } 165 | 166 | [global::System.Configuration.UserScopedSettingAttribute()] 167 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 168 | [global::System.Configuration.DefaultSettingValueAttribute("None")] 169 | public string HostIdentifier { 170 | get { 171 | return ((string)(this["HostIdentifier"])); 172 | } 173 | set { 174 | this["HostIdentifier"] = value; 175 | } 176 | } 177 | 178 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 179 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 180 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 181 | public bool AnonymizeHostname { 182 | get { 183 | return ((bool)(this["AnonymizeHostname"])); 184 | } 185 | } 186 | 187 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 188 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 189 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 190 | public bool ScrubCommandLine { 191 | get { 192 | return ((bool)(this["ScrubCommandLine"])); 193 | } 194 | } 195 | 196 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 197 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 198 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 199 | public bool TraceHostLevel { 200 | get { 201 | return ((bool)(this["TraceHostLevel"])); 202 | } 203 | } 204 | 205 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 206 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 207 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 208 | public bool TracePerThread { 209 | get { 210 | return ((bool)(this["TracePerThread"])); 211 | } 212 | } 213 | 214 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 215 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 216 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 217 | public bool ProfileCode { 218 | get { 219 | return ((bool)(this["ProfileCode"])); 220 | } 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /ntsensors.txt: -------------------------------------------------------------------------------- 1 | NtGetContextThread 2 | NtDeleteValueKey 3 | NtCreateProcessEx 4 | NtSystemRoot 5 | NtFilterBootOption 6 | NtQueryEaFile 7 | NtCreateIRTimer 8 | NtCancelWaitCompletionPacket 9 | NtFlushBuffersFileEx 10 | NtQuerySemaphore 11 | NtLockRegistryKey 12 | NtSetCachedSigningLevel 13 | NtFlushBuffersFile 14 | NtQueryMultipleValueKey 15 | NtUmsThreadYield 16 | NtAlpcCreateResourceReserve 17 | NtSetIoCompletionEx 18 | NtAccessCheckByTypeResultList 19 | NtRaiseException 20 | NtSetSystemInformation 21 | NtWaitForWorkViaWorkerFactory 22 | NtSuspendProcess 23 | NtCommitTransaction 24 | NtdllExports 25 | NtCreateTimer 26 | NtContinue 27 | NtWaitForDebugEvent 28 | NtQueryDebugFilterState 29 | NtProtectVirtualMemory 30 | NtCreateKeyedEvent 31 | NtOpenTimer 32 | NtFlushProcessWriteBuffers 33 | NtQueryVirtualMemory 34 | NtCreateFile 35 | NtAllocateVirtualMemory 36 | NtCreateSymbolicLinkObject 37 | NtImpersonateAnonymousToken 38 | NtCreatePrivateNamespace 39 | NtSetDebugFilterState 40 | NtInitialUserProcessBuffer 41 | NtDeleteWnfStateName 42 | NtGlobalFlag 43 | NtCreateKey 44 | NtSetSystemTime 45 | NtPrivilegeCheck 46 | NtQueryInformationTransaction 47 | NtSetEvent 48 | NtAlpcOpenSenderThread 49 | NtGetCachedSigningLevel 50 | NtDeleteKey 51 | NtPropagationComplete 52 | NtRollbackEnlistment 53 | NtCreateWnfStateName 54 | NtSetThreadExecutionState 55 | NtFreezeRegistry 56 | NtDeletePrivateNamespace 57 | NtSaveKey 58 | NtQueryDirectoryFile 59 | NtPowerInformation 60 | NtCreateSection 61 | NtSetContextThread 62 | NtAlpcCancelMessage 63 | NtAlpcCreatePort 64 | NtUnloadKey 65 | NtDeleteFile 66 | NtCreateTokenEx 67 | NtSetIntervalProfile 68 | NtQueryIntervalProfile 69 | NtCreateTransaction 70 | NtReplaceKey 71 | NtReadRequestData 72 | NtClearEvent 73 | NtCreateDebugObject 74 | NtCreateDirectoryObject 75 | NtRenameTransactionManager 76 | NtCreateTimer2 77 | NtCreateNamedPipeFile 78 | NtAlpcRevokeSecurityContext 79 | NtDeleteBootEntry 80 | NtWriteVirtualMemory 81 | NtAlpcDeleteResourceReserve 82 | NtIsProcessInJob 83 | NtAlertThread 84 | NtQuerySystemInformationEx 85 | NtDebugActiveProcess 86 | NtQueueApcThreadEx 87 | NtOpenFile 88 | NtGetNotificationResourceManager 89 | NtAcceptConnectPort 90 | NtListenPort 91 | NtTerminateJobObject 92 | NtDisableLastKnownGood 93 | NtOpenPrivateNamespace 94 | NtDeviceIoControlFile 95 | NtFlushInstructionCache 96 | NtQuerySystemEnvironmentValue 97 | NtFlushInstallUILanguage 98 | NtMapCMFModule 99 | NtGetCompleteWnfStateSubscription 100 | NtSubscribeWnfStateChange 101 | NtMakePermanentObject 102 | NtAlertResumeThread 103 | NtCreateEvent 104 | NtOpenKeyTransactedEx 105 | NtWriteRequestData 106 | NtDelayExecution 107 | NtSaveMergedKeys 108 | NtAlpcAcceptConnectPort 109 | NtSetInformationJobObject 110 | NtImpersonateThread 111 | NtQueryKey 112 | NtGetWriteWatch 113 | NtQueryLicenseValue 114 | NtSetValueKey 115 | NtAllocateLocallyUniqueId 116 | NtReleaseSemaphore 117 | NtRollbackTransaction 118 | NtGetNlsSectionPtr 119 | NtFindAtom 120 | NtLoadDriver 121 | NtCreateMailslotFile 122 | NtAccessCheck 123 | NtDeleteObjectAuditAlarm 124 | NtSetBootEntryOrder 125 | NtShutdownWorkerFactory 126 | NtOpenEventPair 127 | NtWaitHighEventPair 128 | NtIsSystemResumeAutomatic 129 | NtThawRegistry 130 | NtAccessCheckByTypeResultListAndAuditAlarmByHandle 131 | NtAlpcCreatePortSection 132 | NtCreateJobSet 133 | NtSetQuotaInformationFile 134 | NtStopProfile 135 | NtCreateProfile 136 | NtCreateTransactionManager 137 | NtEnumerateDriverEntries 138 | NtPrepareComplete 139 | NtOpenObjectAuditAlarm 140 | NtRequestWaitReplyPort 141 | NtSetDefaultUILanguage 142 | NtYieldExecution 143 | NtCommitEnlistment 144 | NtCreateEventPair 145 | NtPrePrepareComplete 146 | NtSetSystemEnvironmentValueEx 147 | NtVhdBootFile 148 | NtQueryInformationWorkerFactory 149 | NtCancelIoFile 150 | NtRemoveIoCompletion 151 | NtFsControlFile 152 | NtCancelIoFileEx 153 | NtQueryTimer 154 | NtRollbackComplete 155 | NtCompareTokens 156 | NtCreatePort 157 | NtRemoveProcessDebug 158 | NtSetVolumeInformationFile 159 | NtPlugPlayGetDeviceRelatedDevice 160 | NtAllocateUserPhysicalPages 161 | NtQueryWnfStateData 162 | NtRecoverEnlistment 163 | NtQueryInformationThread 164 | NtQuerySecurityAttributesToken 165 | NtModifyDriverEntry 166 | NtUpdateWnfStateData 167 | NtResumeThread 168 | NtSetIoCompletion 169 | NtQueryPortInformationProcess 170 | NtEnableLastKnownGood 171 | NtSetInformationProcess 172 | NtQueryDefaultLocale 173 | NtReplacePartitionUnit 174 | NtWaitForKeyedEvent 175 | NtQueryWnfStateNameInformation 176 | NtDrawText 177 | NtWaitForSingleObject 178 | NtAddDriverEntry 179 | NtSecureConnectPort 180 | NtQueryInformationJobObject 181 | NtCreateEnlistment 182 | NtCompactKeys 183 | NtQueryValueKey 184 | NtCreateUserProcess 185 | NtSetSecurityObject 186 | NtIsUILanguageComitted 187 | NtPlugPlayGetDeviceStatus 188 | NtDeleteWnfStateData 189 | NtFlushWriteBuffer 190 | NtQuerySystemEnvironmentValueEx 191 | NtTerminateThread 192 | NtRollforwardTransactionManager 193 | NtSaveKeyEx 194 | NtOpenProcess 195 | NtCreateWaitablePort 196 | NtCompressKey 197 | NtCreateThreadEx 198 | NtAlpcDeletePortSection 199 | NtInitiatePowerAction 200 | NtQueryInformationTransactionManager 201 | NtCreateResourceManager 202 | NtPropagationFailed 203 | NtSetUuidSeed 204 | NtSetWnfProcessNotificationEvent 205 | NtInitialUserProcessBufferType 206 | NtUnmapViewOfSectionEx 207 | NtQueryIoCompletion 208 | NtOpenEvent 209 | NtBuildLabEx 210 | NtQueryInformationEnlistment 211 | NtClose 212 | NtCreatePagingFile 213 | NtBuildLab 214 | NtOpenMutant 215 | NtQueryInformationResourceManager 216 | NtCompleteConnectPort 217 | NtPrivilegeObjectAuditAlarm 218 | NtQueryQuotaInformationFile 219 | NtBuildNumber 220 | NtCreateToken 221 | NtSuspendThread 222 | NtPlugPlayGetDeviceProperty 223 | NtSetInformationWorkerFactory 224 | NtRegisterProtocolAddressInformation 225 | NtBuildGUID 226 | NtRenameKey 227 | NtCreateThread 228 | NtSetInformationObject 229 | NtDeleteAtom 230 | NtAlpcDeleteSecurityContext 231 | NtReplyWaitReceivePort 232 | NtTerminateProcess 233 | Ntdll32Exports 234 | NtSetEaFile 235 | NtOpenTransaction 236 | NtPlugPlayControl 237 | NtSinglePhaseReject 238 | NtSetInformationFile 239 | NtPrepareEnlistment 240 | NtAccessCheckAndAuditAlarm 241 | NtInitialUserProcessBufferLength 242 | NtMapViewOfSection 243 | NtPlugPlayGetDeviceRelationsList 244 | NtSetSystemEnvironmentValue 245 | NtOpenDirectoryObject 246 | NtSetInformationKey 247 | NtAddAtom 248 | NtQueryObject 249 | NtReplyWaitReceivePortEx 250 | NtCreateProfileEx 251 | NtUnloadDriver 252 | NtLockFile 253 | NtFilterTokenEx 254 | NtNotifyChangeKey 255 | NtFreeVirtualMemory 256 | NtAlpcQueryInformation 257 | NtThawTransactions 258 | NtGetDevicePowerState 259 | NtCancelTimer2 260 | NtGetMUIRegistryInfo 261 | NtCallbackReturn 262 | NtAddBootEntry 263 | NtfsStructLock 264 | NtWaitForMultipleObjects32 265 | NtQueryMutant 266 | NtAssociateWaitCompletionPacket 267 | NtConnectPort 268 | NtPulseEvent 269 | NtOpenSymbolicLinkObject 270 | NtOpenSemaphore 271 | NtSetEventBoostPriority 272 | NtSetInformationVirtualMemory 273 | NtSetLowWaitHighEventPair 274 | NtResetWriteWatch 275 | NtSystemDebugControl 276 | NtAlpcQueryInformationMessage 277 | NtAdjustTokenClaimsAndDeviceGroups 278 | NtWriteFileGather 279 | NtQueryAttributesFile 280 | NtFlushVirtualMemory 281 | NtCreateKeyTransacted 282 | NtAccessCheckByType 283 | NtDuplicateObject 284 | NtImpersonateClientOfPort 285 | NtQuerySystemTime 286 | NtOpenKeyTransacted 287 | NtRestoreKey 288 | NtOpenThreadTokenEx 289 | NtAdjustGroupsToken 290 | NtQueryFullAttributesFile 291 | NtdllExportInformation 292 | NtRequestPort 293 | NtModifyBootEntry 294 | NtCreateWaitCompletionPacket 295 | NtRegisterThreadTerminatePort 296 | NtAdjustPrivilegesToken 297 | NtReplyPort 298 | NtAlpcDisconnectPort 299 | NtGetNextProcess 300 | NtCreateKeyTransacted_Stub 301 | NtAssignProcessToJobObject 302 | NtRecoverTransactionManager 303 | NtAlpcSetInformation 304 | NtTraceControl 305 | NtTranslateFilePath 306 | NtAlpcOpenSenderProcess 307 | NtOpenSection 308 | NtQueryInformationFile 309 | NtSetDriverEntryOrder 310 | NtCreateSemaphore 311 | NtAlpcConnectPortEx 312 | NtQueryInstallUILanguage 313 | NtQuerySystemInformation 314 | NtQueryOpenSubKeysEx 315 | NtQueueApcThread 316 | NtCancelTimer 317 | NtEnumerateBootEntries 318 | NtWaitForMultipleObjects 319 | NtQueryPerformanceCounter 320 | NtLockVirtualMemory 321 | NtPrePrepareEnlistment 322 | NtCommitComplete 323 | NtInitializeNlsFiles 324 | NtWorkerFactoryWorkerReady 325 | NtCreateLowBoxToken 326 | NtQuerySymbolicLinkObject 327 | NtUnloadKey2 328 | NtLockProductActivationKeys 329 | NtSetInformationTransaction 330 | NtOpenKeyedEvent 331 | NtQuerySection 332 | NtOpenKey 333 | NtQueryEvent 334 | NtLoadKeyEx 335 | NtSetInformationDebugObject 336 | NtEnumerateSystemEnvironmentValuesEx 337 | NtAlpcCreateSecurityContext 338 | NtQueryOpenSubKeys 339 | NtDebugContinue 340 | NtQueryDriverEntryOrder 341 | NtSetInformationTransactionManager 342 | NtQueryBootEntryOrder 343 | NtPrivilegedServiceAuditAlarm 344 | NtMapUserPhysicalPagesScatter 345 | NtSetLowEventPair 346 | NtOpenThread 347 | NtFilterToken 348 | NtSetHighWaitLowEventPair 349 | NtPlugPlayGetDeviceInterfaceEnabled 350 | NtAccessCheckByTypeResultListAndAuditAlarm 351 | NtSetLdtEntries 352 | NtAlpcDeleteSectionView 353 | NtAlertThreadByThreadId 354 | NtDeleteDriverEntry 355 | NtFlushKey 356 | NtDisplayString 357 | NtGetCurrentProcessorNumber 358 | NtQueryVolumeInformationFile 359 | NtReadOnlyEnlistment 360 | NtLoadKey2 361 | NtUnlockVirtualMemory 362 | NtCreateDirectoryObjectEx 363 | NtReleaseMutant 364 | NtRecoverResourceManager 365 | NtCloseObjectAuditAlarm 366 | NtAllocateUuids 367 | NtUnloadKeyEx 368 | NtResetEvent 369 | NtResumeProcess 370 | NtSetTimer 371 | NtEnumerateValueKey 372 | NtQueryTimerResolution 373 | NtFreezeTransactions 374 | NtSetTimer2 375 | NtReadFileScatter 376 | NtSetSystemPowerState 377 | NtShutdownSystem 378 | NtCreateJobObject 379 | NtGetNextThread 380 | NtFreeUserPhysicalPages 381 | NtUnlockFile 382 | NtStartProfile 383 | NtAlpcSendWaitReceivePort 384 | NtAreMappedFilesTheSame 385 | NtAccessCheckByTypeAndAuditAlarm 386 | NtReadVirtualMemory 387 | NtAddAtomEx 388 | NtQueryDefaultUILanguage 389 | NtTestAlert 390 | NtSignalAndWaitForSingleObject 391 | NtVdmControl 392 | NtRemoveIoCompletionEx 393 | NtSetTimerEx 394 | NtOpenSession 395 | NtCancelSynchronousIoFile 396 | NtQueryDirectoryObject 397 | NtQueryEnvironmentVariableInfoEx 398 | NtSerializeBoot 399 | NtOpenResourceManager 400 | NtExtendSection 401 | NtMakeTemporaryObject 402 | NtCreateMutant 403 | NtSetInformationResourceManager 404 | NtWriteFile 405 | NtAlpcConnectPort 406 | NtSetDefaultLocale 407 | NtEnumerateTransactionObject 408 | NtOpenKeyEx 409 | NtNotifyChangeMultipleKeys 410 | NtRaiseHardError 411 | NtGetEnvironmentVariableEx 412 | NtWaitForAlertByThreadId 413 | NtQueryInformationProcess 414 | NtOpenTransactionManager 415 | NtLoadKey 416 | NtDuplicateToken 417 | NtSetHighEventPair 418 | NtMapUserPhysicalPages 419 | NtCreateWorkerFactory 420 | NtSetInformationToken 421 | NtAlpcImpersonateClientOfPort 422 | NtWaitLowEventPair 423 | NtTraceEvent 424 | NtSetDefaultHardErrorPort 425 | NtQueryInformationToken 426 | NtCreateIoCompletion 427 | NtSetInformationThread 428 | NtNotifyChangeDirectoryFile 429 | NtOpenEnlistment 430 | NtOpenProcessTokenEx 431 | NtUnmapViewOfSection 432 | NtReleaseWorkerFactoryWorker 433 | NtQueryInformationAtom 434 | NtAllocateReserveObject 435 | NtCreateProcess 436 | NtReplyWaitReplyPort 437 | NtNotifyChangeSession 438 | NtUnsubscribeWnfStateChange 439 | NtQueryInformationPort 440 | NtSetBootOptions 441 | NtReleaseKeyedEvent 442 | NtAlpcCreateSectionView 443 | NtQuerySecurityObject 444 | NtOpenThreadToken 445 | NtSetTimerResolution 446 | NtSetInformationEnlistment 447 | NtSetIRTimer 448 | NtOpenIoCompletion 449 | NtApphelpCacheControl 450 | NtReadFile 451 | NtQueryBootOptions 452 | NtInitializeRegistry 453 | NtOpenProcessToken 454 | NtEnumerateKey 455 | NtOpenJobObject 456 | xHalIommuInitialize 457 | NtWaitForWnfNotifications 458 | NtMajorVersion 459 | NtMinorVersion 460 | NtGetPlugPlayEvent 461 | NtCancelDeviceWakeupRequest 462 | NtRequestDeviceWakeup 463 | NtReleaseCMFViewOwnership 464 | NtAcquireCMFViewOwnership 465 | NtRequestWakeupLatency 466 | -------------------------------------------------------------------------------- /SystemCallService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7D3C3B13-8911-48C6-9B42-95DE79B34716} 8 | WinExe 9 | Properties 10 | SystemCallService 11 | SystemCallService 12 | v4.5 13 | 512 14 | false 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 1 26 | 2014.01.0.%2a 27 | false 28 | true 29 | true 30 | 30789494 31 | 32 | 33 | x64 34 | true 35 | full 36 | false 37 | bin\Debug\ 38 | DEBUG;TRACE 39 | prompt 40 | 4 41 | false 42 | 43 | 44 | x64 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | true 52 | 53 | 54 | D30FE9BA74CC0F70A30EE2AA7208104008340109 55 | 56 | 57 | true 58 | 59 | 60 | true 61 | 62 | 63 | true 64 | bin\x64\Debug\ 65 | DEBUG;TRACE 66 | full 67 | x64 68 | prompt 69 | MinimumRecommendedRules.ruleset 70 | true 71 | 72 | 73 | bin\x64\Release\ 74 | 75 | 76 | false 77 | true 78 | pdbonly 79 | x64 80 | prompt 81 | MinimumRecommendedRules.ruleset 82 | true 83 | false 84 | 0 85 | 86 | 87 | true 88 | bin\x86\Debug\ 89 | DEBUG;TRACE 90 | full 91 | x86 92 | prompt 93 | MinimumRecommendedRules.ruleset 94 | true 95 | 96 | 97 | bin\x86\Release\ 98 | true 99 | 1 100 | pdbonly 101 | x86 102 | prompt 103 | MinimumRecommendedRules.ruleset 104 | true 105 | false 106 | 107 | 108 | 109 | Component 110 | 111 | 112 | ProjectInstaller.cs 113 | 114 | 115 | True 116 | True 117 | SystemCallServiceSettings.settings 118 | 119 | 120 | 121 | Component 122 | 123 | 124 | SystemCallService.cs 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | SettingsSingleFileGenerator 135 | SystemCallServiceSettings.Designer.cs 136 | 137 | 138 | PreserveNewest 139 | 140 | 141 | PreserveNewest 142 | 143 | 144 | PreserveNewest 145 | 146 | 147 | PreserveNewest 148 | 149 | 150 | PreserveNewest 151 | 152 | 153 | PreserveNewest 154 | 155 | 156 | PreserveNewest 157 | 158 | 159 | PreserveNewest 160 | 161 | 162 | PreserveNewest 163 | 164 | 165 | PreserveNewest 166 | 167 | 168 | PreserveNewest 169 | 170 | 171 | PreserveNewest 172 | 173 | 174 | PreserveNewest 175 | 176 | 177 | PreserveNewest 178 | 179 | 180 | PreserveNewest 181 | 182 | 183 | PreserveNewest 184 | 185 | 186 | PreserveNewest 187 | 188 | 189 | PreserveNewest 190 | 191 | 192 | PreserveNewest 193 | 194 | 195 | PreserveNewest 196 | 197 | 198 | PreserveNewest 199 | 200 | 201 | PreserveNewest 202 | 203 | 204 | PreserveNewest 205 | 206 | 207 | PreserveNewest 208 | 209 | 210 | PreserveNewest 211 | 212 | 213 | 214 | 215 | False 216 | Microsoft .NET Framework 4.5 %28x86 and x64%29 217 | true 218 | 219 | 220 | False 221 | .NET Framework 3.5 SP1 Client Profile 222 | false 223 | 224 | 225 | False 226 | .NET Framework 3.5 SP1 227 | false 228 | 229 | 230 | 231 | 232 | ProjectInstaller.cs 233 | 234 | 235 | SystemCallService.cs 236 | 237 | 238 | 239 | 240 | PreserveNewest 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | packages\EntityFramework.6.1.2\lib\net45\EntityFramework.dll 249 | True 250 | 251 | 252 | packages\EntityFramework.6.1.2\lib\net45\EntityFramework.SqlServer.dll 253 | True 254 | 255 | 256 | packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.29\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll 257 | True 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | packages\System.Data.SQLite.Core.1.0.96.0\lib\net45\System.Data.SQLite.dll 266 | True 267 | 268 | 269 | packages\System.Data.SQLite.EF6.1.0.96.0\lib\net45\System.Data.SQLite.EF6.dll 270 | True 271 | 272 | 273 | packages\System.Data.SQLite.Linq.1.0.96.0\lib\net45\System.Data.SQLite.Linq.dll 274 | True 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 286 | 287 | 288 | 289 | 296 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /SystemCallService.cs: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 Ray Canzanese 2 | * email: rcanzanese@gmail.com 3 | * url: www.canzanese.com 4 | * 5 | * This file is part of SystemCallService. 6 | * 7 | * SystemCallService is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * SystemCallService is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with SystemCallService. If not, see . 19 | */ 20 | 21 | // TODO items 22 | // - break more functions out of the main class 23 | // - figure out if there is a easy way to incorporate symbol lookup 24 | 25 | 26 | // NOTE: You must manually set / unset this variable for 32 / 64 bit builds 27 | //#define X86 28 | 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Configuration; 33 | using System.Data.SQLite; 34 | using System.Diagnostics; 35 | using System.Globalization; 36 | using System.IO; 37 | using System.Linq; 38 | using System.Reflection; 39 | using System.Runtime.CompilerServices; 40 | using System.Runtime.InteropServices; 41 | using System.Security.Cryptography; 42 | using System.ServiceProcess; 43 | using System.Text; 44 | using System.Text.RegularExpressions; 45 | using System.Threading; 46 | using System.Timers; 47 | using Microsoft.Diagnostics.Tracing; 48 | using Microsoft.Diagnostics.Tracing.Parsers; 49 | using Microsoft.Diagnostics.Tracing.Parsers.Kernel; 50 | using Microsoft.Diagnostics.Tracing.Session; 51 | 52 | namespace SystemCallService 53 | { 54 | /// 55 | /// Class for the service, extends the base service class. No actual functionality is here other than handling requests. 56 | /// 57 | public partial class SystemCallService : ServiceBase 58 | { 59 | private Thread _thread; // Worker thread for running the service 60 | private SystemCallServiceLoop _scc; // System call counter object 61 | private bool _isRunning; // Keeps track of whether it is running to handle power events 62 | 63 | /// 64 | /// Initialization and establishes that the SCS handles power events 65 | /// 66 | public SystemCallService() 67 | { 68 | InitializeComponent(); 69 | CanHandlePowerEvent = true; 70 | } 71 | 72 | /// 73 | /// Handles hibernation events. 74 | /// 75 | /// Powerstatus passed in by SC 76 | /// true 77 | protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus) 78 | { 79 | EventLog.WriteEntry("Power Status Change -- " + powerStatus, EventLogEntryType.Warning); 80 | 81 | if (PowerBroadcastStatus.Suspend == powerStatus) 82 | { 83 | if (_isRunning) 84 | { 85 | EventLog.WriteEntry("Stopping for suspend.", EventLogEntryType.Warning); 86 | OnStop(); 87 | } 88 | else 89 | { 90 | EventLog.WriteEntry("Tried suspending but it was already stopped.", EventLogEntryType.Warning); 91 | } 92 | } 93 | 94 | // Start on resume. 95 | else if (PowerBroadcastStatus.ResumeSuspend == powerStatus || 96 | PowerBroadcastStatus.ResumeAutomatic == powerStatus) 97 | { 98 | if (_isRunning) 99 | { 100 | EventLog.WriteEntry("Tried resuming, but already running.", EventLogEntryType.Warning); 101 | } 102 | else 103 | { 104 | EventLog.WriteEntry("Resuming.", EventLogEntryType.Warning); 105 | OnStart(null); 106 | } 107 | } 108 | return true; 109 | } 110 | 111 | 112 | /// 113 | /// Called by SC when the service is started. Must return immediately. 114 | /// 115 | /// Passed by SC 116 | protected override void OnStart(string[] args) 117 | { 118 | _isRunning = true; 119 | 120 | // Sets the event log source so we can find us the in the application log 121 | EventLog.Source = "SystemCallService"; 122 | 123 | // Starts the worker thread that actually performs all the useful tasks 124 | _thread = new Thread(WorkerThreadFunc) 125 | { 126 | Name = "Main SystemCallService Worker Thread", 127 | IsBackground = true 128 | }; 129 | _thread.Start(); 130 | 131 | // Prints the path to the local configuration to the app event log. 132 | EventLog.WriteEntry( 133 | "Local Configuration Location:" + 134 | ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath, 135 | EventLogEntryType.Information); 136 | } 137 | 138 | /// 139 | /// Called by SC when service is stopped 140 | /// 141 | protected override void OnStop() 142 | { 143 | _isRunning = false; 144 | 145 | // Signal the thread to stop collecting data 146 | _scc.Stop(true); 147 | 148 | // Give the thread 10 seconds to stop gracefully. It does a lot of processing, so we are conservative with this etimate for now. 149 | if (_thread.Join(10000)) return; 150 | 151 | EventLog.WriteEntry("Internal error Stopping Service", EventLogEntryType.Error); 152 | _thread.Abort(); 153 | } 154 | 155 | /// 156 | /// Worker thread responsible for kicking off the data collection. Exits when the data collection is signalled by OnStop to stop. 157 | /// 158 | private void WorkerThreadFunc() 159 | { 160 | // Create a new SyscallCounter object with sampling periods from settings 161 | _scc = new SystemCallServiceLoop(EventLog); 162 | 163 | // Continuously restart the service until IsRunning is set to false 164 | while (_isRunning) 165 | { 166 | _scc.Start(); 167 | } 168 | } 169 | } 170 | 171 | /// 172 | /// Put host, process, and thread metadata in a SQLite database 173 | /// 174 | public class DatabaseInterface 175 | { 176 | //EventLog object for logging to the Application Event Log 177 | private readonly StreamWriter _debugLog; 178 | 179 | // Database connection 180 | private readonly SQLiteConnection _connection; 181 | 182 | // Everything is in one transaction 183 | private SQLiteTransaction _transaction; 184 | 185 | // Queries for adding processes and threads and a list of the column titles to expedite the query building. 186 | private readonly SQLiteCommand _processAdd; 187 | private readonly List _processColumns; 188 | private readonly SQLiteCommand _threadAdd; 189 | private readonly List _threadColumns; 190 | private readonly SQLiteCommand _processEnd; 191 | private readonly SQLiteCommand _threadEnd; 192 | 193 | /// 194 | /// Constructor 195 | /// 196 | /// Absolute path to the database file 197 | /// Handle to debug log 198 | public DatabaseInterface(string path, StreamWriter debugLog) 199 | { 200 | _debugLog = debugLog; 201 | 202 | // Create file 203 | SQLiteConnection.CreateFile(path); 204 | 205 | //Connect and open handle 206 | _connection = new SQLiteConnection("Data Source=" + path + ";Version=3;"); 207 | _connection.Open(); 208 | 209 | _transaction = _connection.BeginTransaction(); 210 | 211 | // Create table for processes 212 | using (SQLiteCommand genericCommand = _connection.CreateCommand()) 213 | { 214 | // Create process Table 215 | genericCommand.CommandText = "CREATE TABLE Processes (" + 216 | Properties.SystemCallServiceSettings.Default.ProcessTableStructure + ")"; 217 | genericCommand.ExecuteNonQuery(); 218 | _processAdd = SetupObjectQuery(typeof (ProcessInfo), "Processes", out _processColumns); 219 | 220 | // Create table for threads 221 | genericCommand.CommandText = "CREATE TABLE Threads (" + 222 | Properties.SystemCallServiceSettings.Default.ThreadTableStructure + ")"; 223 | genericCommand.ExecuteNonQuery(); 224 | genericCommand.Dispose(); 225 | } 226 | 227 | // Create command for thread and process endings 228 | _threadEnd = _connection.CreateCommand(); 229 | _threadEnd.CommandText = "UPDATE threads SET StopRelativeMsec=@StopRelativeMsec WHERE Guid=@Guid"; 230 | _threadEnd.Parameters.AddWithValue("@StopRelativeMsec", ""); 231 | _threadEnd.Parameters.AddWithValue("@Guid", ""); 232 | 233 | _processEnd = _connection.CreateCommand(); 234 | _processEnd.CommandText = "UPDATE processes SET StopRelativeMsec=@StopRelativeMsec WHERE Guid=@Guid"; 235 | _processEnd.Parameters.AddWithValue("@StopRelativeMsec", ""); 236 | _processEnd.Parameters.AddWithValue("@Guid", ""); 237 | 238 | _threadAdd = SetupObjectQuery(typeof (ThreadInfo), "Threads", out _threadColumns); 239 | 240 | // Commit all the table creations and starts a new transaction 241 | _transaction.Commit(); 242 | _transaction.Dispose(); 243 | _transaction = _connection.BeginTransaction(); 244 | } 245 | 246 | 247 | /// 248 | /// Update the thread end time. 249 | /// 250 | /// end time in ms 251 | /// thread guid 252 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 253 | public void UpdateThreadEnd(double mSec, string guid) 254 | { 255 | _threadEnd.Parameters["@StopRelativeMsec"].Value = mSec; 256 | _threadEnd.Parameters["@Guid"].Value = guid; 257 | _threadEnd.ExecuteNonQuery(); 258 | } 259 | 260 | /// 261 | /// Update the process end time. 262 | /// 263 | /// end time in ms 264 | /// process guid 265 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 266 | public void UpdateProcessEnd(double mSec, string guid) 267 | { 268 | _processEnd.Parameters["@StopRelativeMsec"].Value = mSec; 269 | _processEnd.Parameters["@Guid"].Value = guid; 270 | _processEnd.ExecuteNonQuery(); 271 | } 272 | 273 | /// 274 | /// Construct a query to use for adding properties of an object to the database. 275 | /// 276 | /// The object type that will be added 277 | /// The name of the table 278 | /// Output the names of the columns so we don't have to look them up every time. 279 | /// The sqlite command 280 | public SQLiteCommand SetupObjectQuery(Type type, string table, out List columns) 281 | { 282 | columns = new List(); 283 | foreach (var field in type.GetProperties()) 284 | { 285 | if (!field.Name.Contains("Flag") && !field.Name.Contains("InsertCommand")) 286 | // I have flags in the data structures that are only used internally and not added to database 287 | { 288 | columns.Add(field.Name); 289 | } 290 | } 291 | 292 | SQLiteCommand command = _connection.CreateCommand(); 293 | command.CommandText = "INSERT INTO " + table + "(" + String.Join(",", columns) + ") VALUES(@" + 294 | String.Join(",@", columns) + ")"; 295 | 296 | foreach (var column in columns) 297 | { 298 | command.Parameters.AddWithValue("@" + column, ""); 299 | } 300 | 301 | return command; 302 | } 303 | 304 | /// 305 | /// Add the properties of an object as a new entry into the table. 306 | /// 307 | /// The object containing data to add 308 | /// The name of the table 309 | /// The command prepared by SetupObjectQuery 310 | /// The name of the columns prepared by SetupObjectQuery 311 | /// True 312 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 313 | public bool AddObject(Object data, string table, SQLiteCommand command, List columns) 314 | { 315 | foreach (var column in columns) 316 | { 317 | command.Parameters["@" + column].Value = data.GetType().GetProperty(column).GetValue(data, null); 318 | } 319 | command.ExecuteNonQuery(); 320 | return true; 321 | } 322 | 323 | /// 324 | /// Add a thread to the thread table. 325 | /// 326 | /// 327 | /// 328 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 329 | public bool AddThread(ThreadInfo thread) 330 | { 331 | AddObject(thread, "Threads", _threadAdd, _threadColumns); 332 | return true; 333 | } 334 | 335 | /// 336 | /// Add a process to the process table. 337 | /// 338 | /// 339 | /// 340 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 341 | public bool AddProcess(ProcessInfo process) 342 | { 343 | AddObject(process, "Processes", _processAdd, _processColumns); 344 | return true; 345 | } 346 | 347 | /// 348 | /// Add system information 349 | /// 350 | /// System information structure 351 | /// 352 | public bool AddSystemInformation(SystemInformation sysinfo) 353 | { 354 | using (var localCommand = _connection.CreateCommand()) 355 | { 356 | //Create table 357 | localCommand.CommandText = "CREATE TABLE SystemInfo (" + 358 | Properties.SystemCallServiceSettings.Default.SystemInfoTableStructure + ")"; 359 | localCommand.ExecuteNonQuery(); 360 | 361 | // Setup Query 362 | List systemInfoColumns; 363 | SQLiteCommand systemInfoAdd = SetupObjectQuery(typeof (SystemInformation), "SystemInfo", 364 | out systemInfoColumns); 365 | 366 | // Execute query 367 | AddObject(sysinfo, "SystemInfo", systemInfoAdd, systemInfoColumns); 368 | } 369 | return true; 370 | } 371 | 372 | 373 | /// 374 | /// Commit the current transaction and create a new one. 375 | /// 376 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 377 | public void Commit() 378 | { 379 | try 380 | { 381 | _transaction.Commit(); 382 | _transaction.Dispose(); 383 | _transaction = _connection.BeginTransaction(); 384 | } 385 | catch (Exception e) 386 | { 387 | _debugLog.WriteLine("Commit error: " + e); 388 | } 389 | } 390 | 391 | /// 392 | /// Commit transaction, dispose all commands, and close the connection to the database 393 | /// 394 | public void CloseConnection() 395 | { 396 | Commit(); 397 | 398 | _processAdd.Dispose(); 399 | _threadAdd.Dispose(); 400 | _processEnd.Dispose(); 401 | _threadEnd.Dispose(); 402 | 403 | try 404 | { 405 | _transaction.Dispose(); 406 | } 407 | catch (Exception e) 408 | { 409 | _debugLog.WriteLine("CloseError: " + e); 410 | } 411 | try 412 | { 413 | _connection.Close(); 414 | _connection.Dispose(); 415 | } 416 | catch (Exception e) 417 | { 418 | _debugLog.WriteLine("CloseError: " + e); 419 | } 420 | } 421 | } 422 | 423 | /// 424 | /// Generic class for storing information about a process or thread 425 | /// 426 | public class Info 427 | { 428 | public String Guid { get; set; } // GUID to identify the data table. 429 | public double DeletionFlag; // Indicates when object was flagged for deletion 430 | public bool Deleted; // Indicates that that it has been deleted 431 | public double StartRelativeMSec { get; set; } // Time the process started as RelativeMSec count 432 | public DateTime Start { get; set; } // Time the process was started 433 | public double StopRelativeMSec { get; set; } // Time the process started as RelativeMSec count 434 | public SystemCallTracer Counter; // Where the tracing and counting occurs 435 | } 436 | 437 | /// 438 | /// Information about active processes 439 | /// 440 | public class ProcessInfo : Info 441 | { 442 | public string Name; // Just the executable name 443 | public int Pid { get; set; } 444 | public long ProcessKey; // I don't know whether this is unique -- currently unused 445 | public string CommandLine { get; set; } // Full path used to launch the process 446 | public string ImageFileName { get; set; } // Same as executable name? 447 | public string KernelImageFileName; // Same as executable name? 448 | public int ParentId { get; set; } // Parent PID 449 | public uint TotalThreads; // Total number of child threads 450 | public uint ActiveThreads; // Number of threads currently executing 451 | public double LastActive; // Time it was last CSWITCHED off a core. 452 | public string Md5 { get; set; } 453 | } 454 | 455 | /// 456 | /// Information about the host 457 | /// 458 | public class SystemInformation 459 | { 460 | public string NtoskrnlVersion { get; set; } // ntoskrnl.exe file version 461 | public string NtoskrnlMd5 { get; set; } // ntoskrnl.exe file version 462 | public int Cores { get; set; } // Number of logical processor cores 463 | public string Hostname { get; set; } // hostname 464 | public double HostSampling { get; set; } // System sampling period 465 | public double ProcessSampling { get; set; } // Process sampling period 466 | public double ThreadSampling { get; set; } // Thread Sampling period 467 | public long HostTrace { get; set; } // System sampling period 468 | public long ProcessTrace { get; set; } // Process sampling period 469 | public long ThreadTrace { get; set; } // Thread Sampling period 470 | } 471 | 472 | /// 473 | /// Information about active threads 474 | /// 475 | public class ThreadInfo : Info 476 | { 477 | public int Pid { get; set; } // PID to which the thread belongs 478 | public double PidStartRelativeMSec { get; set; } // Process start time as RelativeMSec 479 | public int Tid { get; set; } 480 | public String ProcessGuid { get; set; } // Process GUID so we can do joins 481 | public double LastActive; // Last time it was CSWITCHed out 482 | public bool IsActive; // Whether it is currently active on a core 483 | } 484 | 485 | /// 486 | /// Perform system call traces at the host, process, and thread levels 487 | /// 488 | public class SystemCallTracer 489 | { 490 | private readonly string _filename; 491 | 492 | // TODO: Implement these or remove them. 493 | private double _startTimeMs; 494 | private StreamWriter _debugLog; 495 | 496 | // For saving raw traces 497 | private long _maxTrace = -1; 498 | private FileStream _traceOutputFile; 499 | private BinaryWriter _traceWriter; 500 | private bool _fullTrace; 501 | private long _traceLength; 502 | private bool _traceFinished = true; 503 | 504 | /// 505 | /// Create the tracer. 506 | /// 507 | /// Filename to store the trace 508 | /// Debug logger 509 | public SystemCallTracer(string filename, StreamWriter debugLog) 510 | { 511 | _filename = filename; 512 | _debugLog = debugLog; 513 | } 514 | 515 | 516 | 517 | /// 518 | /// Initialize a trace 519 | /// 520 | /// Maximum number of system calls. Negative number indicates no limit. 521 | /// Start time of trace in ms. 522 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 523 | public void InitializeFullTrace(long maxTrace, double timeMs) 524 | { 525 | _traceOutputFile = File.Open(_filename + "_trace", FileMode.Create); 526 | _traceWriter = new BinaryWriter(_traceOutputFile); 527 | _maxTrace = maxTrace; 528 | _traceFinished = false; 529 | _fullTrace = true; 530 | _startTimeMs = timeMs; 531 | } 532 | 533 | /// 534 | /// Add a system call to the trace 535 | /// 536 | /// system call index 537 | /// time of the call 538 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 539 | public void Add(ushort syscall, double timeMs) 540 | { 541 | if (!_fullTrace) return; 542 | 543 | if (_maxTrace >= 0 && _traceLength >= _maxTrace) 544 | { 545 | if (_traceFinished) return; 546 | _traceFinished = true; 547 | _traceWriter.Flush(); 548 | _traceWriter.Close(); 549 | _traceOutputFile.Close(); 550 | //DebugLog.WriteLine("TOTAL_TRACE_TIME=" + (time - StartTimeMs)); 551 | return; 552 | } 553 | _traceWriter.Write(syscall); 554 | _traceLength += 1; 555 | } 556 | 557 | /// 558 | /// End the trace and close the file. 559 | /// 560 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 561 | public void Close() 562 | { 563 | if (_traceFinished) return; 564 | _traceFinished = true; 565 | _traceWriter.Flush(); 566 | _traceWriter.Close(); 567 | _traceOutputFile.Close(); 568 | } 569 | } 570 | 571 | /// 572 | /// Service loop and primary interface with ETW 573 | /// 574 | public class SystemCallServiceLoop 575 | { 576 | // Regex for sanitizing the command line -- either it is quoted, contains spaces and ends with exe, or contains no spaces. This covers all cases seen on the development machine. 577 | private readonly Regex _pathRegex = new Regex("(\"[^\"]*\"|.*?\\.exe|[^ ]*)"); 578 | 579 | // List of settings we want to print out in debug log / get from web 580 | private readonly string[] _properties = 581 | { 582 | "AutoResetMs", "TracePerProcess", "TracePerThread", "MaxTraceSyscalls", 583 | "Verbosity", "ScrubCommandLine", "AnonymizeHostname" 584 | }; 585 | 586 | // Private copies of settings for speed. I don't know whether these are actually faster. 587 | private readonly bool _traceHostLevel = Properties.SystemCallServiceSettings.Default.TraceHostLevel; 588 | private readonly bool _tracePerThread = Properties.SystemCallServiceSettings.Default.TracePerThread; 589 | private readonly bool _tracePerProcess = Properties.SystemCallServiceSettings.Default.TracePerProcess; 590 | private readonly long _maxTraceSyscalls = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls; 591 | private readonly int _verbosity = Properties.SystemCallServiceSettings.Default.Verbosity; 592 | private readonly double _commitInterval = Properties.SystemCallServiceSettings.Default.CommitInterval; 593 | private readonly bool _scrubCommandLine = Properties.SystemCallServiceSettings.Default.ScrubCommandLine; 594 | private readonly string _dataDirectory = Properties.SystemCallServiceSettings.Default.DataDirectory; 595 | private readonly double _processDeletionDelay = Properties.SystemCallServiceSettings.Default.ProcessDeletionDelay; //ms 596 | private readonly double _minBackoff = Properties.SystemCallServiceSettings.Default.MinBackoff; 597 | private double _threadDeletionDelay = Properties.SystemCallServiceSettings.Default.ThreadDeletionDelay; //ms 598 | 599 | // Counting system call tuples 600 | private SystemCallTracer _systemWideCounter; 601 | 602 | // System call list 603 | private List _syscallNameList; 604 | 605 | //Code profiling 606 | private readonly bool _profileCode = Properties.SystemCallServiceSettings.Default.ProfileCode; 607 | private readonly Dictionary _codeProfileTimers = new Dictionary(); 608 | private readonly Dictionary _codeProfileCounters = new Dictionary(); 609 | 610 | private readonly string[] _codeProfileKeys = 611 | { 612 | "Commit", "Syscall", "ProcessStartTable", "WriteProcessData", "ProcessDeletionQueue", "ThreadDeletionQueue", 613 | "ContextSwitch", "ContextSwitch1", "ContextSwitch2", "ContextSwitch3", "Database.Commit", 614 | "WriteProcessDataInsert", "CreateTable", "WriteSystemData", "ProcessStart", "ProcessStop", "ThreadStart", 615 | "ThreadStop", "CreateCommand", "InsertCommandClone", "InsertCommandNew" 616 | }; 617 | 618 | // Last time we checked for thread and process deletion 619 | private double _lastDeletionCheck; 620 | 621 | // System information 622 | private SystemInformation _systemInfo; 623 | 624 | // End service flag 625 | private bool _endService; 626 | 627 | // Timer to trigger automatic restarts 628 | private readonly System.Timers.Timer _resetTimer; 629 | 630 | // Database connection 631 | private DatabaseInterface _database; 632 | 633 | // For timing the code 634 | private readonly Stopwatch _timer = new Stopwatch(); // Keeps track of processing lag. 635 | 636 | // For keeping track of how much time each thread has been active since last cswitch 637 | private double[] _lastCSwitch; 638 | 639 | // Dict for active threads, indexed by PID then TID 640 | private class ThreadDict : Dictionary{} 641 | private class ProcessThreadDict : Dictionary{}; 642 | 643 | //Queue for creating tables 644 | private readonly Queue _tableCreations = new Queue(); 645 | 646 | // Queue for deleting processes and threads 647 | private readonly List _processesToDelete = new List(); 648 | private readonly List _threadsToDelete = new List(); 649 | 650 | // A Dictionary of active threads by process [PID][TID] 651 | private readonly ProcessThreadDict _activeThreadsByProcess = new ProcessThreadDict(); 652 | 653 | // Dict for unknown threads, indexed by TID 654 | private readonly ThreadDict _unkownThreads = new ThreadDict(); 655 | 656 | // Dict for active processes, indexed by PID 657 | private readonly Dictionary _activeProcesses = new Dictionary(); 658 | 659 | //EventLog object for logging to the Application Event Log 660 | private readonly EventLog _eventLog; 661 | 662 | // Data directory location, used for generating paths to various files 663 | private readonly string _rootPath; 664 | private readonly string _tempPath; 665 | private string _dataSubFolder; 666 | 667 | // Maps from the addresses to some set of integers so we can do array indexing quickly and easily 668 | private int[] _ntMap; 669 | private ulong _ntLowestAddress; 670 | private ulong _ntMaxAddress; 671 | 672 | // Number of logical processors 673 | private int _logicalProcessorCount; 674 | 675 | // File to store all of our debug messages 676 | private StreamWriter _debugLog; 677 | 678 | // Event tracing session 679 | private TraceEventSession _eventTracingSession; 680 | 681 | // Place to keep track of what process and thread on each processor core 682 | private int[] _processorActiveThreads; 683 | private int[] _processorActiveProcesses; 684 | 685 | // Default values for processors. Used for convenience 686 | private const int DefaultProcessorValue = -2; 687 | private const int UnknownPid = -1; 688 | private const int IdlePid = 0; 689 | 690 | // Address of the Kenrel 691 | private UInt64 _ntKernelAddress; 692 | private String _ntKernelImageName; 693 | 694 | // Track the last time the database changes were committed 695 | private double _lastCommit = -100; 696 | 697 | // DLL imports for the functions that we use to get the base addresses of the kernel modules. 698 | // The precompiler directives handle the 32 bit vs. 64 distinction 699 | [DllImport("psapi")] 700 | private static extern bool EnumDeviceDrivers( 701 | #if X86 702 | [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] UInt32[] ddAddresses, 703 | #else 704 | [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In] [Out] UInt64[] ddAddresses, 705 | #endif 706 | UInt32 arraySizeBytes, 707 | [MarshalAs(UnmanagedType.U4)] out UInt32 bytesNeeded 708 | ); 709 | 710 | [DllImport("psapi")] 711 | private static extern int GetDeviceDriverBaseName( 712 | #if X86 713 | UInt32 ddAddress, 714 | #else 715 | UInt64 ddAddress, 716 | #endif 717 | StringBuilder ddBaseName, 718 | int baseNameStringSizeChars 719 | ); 720 | 721 | /// 722 | /// Set the tracer parameters. 723 | /// 724 | /// EventLog object 725 | public SystemCallServiceLoop(EventLog el) 726 | { 727 | // Keep an instance variable of the event log -- used for crash logging 728 | _eventLog = el; 729 | 730 | // Keep track of where this is executing from and where we store the data 731 | _rootPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); 732 | _tempPath = Path.GetTempPath(); 733 | 734 | // Setup a timer to automatically restart logging 735 | _resetTimer = new System.Timers.Timer {AutoReset = false}; 736 | _resetTimer.Elapsed += ResetTimerEvent; 737 | } 738 | 739 | /// 740 | /// Compute the MD5 of the kernel. 741 | /// 742 | /// Filename of kernel (varies for different versions of wWndows). 743 | /// 744 | private string ComputeMd5(string kernelFileName) 745 | { 746 | string md5Sum; 747 | 748 | // Debug print MD5sum of the kernel 749 | using (var md5 = MD5.Create()) 750 | { 751 | using ( 752 | var stream = 753 | File.OpenRead(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), 754 | kernelFileName))) 755 | { 756 | md5Sum = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(); 757 | } 758 | } 759 | return md5Sum; 760 | } 761 | 762 | /// 763 | /// Load the system call addresses. 764 | /// 765 | /// Filename of the kernel 766 | /// Kernel version 767 | /// Filename that lists desired system calls to trace 768 | /// List of the system calls (out) 769 | /// Base address of kernel (out) 770 | /// Max address of system call (out) 771 | /// Used as offset for GDI tracing to prevent index collisions with multiple kernel files. 772 | /// Base address of the kernel. 773 | /// The map from addresses to indices 774 | private int[] LoadAddressMaps(String kernelFileName, String version, String sensorFileName, 775 | out List sensorList, out ulong baseAddress, out ulong maxAddress, int indexBase, ulong kernelBase) 776 | { 777 | // Load the symbol table and build a dict, where the sensor names are the keys 778 | string[] lines; 779 | string md5Sum = ComputeMd5(kernelFileName); 780 | _debugLog.WriteLine("KERNEL MD5: " + md5Sum); 781 | 782 | // This is an abuse of naming, but because they are identified by version and MD5, I am not going to differentiate among different kernel image file names 783 | string subdirectory = "ntoskrnl.exe"; 784 | string localFilename = Path.Combine(_rootPath, Properties.SystemCallServiceSettings.Default.SymbolSubfolder, 785 | subdirectory, version + "_" + md5Sum + ".symbols"); 786 | 787 | try 788 | { 789 | lines = File.ReadAllLines(localFilename); 790 | } 791 | catch 792 | { 793 | _debugLog.WriteLine("Kernel symbols not held locally. Checking online"); 794 | _debugLog.WriteLine("NtVersion: " + _systemInfo.NtoskrnlVersion); 795 | _debugLog.WriteLine("Local Filename: " + localFilename); 796 | _debugLog.Flush(); 797 | 798 | File.Copy(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), kernelFileName), 799 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, 800 | _dataSubFolder, version + "_" + md5Sum + ".binary")); 801 | maxAddress = 0; 802 | baseAddress = 0; 803 | sensorList = null; 804 | return null; 805 | } 806 | 807 | Dictionary symbolTable = new Dictionary(); 808 | 809 | // First group is the address, second group is the name; 810 | Regex re = new Regex(@"[ ]+[0-9a-f]+[ ]+([0-9a-f]+)[ ]+:+[ ]+(.*)"); 811 | 812 | foreach (string line in lines) 813 | { 814 | Match match = re.Match(line); 815 | 816 | if (match.Success) 817 | { 818 | symbolTable[match.Groups[2].Value] = UInt64.Parse(match.Groups[1].Value, NumberStyles.HexNumber) - 819 | UInt64.Parse("1000000", NumberStyles.HexNumber); 820 | // corrects dbh.exe offset default. 821 | } 822 | } 823 | 824 | // Load the sensor list to figure out the offsets 825 | lines = File.ReadAllLines(Path.Combine(_rootPath, sensorFileName)); 826 | 827 | // Creates a list of the sensor names as a list of strings and the map from the addresses to the indices 828 | sensorList = new List(); 829 | 830 | List temp = new List(); 831 | 832 | // Convert the list of addresses to a map. 833 | foreach (string line in lines) 834 | { 835 | sensorList.Add(line); 836 | try 837 | { 838 | var offset = symbolTable[line]; 839 | temp.Add(offset); 840 | } 841 | catch 842 | { 843 | _debugLog.WriteLine("Sensor not found in symbol table: " + line); 844 | } 845 | } 846 | 847 | baseAddress = temp.Min() + kernelBase; 848 | maxAddress = temp.Max() + kernelBase; 849 | int[] sensorMap = new int[1 + (temp.Max() - temp.Min())]; 850 | 851 | for (int i = 0; i < sensorMap.Count(); i++) 852 | { 853 | sensorMap[i] = -1; 854 | } 855 | 856 | for (int i = 0; i < temp.Count; i++) 857 | { 858 | sensorMap[(temp[i] - temp.Min())] = i + indexBase; 859 | } 860 | 861 | // Debugging information 862 | _debugLog.WriteLine("Base: {0:X}", kernelBase); 863 | _debugLog.WriteLine("Min: {0:X}", temp.Min()); 864 | _debugLog.WriteLine("Max: {0:X}", temp.Max()); 865 | _debugLog.WriteLine("baseAddress: {0:X}", baseAddress); 866 | _debugLog.WriteLine("maxAddress: {0:X}", maxAddress); 867 | 868 | return sensorMap; 869 | } 870 | 871 | /// 872 | /// Get the hostname or the anonymized identifier. 873 | /// 874 | /// hostname or anonymized identifier 875 | private string GetHostname() 876 | { 877 | string hostname; 878 | if (Properties.SystemCallServiceSettings.Default.AnonymizeHostname) 879 | { 880 | if (Properties.SystemCallServiceSettings.Default.HostIdentifier == "None") 881 | { 882 | Properties.SystemCallServiceSettings.Default.HostIdentifier = Path.GetRandomFileName(); 883 | Properties.SystemCallServiceSettings.Default.Save(); 884 | } 885 | hostname = Properties.SystemCallServiceSettings.Default.HostIdentifier; 886 | } 887 | else 888 | { 889 | hostname = Environment.MachineName; 890 | } 891 | return hostname; 892 | } 893 | 894 | 895 | /// 896 | /// Ges system information and save it in the database 897 | /// 898 | private void GetSystemInformation() 899 | { 900 | // Anonymize the hostname (if necessary) by generating random string instead and saving it in properties 901 | string hostname = GetHostname(); 902 | 903 | 904 | // Creates object to hold system info and populates it 905 | _systemInfo = new SystemInformation 906 | { 907 | Cores = Environment.ProcessorCount, 908 | NtoskrnlVersion = 909 | FileVersionInfo.GetVersionInfo( 910 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), _ntKernelImageName)) 911 | .ProductVersion, 912 | NtoskrnlMd5 = ComputeMd5(_ntKernelImageName), 913 | Hostname = hostname, 914 | ThreadSampling = 0, 915 | ProcessSampling = 0, 916 | HostSampling = 0, 917 | ThreadTrace = 0, 918 | ProcessTrace = 0, 919 | HostTrace = 0 920 | }; 921 | 922 | if (Properties.SystemCallServiceSettings.Default.TracePerThread) 923 | { 924 | _systemInfo.ThreadTrace = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls; 925 | } 926 | if (Properties.SystemCallServiceSettings.Default.TracePerProcess) 927 | { 928 | _systemInfo.ProcessTrace = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls; 929 | } 930 | if (Properties.SystemCallServiceSettings.Default.TraceHostLevel) 931 | { 932 | _systemInfo.HostTrace = 1; 933 | } 934 | 935 | // Save logical processor count because we use it during tracing 936 | _logicalProcessorCount = _systemInfo.Cores; 937 | 938 | // Add to database 939 | _database.AddSystemInformation(_systemInfo); 940 | } 941 | 942 | 943 | /// 944 | /// Wrapper for regular starts. 945 | /// 946 | /// data from trace event 947 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 948 | private void ProcessStart(TraceEvent data) 949 | { 950 | ProcessStartHelper(data, false); 951 | } 952 | 953 | /// 954 | /// Wrapper for dc starts. 955 | /// 956 | /// data from trace event 957 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 958 | private void ProcessDcStart(TraceEvent data) 959 | { 960 | ProcessStartHelper(data, true); 961 | } 962 | 963 | /// 964 | /// Get the full path of anexecutable image. 965 | /// 966 | /// 967 | /// the path 968 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 969 | public static string GetFullPath(string fileName) 970 | { 971 | // Trim surrounding quotes 972 | string path = fileName.Trim('\"'); 973 | 974 | // If it already exists, just return it. 975 | if (File.Exists(path)) 976 | return Path.GetFullPath(path); 977 | 978 | // If there isn't a dot, try adding an extension 979 | if (!path.Contains('.')) 980 | { 981 | path = path + ".exe"; 982 | if (File.Exists(path)) 983 | return Path.GetFullPath(path); 984 | } 985 | 986 | // If there is a %, try expanding environment variables 987 | // If there isn't a dot, try adding an extension 988 | if (path.Contains('%')) 989 | { 990 | path = Environment.ExpandEnvironmentVariables(path); 991 | if (File.Exists(path)) 992 | return Path.GetFullPath(path); 993 | } 994 | 995 | // This appears at the beginning of some strings 996 | if (path.Contains(@"\??\")) 997 | { 998 | path = path.Replace(@"\??\", ""); 999 | if (File.Exists(path)) 1000 | return Path.GetFullPath(path); 1001 | } 1002 | 1003 | // If there aren't any slashes, check the environment PATH 1004 | if (!path.Contains(@"\")) 1005 | { 1006 | var values = Environment.GetEnvironmentVariable("PATH"); 1007 | if (values == null) return null; 1008 | foreach (var t in values.Split(';')) 1009 | { 1010 | var fullPath = Path.Combine(t, fileName); 1011 | if (File.Exists(fullPath)) 1012 | return fullPath; 1013 | } 1014 | } 1015 | 1016 | return null; 1017 | } 1018 | 1019 | 1020 | /// 1021 | /// When a process starts, add the process and the information about the process to the active processes dict and create a dict of threads for the process 1022 | /// 1023 | /// The trace event data 1024 | /// True if a DC start 1025 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1026 | private void ProcessStartHelper(TraceEvent data, bool dcStart) 1027 | { 1028 | if (_profileCode) 1029 | { 1030 | _codeProfileCounters["ProcessStart"] += 1; 1031 | _codeProfileTimers["ProcessStart"].Start(); 1032 | } 1033 | 1034 | ProcessTraceData procData = (ProcessTraceData) data; 1035 | 1036 | // We don't care about the system idle service. We know it is there and that it does nothing. 1037 | if (procData.ProcessID == IdlePid) 1038 | { 1039 | if (_profileCode) 1040 | { 1041 | _codeProfileTimers["ProcessStart"].Stop(); 1042 | } 1043 | return; 1044 | } 1045 | 1046 | // Scrub command line -- take away the arguments 1047 | String commandLine; 1048 | String scrubbedCommandLine; 1049 | Match m = _pathRegex.Match(procData.CommandLine); 1050 | if (m.Success) 1051 | { 1052 | scrubbedCommandLine = m.Value; 1053 | } 1054 | else 1055 | { 1056 | scrubbedCommandLine = ""; 1057 | } 1058 | 1059 | if (_scrubCommandLine) 1060 | { 1061 | commandLine = scrubbedCommandLine; 1062 | } 1063 | else 1064 | { 1065 | commandLine = procData.CommandLine; 1066 | } 1067 | 1068 | // checksum the image if possible. Checks existence first to avoid unnecessary error handling overhead. 1069 | string md5Sum = ""; 1070 | if (!dcStart) 1071 | { 1072 | try 1073 | { 1074 | string actualPath = GetFullPath(scrubbedCommandLine); 1075 | 1076 | if (actualPath != null) 1077 | { 1078 | using ( 1079 | FileStream fs = new FileStream(actualPath, FileMode.Open, FileAccess.Read, 1080 | FileShare.ReadWrite)) 1081 | { 1082 | using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider()) 1083 | { 1084 | byte[] hash = md5.ComputeHash(fs); 1085 | StringBuilder buf = new StringBuilder(2*hash.Length); 1086 | foreach (byte b in hash) 1087 | { 1088 | buf.AppendFormat("{0:X2}", b); 1089 | } 1090 | md5Sum = buf.ToString(); 1091 | } 1092 | } 1093 | } 1094 | } 1095 | catch (Exception e) 1096 | { 1097 | _debugLog.WriteLine("ERROR on " + scrubbedCommandLine); 1098 | _debugLog.WriteLine(e); 1099 | } 1100 | } 1101 | 1102 | //Create the process info struct 1103 | ProcessInfo newProcess = new ProcessInfo 1104 | { 1105 | Name = data.ProcessName, 1106 | Pid = data.ProcessID, 1107 | ProcessKey = (long) procData.UniqueProcessKey, 1108 | CommandLine = commandLine, 1109 | ImageFileName = procData.ImageFileName, 1110 | KernelImageFileName = procData.KernelImageFileName, 1111 | ParentId = procData.ParentID, 1112 | Start = data.TimeStamp, 1113 | StartRelativeMSec = data.TimeStampRelativeMSec, 1114 | Guid = Guid.NewGuid().ToString("N"), 1115 | Counter = null, 1116 | Md5 = md5Sum 1117 | }; 1118 | 1119 | // Write a debug message indicating that a new process started 1120 | if (_verbosity >= 3) 1121 | { 1122 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1123 | data.TimeStampRelativeMSec + " " + "Process Start:" + newProcess.Name + 1124 | " " + newProcess.CommandLine + " " + newProcess.Pid); 1125 | } 1126 | 1127 | // If we already Have the PID in the active process lists but it has been marked for deletion, lets try to force the deletion. 1128 | if (_activeProcesses.ContainsKey(data.ProcessID)) 1129 | { 1130 | if (_verbosity >= 1) 1131 | { 1132 | _debugLog.WriteLine("WARNING: Process ID already exists. " + data.ProcessID); 1133 | _debugLog.WriteLine("Deletion flag: " + _activeProcesses[data.ProcessID].DeletionFlag); 1134 | } 1135 | 1136 | if (_activeProcesses[data.ProcessID].DeletionFlag > 0) 1137 | { 1138 | foreach (var thread in _activeThreadsByProcess[data.ProcessID]) 1139 | { 1140 | thread.Value.DeletionFlag = data.TimeStampRelativeMSec - (_threadDeletionDelay*2); 1141 | } 1142 | _activeProcesses[data.ProcessID].DeletionFlag = data.TimeStampRelativeMSec - 1143 | (_processDeletionDelay*2); 1144 | 1145 | ThreadDeletionQueue(data); 1146 | ProcessDeletionQueue(data); 1147 | 1148 | if (_activeProcesses.ContainsKey(data.ProcessID)) 1149 | { 1150 | _debugLog.WriteLine("Error: Process ID already exists. " + data.ProcessID); 1151 | _debugLog.WriteLine("Deletion flag: " + _activeProcesses[data.ProcessID].DeletionFlag); 1152 | throw new Exception("Duplicate process disaster despite our correction efforts"); 1153 | } 1154 | } 1155 | } 1156 | 1157 | // Add Process to active process list 1158 | _activeProcesses[data.ProcessID] = newProcess; 1159 | 1160 | // Add Process to active threads list 1161 | _activeThreadsByProcess[data.ProcessID] = new ThreadDict(); 1162 | 1163 | // Create a new tracker 1164 | newProcess.Counter = 1165 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newProcess.Guid), _debugLog); 1166 | if (!dcStart && (_tracePerProcess)) 1167 | { 1168 | newProcess.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec); 1169 | } 1170 | 1171 | // Add to database 1172 | if (_profileCode) 1173 | { 1174 | _codeProfileCounters["CreateTable"] += 1; 1175 | _codeProfileTimers["CreateTable"].Start(); 1176 | } 1177 | 1178 | _database.AddProcess(newProcess); 1179 | 1180 | if (_profileCode) 1181 | { 1182 | _codeProfileTimers["CreateTable"].Stop(); 1183 | } 1184 | if (_profileCode) 1185 | { 1186 | _codeProfileTimers["ProcessStart"].Stop(); 1187 | } 1188 | } 1189 | 1190 | /// 1191 | /// Handle process stop events 1192 | /// 1193 | /// Trace event data 1194 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1195 | private void ProcessStop(TraceEvent data) 1196 | { 1197 | if (_profileCode) 1198 | { 1199 | _codeProfileCounters["ProcessStop"] += 1; 1200 | _codeProfileTimers["ProcessStop"].Start(); 1201 | } 1202 | 1203 | int pid = data.ProcessID; 1204 | 1205 | if (_verbosity >= 3) 1206 | { 1207 | _debugLog.WriteLine("Process Stop " + pid); 1208 | } 1209 | 1210 | // Ignore the idle PID because we never created an object for it 1211 | if (pid == IdlePid) 1212 | { 1213 | if (_profileCode) 1214 | { 1215 | _codeProfileTimers["ProcessStop"].Stop(); 1216 | } 1217 | return; 1218 | } 1219 | 1220 | // We were receiving DCSTOP events with no corresponding starts 1221 | if (!_activeProcesses.ContainsKey(pid)) 1222 | { 1223 | _debugLog.WriteLine("Process missing from dict"); 1224 | if (_endService) 1225 | { 1226 | _debugLog.WriteLine("Probably a DCSTOP, ignoring"); 1227 | return; 1228 | } 1229 | } 1230 | 1231 | //Get process info 1232 | ProcessInfo stoppingProcess = _activeProcesses[pid]; 1233 | 1234 | if (_verbosity >= 3) 1235 | { 1236 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1237 | data.TimeStampRelativeMSec + " " + "Process Stop: " + 1238 | stoppingProcess.Name + " " + stoppingProcess.Pid); 1239 | } 1240 | 1241 | // Set the stop time 1242 | stoppingProcess.StopRelativeMSec = data.TimeStampRelativeMSec; 1243 | 1244 | // Update the process end time in the database 1245 | _database.UpdateProcessEnd(stoppingProcess.StopRelativeMSec, stoppingProcess.Guid); 1246 | 1247 | // Flag for deletion 1248 | stoppingProcess.DeletionFlag = data.TimeStampRelativeMSec; 1249 | 1250 | // Put it in the deletion queue 1251 | _processesToDelete.Add(stoppingProcess); 1252 | 1253 | if (_profileCode) 1254 | { 1255 | _codeProfileTimers["ProcessStop"].Stop(); 1256 | } 1257 | } 1258 | 1259 | 1260 | /// 1261 | /// Wrapper for regular thread starts 1262 | /// 1263 | /// 1264 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1265 | private void ThreadStart(TraceEvent data) 1266 | { 1267 | ThreadStartHelper(data, false); 1268 | } 1269 | 1270 | 1271 | /// 1272 | /// Wrapper for dc thread starts 1273 | /// 1274 | /// 1275 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1276 | private void ThreadDcStart(TraceEvent data) 1277 | { 1278 | ThreadStartHelper(data, true); 1279 | } 1280 | 1281 | 1282 | /// 1283 | /// Process thread starts 1284 | /// 1285 | /// Trace event data 1286 | /// True if DC start 1287 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1288 | private void ThreadStartHelper(TraceEvent data, bool dcStart) 1289 | { 1290 | if (_profileCode) 1291 | { 1292 | _codeProfileCounters["ThreadStart"] += 1; 1293 | _codeProfileTimers["ThreadStart"].Start(); 1294 | } 1295 | 1296 | ThreadTraceData threadData = (ThreadTraceData) data; 1297 | int tid = data.ThreadID; 1298 | 1299 | if (_verbosity >= 4) 1300 | { 1301 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1302 | data.TimeStampRelativeMSec + "Thread start " + tid + 1303 | " for pid " + data.ProcessID + " " + threadData.ProcessID); 1304 | } 1305 | 1306 | // system idle process has as many threads as there are cores, all with diplicate Tid and Pid 0. We ignore these. 1307 | if (tid == 0 && data.ProcessID == 0) 1308 | { 1309 | if (_profileCode) 1310 | { 1311 | _codeProfileTimers["ThreadStart"].Stop(); 1312 | } 1313 | return; 1314 | } 1315 | 1316 | if (_unkownThreads.ContainsKey(tid)) 1317 | { 1318 | // This means it is a TID that we saw in a context switch already. We need to update its info. 1319 | _unkownThreads[tid].Pid = data.ProcessID; 1320 | _unkownThreads[tid].ProcessGuid = _activeProcesses[data.ProcessID].Guid; 1321 | _unkownThreads[tid].PidStartRelativeMSec = _activeProcesses[data.ProcessID].StartRelativeMSec; 1322 | 1323 | // Put it in the correct process list 1324 | _activeThreadsByProcess[data.ProcessID][tid] = _unkownThreads[tid]; 1325 | 1326 | // Count new thread. 1327 | _activeProcesses[data.ProcessID].TotalThreads += 1; 1328 | 1329 | // Remove from unknown list 1330 | _unkownThreads.Remove(tid); 1331 | 1332 | if (_verbosity >= 4) 1333 | { 1334 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1335 | data.TimeStampRelativeMSec + " " + "Updated PID in thread start" + 1336 | _activeProcesses[data.ProcessID].Name + ", " + 1337 | _activeThreadsByProcess[data.ProcessID][tid].Tid); 1338 | } 1339 | 1340 | // Make sure the processor is updated if this thread is currently executing: 1341 | for (int i = 0; i < _processorActiveProcesses.Count(); i++) 1342 | { 1343 | if (_processorActiveThreads[i] == tid && _processorActiveProcesses[i] == UnknownPid) 1344 | { 1345 | if (_verbosity >= 4) 1346 | { 1347 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + 1348 | " " + data.TimeStampRelativeMSec + " Updated executing PID "); 1349 | } 1350 | _processorActiveProcesses[i] = data.ProcessID; 1351 | } 1352 | } 1353 | 1354 | if (_profileCode) 1355 | { 1356 | _codeProfileTimers["ThreadStart"].Stop(); 1357 | } 1358 | return; 1359 | } 1360 | // Need to add duplicate TID mitigation code here! 1361 | if (_activeThreadsByProcess.ContainsKey(data.ProcessID) && 1362 | _activeThreadsByProcess[data.ProcessID].ContainsKey(tid)) 1363 | { 1364 | if (_verbosity >= 1) 1365 | { 1366 | _debugLog.WriteLine("WARNING: TID " + tid + " already exists for " + data.ProcessID); 1367 | _debugLog.WriteLine("Deleted: " + 1368 | _activeThreadsByProcess[data.ProcessID][tid].Deleted); 1369 | _debugLog.WriteLine("Deletion flag: " + 1370 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag); 1371 | } 1372 | 1373 | if (_activeThreadsByProcess[data.ProcessID][tid].DeletionFlag > 0) 1374 | { 1375 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag = data.TimeStampRelativeMSec - 1376 | (_threadDeletionDelay*2); 1377 | 1378 | ThreadDeletionQueue(data); 1379 | 1380 | if (_activeThreadsByProcess[data.ProcessID].ContainsKey(tid)) 1381 | { 1382 | _debugLog.WriteLine("ERROR: TID " + tid + " already exists for " + 1383 | data.ProcessID); 1384 | _debugLog.WriteLine("Deleted: " + 1385 | _activeThreadsByProcess[data.ProcessID][tid].Deleted); 1386 | _debugLog.WriteLine("Deletion flag: " + 1387 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag); 1388 | throw new Exception("Duplicate thread disaster despite our correction efforts"); 1389 | } 1390 | } 1391 | } 1392 | //Create thread info object 1393 | ThreadInfo newThread = new ThreadInfo 1394 | { 1395 | Pid = data.ProcessID, 1396 | Tid = tid, 1397 | Start = data.TimeStamp, 1398 | StartRelativeMSec = data.TimeStampRelativeMSec, 1399 | PidStartRelativeMSec = _activeProcesses[data.ProcessID].StartRelativeMSec, 1400 | Guid = Guid.NewGuid().ToString("N"), 1401 | ProcessGuid = _activeProcesses[data.ProcessID].Guid 1402 | }; 1403 | 1404 | // Only create database entries and counter objects if we are doing thread tracing. 1405 | if (_tracePerThread) 1406 | { 1407 | newThread.Counter = 1408 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newThread.Guid), 1409 | _debugLog); 1410 | if (!dcStart && _tracePerThread) 1411 | { 1412 | newThread.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec); 1413 | } 1414 | 1415 | _database.AddThread(newThread); 1416 | } 1417 | 1418 | // Count new thread. 1419 | _activeProcesses[data.ProcessID].TotalThreads += 1; 1420 | _activeThreadsByProcess[data.ProcessID][tid] = newThread; 1421 | if (_profileCode) 1422 | { 1423 | _codeProfileTimers["ThreadStart"].Stop(); 1424 | } 1425 | } 1426 | 1427 | /// 1428 | /// Process thread stops 1429 | /// 1430 | /// Trace event data 1431 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1432 | private void ThreadStop(TraceEvent data) 1433 | { 1434 | if (_profileCode) 1435 | { 1436 | _codeProfileCounters["ThreadStop"] += 1; 1437 | _codeProfileTimers["ThreadStop"].Start(); 1438 | } 1439 | 1440 | if (_verbosity >= 4) 1441 | { 1442 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1443 | data.TimeStampRelativeMSec + " " + "Thread Stop: " + data.ThreadID + " " + 1444 | data.ProcessID); 1445 | } 1446 | 1447 | // system idle process has as many threads as there are cores, all with duplicate Tid and Pid 0 1448 | if (data.ProcessID == 0 && data.ThreadID == 0) 1449 | { 1450 | if (_profileCode) 1451 | { 1452 | _codeProfileTimers["ThreadStop"].Stop(); 1453 | } 1454 | return; 1455 | } 1456 | 1457 | // Update Stop times for thread 1458 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].StopRelativeMSec = data.TimeStampRelativeMSec; 1459 | 1460 | // Flag for deletion 1461 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].DeletionFlag = data.TimeStampRelativeMSec; 1462 | 1463 | // Only update database if we are doing thread analysis 1464 | if (_tracePerThread) 1465 | { 1466 | _database.UpdateThreadEnd(data.TimeStampRelativeMSec, 1467 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].Guid); 1468 | } 1469 | 1470 | _threadsToDelete.Add(_activeThreadsByProcess[data.ProcessID][data.ThreadID]); 1471 | if (_profileCode) 1472 | { 1473 | _codeProfileTimers["ThreadStop"].Stop(); 1474 | } 1475 | } 1476 | 1477 | /// 1478 | /// Processes context switches, which is a lot of work. A lot of 1479 | /// error checking here to be sure what we are tracking matches the 1480 | /// the information reported by ETW. 1481 | /// 1482 | /// Trace event data 1483 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1484 | private void ContextSwitch(TraceEvent data) 1485 | { 1486 | // Get the context switch data 1487 | CSwitchTraceData cSwitchData = (CSwitchTraceData) data; 1488 | 1489 | if (_profileCode) 1490 | { 1491 | _codeProfileCounters["ContextSwitch"] += 1; 1492 | _codeProfileTimers["ContextSwitch"].Start(); 1493 | } 1494 | 1495 | // Debug logging 1496 | if (_verbosity >= 5) 1497 | { 1498 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1499 | data.TimeStampRelativeMSec + " Exchanged " + cSwitchData.OldThreadID + 1500 | " " + cSwitchData.OldProcessID + " for " + cSwitchData.NewThreadID + " " + 1501 | cSwitchData.NewProcessID + " ON CORE " + cSwitchData.ProcessorNumber); 1502 | } 1503 | 1504 | 1505 | // At the context switches we check to see whether we should do some writing and comitting. 1506 | if (_lastCommit < -99) 1507 | { 1508 | _lastCommit = data.TimeStampRelativeMSec; 1509 | } 1510 | if (_lastCommit + _commitInterval <= data.TimeStampRelativeMSec) 1511 | { 1512 | //Database commits 1513 | if (_profileCode) 1514 | { 1515 | _codeProfileCounters["Commit"] += 1; 1516 | _codeProfileTimers["Commit"].Start(); 1517 | } 1518 | _database.Commit(); 1519 | if (_profileCode) 1520 | { 1521 | _codeProfileTimers["Commit"].Stop(); 1522 | } 1523 | 1524 | _lastCommit = data.TimeStampRelativeMSec; 1525 | } 1526 | 1527 | 1528 | // Update the last CSwitch time 1529 | _lastCSwitch[cSwitchData.ProcessorNumber] = data.TimeStampRelativeMSec; 1530 | 1531 | // Should we do a deletion check? 1532 | if (data.TimeStampRelativeMSec > _lastDeletionCheck + _minBackoff) 1533 | { 1534 | ThreadDeletionQueue(data); 1535 | ProcessDeletionQueue(data); 1536 | _lastDeletionCheck = data.TimeStampRelativeMSec; 1537 | } 1538 | 1539 | // First handle what is being switched out -- As long as it is not the default. 1540 | if (_processorActiveThreads[cSwitchData.ProcessorNumber] != DefaultProcessorValue) 1541 | { 1542 | // Verify that old thread IDs match 1543 | if (_processorActiveThreads[cSwitchData.ProcessorNumber] != cSwitchData.OldThreadID) 1544 | { 1545 | _debugLog.Write("CSWITCH error. Old thread mismatch. Switched out " + cSwitchData.OldThreadID + 1546 | " but should have been" + _processorActiveThreads[cSwitchData.ProcessorNumber]); 1547 | _debugLog.Flush(); 1548 | throw new Exception("CSWITCH OldThread Mismatch"); 1549 | } 1550 | 1551 | // For any old non-idle process, we need to update the old thread and process information. 1552 | if (cSwitchData.OldThreadID != IdlePid) 1553 | { 1554 | // Easy Case: We already know about old process and thread. 1555 | if (_activeThreadsByProcess.ContainsKey(cSwitchData.OldProcessID) && 1556 | _activeThreadsByProcess[cSwitchData.OldProcessID].ContainsKey(cSwitchData.OldThreadID)) 1557 | { 1558 | // Update thread activity 1559 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID].IsActive = false; 1560 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID].LastActive = 1561 | cSwitchData.TimeStampRelativeMSec; 1562 | 1563 | // Update process activity 1564 | _activeProcesses[cSwitchData.OldProcessID].ActiveThreads -= 1; 1565 | _activeProcesses[cSwitchData.OldProcessID].LastActive = cSwitchData.TimeStampRelativeMSec; 1566 | } 1567 | 1568 | // Harder case: We know about old thread, but not the process. 1569 | else if (_unkownThreads.ContainsKey(cSwitchData.OldThreadID)) 1570 | { 1571 | _unkownThreads[cSwitchData.OldThreadID].IsActive = false; 1572 | _unkownThreads[cSwitchData.OldThreadID].LastActive = cSwitchData.TimeStampRelativeMSec; 1573 | 1574 | // Update the process information if the old PID exists now. 1575 | if (cSwitchData.OldProcessID > 0) 1576 | { 1577 | _unkownThreads[cSwitchData.OldThreadID].Pid = cSwitchData.OldProcessID; 1578 | 1579 | // Add thread to the process thread list 1580 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID] = 1581 | _unkownThreads[cSwitchData.OldThreadID]; 1582 | 1583 | // Update GUID 1584 | _unkownThreads[cSwitchData.OldThreadID].ProcessGuid = 1585 | _activeProcesses[cSwitchData.OldProcessID].Guid; 1586 | 1587 | // New thread for this process 1588 | _activeProcesses[cSwitchData.OldProcessID].TotalThreads += 1; 1589 | 1590 | //Remove from UnkownThreads 1591 | _unkownThreads.Remove(cSwitchData.OldThreadID); 1592 | 1593 | // Log information 1594 | if (_verbosity >= 3) 1595 | { 1596 | _debugLog.WriteLine( 1597 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1598 | data.TimeStampRelativeMSec + "Updated PID to " + 1599 | cSwitchData.OldProcessID + " for switched out thread " + 1600 | cSwitchData.OldThreadID); 1601 | } 1602 | 1603 | // Update Active processors for this thread 1604 | for (int i = 0; i < _processorActiveProcesses.Count(); i++) 1605 | { 1606 | if (i != cSwitchData.ProcessorNumber && 1607 | _processorActiveThreads[i] == cSwitchData.OldThreadID && 1608 | _processorActiveProcesses[i] == UnknownPid) 1609 | { 1610 | if (_verbosity >= 3) 1611 | { 1612 | _debugLog.WriteLine( 1613 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1614 | data.TimeStampRelativeMSec + " Updated executing PID "); 1615 | } 1616 | _processorActiveProcesses[i] = cSwitchData.OldProcessID; 1617 | _activeProcesses[cSwitchData.OldProcessID].ActiveThreads += 1; 1618 | } 1619 | } 1620 | } 1621 | } 1622 | 1623 | // Otherwise, we are in an error condition. 1624 | else 1625 | { 1626 | _debugLog.Write("FATAL CSWITCH ERROR: Don't know anything about switched out thread."); 1627 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1628 | data.TimeStampRelativeMSec + " Exchanged " + 1629 | cSwitchData.OldThreadID + " " + cSwitchData.OldProcessID + " for " + 1630 | cSwitchData.NewThreadID + " " + 1631 | cSwitchData.NewProcessID + " ON CORE " + 1632 | cSwitchData.ProcessorNumber); 1633 | _debugLog.Flush(); 1634 | throw new Exception("FATAL CSWITCH ERROR: Don't know anything about switched out thread."); 1635 | } 1636 | } 1637 | } 1638 | 1639 | 1640 | // Gratuitious logging for debugging purposes only. 1641 | //DebugLog.WriteLine("Processes:" + String.Join(",", ProcessorActiveProcesses)); 1642 | //DebugLog.WriteLine("Threads:" + String.Join(",", ProcessorActiveThreads)); 1643 | // If the new thread is the system IDLE process, we are fine. Just set it and continue 1644 | int newThreadId = cSwitchData.NewThreadID; 1645 | int newProcessId = cSwitchData.NewProcessID; 1646 | 1647 | // For Nonzero new processes, we have work to do. 1648 | if (cSwitchData.NewThreadID != IdlePid) 1649 | { 1650 | // If we know about both the thread and process already 1651 | if (_activeThreadsByProcess.ContainsKey(cSwitchData.NewProcessID) && 1652 | _activeThreadsByProcess[cSwitchData.NewProcessID].ContainsKey(cSwitchData.NewThreadID)) 1653 | { 1654 | // Update thread activity 1655 | _activeThreadsByProcess[cSwitchData.NewProcessID][cSwitchData.NewThreadID].IsActive = true; 1656 | 1657 | // Update process activity 1658 | _activeProcesses[cSwitchData.NewProcessID].ActiveThreads += 1; 1659 | } 1660 | // If we only know about the thread 1661 | else if (_unkownThreads.ContainsKey(cSwitchData.NewThreadID)) 1662 | { 1663 | _unkownThreads[cSwitchData.NewThreadID].IsActive = true; 1664 | newProcessId = UnknownPid; 1665 | } 1666 | 1667 | // If we don't know about the thread yet and process is unknown, it is the weird case we see every now and then. 1668 | else if (cSwitchData.NewProcessID < 0) 1669 | { 1670 | if (_verbosity >= 4) 1671 | { 1672 | _debugLog.WriteLine("CSwitch: Created new TID in thread list (" + cSwitchData.NewThreadID + ")"); 1673 | _debugLog.WriteLine("Threads Old: " + cSwitchData.OldThreadID + " New: " + 1674 | cSwitchData.NewThreadID); 1675 | _debugLog.WriteLine("Processes Old: " + cSwitchData.OldProcessID + " New: " + 1676 | cSwitchData.NewProcessID); 1677 | } 1678 | 1679 | //Create thread info object 1680 | ThreadInfo newThread = new ThreadInfo 1681 | { 1682 | Tid = cSwitchData.NewThreadID, 1683 | Pid = UnknownPid, 1684 | Start = data.TimeStamp, 1685 | StartRelativeMSec = data.TimeStampRelativeMSec, 1686 | Guid = Guid.NewGuid().ToString("N") 1687 | }; 1688 | 1689 | // Create a new tracker 1690 | newThread.Counter = 1691 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newThread.Guid), 1692 | _debugLog); 1693 | if (_tracePerThread) 1694 | { 1695 | newThread.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec); 1696 | } 1697 | 1698 | _unkownThreads[cSwitchData.NewThreadID] = newThread; 1699 | newProcessId = UnknownPid; 1700 | } 1701 | 1702 | // Otherwise we are in an error condition 1703 | else 1704 | { 1705 | _debugLog.Write("FATAL CSWITCH ERROR: Don't know anything about switched in thread."); 1706 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1707 | data.TimeStampRelativeMSec + " Exchanged " + cSwitchData.OldThreadID + 1708 | " " + cSwitchData.OldProcessID + " for " + cSwitchData.NewThreadID + 1709 | " " + cSwitchData.NewProcessID + " ON CORE " + 1710 | cSwitchData.ProcessorNumber); 1711 | _debugLog.Flush(); 1712 | throw new Exception("FATAL CSWITCH ERROR: Don't know anything about switched in thread."); 1713 | } 1714 | } 1715 | 1716 | // Update information about the threads and processes on the cores 1717 | _processorActiveProcesses[cSwitchData.ProcessorNumber] = newProcessId; 1718 | _processorActiveThreads[cSwitchData.ProcessorNumber] = newThreadId; 1719 | 1720 | 1721 | if (_profileCode) 1722 | { 1723 | _codeProfileTimers["ContextSwitch"].Stop(); 1724 | } 1725 | } 1726 | 1727 | 1728 | /// 1729 | /// Processes the thread deletion queue 1730 | /// 1731 | /// Trace event data 1732 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1733 | private void ThreadDeletionQueue(TraceEvent data) 1734 | { 1735 | if (_profileCode) 1736 | { 1737 | _codeProfileCounters["ThreadDeletionQueue"] += 1; 1738 | _codeProfileTimers["ThreadDeletionQueue"].Start(); 1739 | } 1740 | 1741 | // Return if there is nothing to do. 1742 | if (_threadsToDelete.Count != 0) 1743 | { 1744 | // Otherwise loop over all the threads to see which ones are ready to be deleted. 1745 | for (int i = _threadsToDelete.Count - 1; i >= 0; i--) 1746 | { 1747 | var thread = _threadsToDelete[i]; 1748 | 1749 | if (thread.IsActive) 1750 | { 1751 | _threadDeletionDelay *= 1.1; 1752 | if (_verbosity >= 4) 1753 | { 1754 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + 1755 | " " + data.TimeStampRelativeMSec + 1756 | " Thread delay updated because still active. " + thread.Tid); 1757 | } 1758 | } 1759 | 1760 | // If the deletion time has passed, see if it is ready 1761 | else if (data.TimeStampRelativeMSec > thread.DeletionFlag + _threadDeletionDelay) 1762 | { 1763 | // If there is no active process associated with this thread, good! 1764 | if (!_activeProcesses.ContainsKey(thread.Pid)) 1765 | { 1766 | if (_verbosity >= 4) 1767 | { 1768 | _debugLog.WriteLine( 1769 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1770 | data.TimeStampRelativeMSec + " " + 1771 | "Deleted thread with no active process" + thread.Tid + "," + 1772 | thread.Pid); 1773 | } 1774 | 1775 | // Remove from the unknown threads 1776 | _unkownThreads.Remove(thread.Pid); 1777 | 1778 | // Dispose of the commands -- Do I need to write a dispose method for the Counter? 1779 | if (thread.Counter != null) 1780 | { 1781 | thread.Counter.Close(); 1782 | } 1783 | thread.Deleted = true; 1784 | 1785 | // Remove thread from deletion list 1786 | _threadsToDelete.RemoveAt(i); 1787 | } 1788 | 1789 | // Else we just remove the old thread from its process 1790 | else 1791 | { 1792 | if (_verbosity >= 4) 1793 | { 1794 | _debugLog.WriteLine( 1795 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " + 1796 | data.TimeStampRelativeMSec + " " + "Thread deleted normally." + 1797 | thread.Tid + "," + thread.Pid); 1798 | } 1799 | 1800 | _activeThreadsByProcess[thread.Pid].Remove(thread.Tid); 1801 | 1802 | _activeProcesses[thread.Pid].TotalThreads -= 1; 1803 | 1804 | // Dispose of the commands 1805 | if (thread.Counter != null) 1806 | { 1807 | thread.Counter.Close(); 1808 | } 1809 | 1810 | thread.Deleted = true; 1811 | 1812 | _threadsToDelete.RemoveAt(i); 1813 | } 1814 | } 1815 | } 1816 | } 1817 | if (_profileCode) 1818 | { 1819 | _codeProfileTimers["ThreadDeletionQueue"].Stop(); 1820 | } 1821 | } 1822 | 1823 | /// 1824 | /// Process the process deletion queue 1825 | /// 1826 | /// Trace event data 1827 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1828 | private void ProcessDeletionQueue(TraceEvent data) 1829 | { 1830 | if (_processesToDelete.Count != 0) 1831 | { 1832 | for (int i = _processesToDelete.Count - 1; i >= 0; i--) 1833 | { 1834 | ProcessInfo process = _processesToDelete[i]; 1835 | 1836 | // Process is still active 1837 | if (process.ActiveThreads > 0) 1838 | { 1839 | process.DeletionFlag = data.TimeStampRelativeMSec; 1840 | if (_verbosity >= 5) 1841 | { 1842 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + 1843 | " " + data.TimeStampRelativeMSec + " " + 1844 | "process still active. Deletion delayed. " + process.Pid); 1845 | } 1846 | } 1847 | 1848 | // Process still has threads 1849 | else if (process.TotalThreads > 0) 1850 | { 1851 | } 1852 | 1853 | // Process is ready to be removed when it has no threads and delay is over 1854 | else if (data.TimeStampRelativeMSec > process.DeletionFlag + _processDeletionDelay) 1855 | { 1856 | if (_verbosity >= 3) 1857 | { 1858 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + 1859 | " " + data.TimeStampRelativeMSec + " Removed old process " + 1860 | process.Pid); 1861 | } 1862 | 1863 | // Remove process 1864 | _activeProcesses.Remove(process.Pid); 1865 | 1866 | // remove thread list for process 1867 | _activeThreadsByProcess.Remove(process.Pid); 1868 | 1869 | // Dispose of the commands 1870 | if (process.Counter != null) 1871 | { 1872 | process.Counter.Close(); 1873 | } 1874 | 1875 | process.Deleted = true; 1876 | 1877 | //Remove it from list 1878 | _processesToDelete.RemoveAt(i); 1879 | } 1880 | } 1881 | } 1882 | } 1883 | 1884 | /// 1885 | /// System call enter processing 1886 | /// 1887 | /// Trace event data 1888 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 1889 | private void SystemCallEnter(TraceEvent data) 1890 | { 1891 | if (_profileCode) 1892 | { 1893 | _codeProfileCounters["Syscall"] += 1; 1894 | _codeProfileTimers["Syscall"].Start(); 1895 | } 1896 | 1897 | int index = -2; 1898 | SysCallEnterTraceData traceData = (SysCallEnterTraceData) data; 1899 | 1900 | if (traceData.SysCallAddress >= _ntLowestAddress && traceData.SysCallAddress <= _ntMaxAddress) 1901 | { 1902 | index = _ntMap[(traceData.SysCallAddress - _ntLowestAddress)]; 1903 | 1904 | // This is here for now for debugging puposes as a sanity check that we are tracing whole kernel 1905 | if (index == -1) 1906 | { 1907 | _debugLog.WriteLine("UNKNOWN System Call Enter NT {0:X} on core {1} ", traceData.SysCallAddress, 1908 | traceData.ProcessorNumber); 1909 | } 1910 | } 1911 | 1912 | if (index >= 0) 1913 | { 1914 | // Do host-wide data collection 1915 | if (_traceHostLevel) 1916 | { 1917 | _systemWideCounter.Add((ushort) index, data.TimeStampRelativeMSec); 1918 | } 1919 | 1920 | // Do process level data collection 1921 | if (_tracePerProcess) 1922 | { 1923 | if (_activeProcesses.ContainsKey(_processorActiveProcesses[traceData.ProcessorNumber])) 1924 | { 1925 | ProcessInfo process = _activeProcesses[_processorActiveProcesses[traceData.ProcessorNumber]]; 1926 | process.Counter.Add((ushort) index, data.TimeStampRelativeMSec); 1927 | } 1928 | } 1929 | 1930 | 1931 | // Do it per thread 1932 | // Do process level data collection 1933 | if (_tracePerThread) 1934 | { 1935 | ThreadInfo thread = null; 1936 | 1937 | if (_unkownThreads.ContainsKey(_processorActiveThreads[traceData.ProcessorNumber])) 1938 | { 1939 | thread = _unkownThreads[_processorActiveThreads[traceData.ProcessorNumber]]; 1940 | } 1941 | else if (_activeThreadsByProcess.ContainsKey(_processorActiveProcesses[traceData.ProcessorNumber]) && 1942 | _activeThreadsByProcess[_processorActiveProcesses[traceData.ProcessorNumber]].ContainsKey( 1943 | _processorActiveThreads[traceData.ProcessorNumber])) 1944 | { 1945 | thread = 1946 | _activeThreadsByProcess[_processorActiveProcesses[traceData.ProcessorNumber]][ 1947 | _processorActiveThreads[traceData.ProcessorNumber]]; 1948 | } 1949 | 1950 | if (thread != null) 1951 | { 1952 | thread.Counter.Add((ushort) index, data.TimeStampRelativeMSec); 1953 | } 1954 | } 1955 | } 1956 | if (_profileCode) 1957 | { 1958 | _codeProfileTimers["Syscall"].Stop(); 1959 | } 1960 | } 1961 | 1962 | /// 1963 | /// Get the base addresses of the kernel 1964 | /// 1965 | /// true upon success 1966 | private bool GetBaseAddresses() 1967 | { 1968 | uint bytesNeeded; 1969 | 1970 | // See how big the buffer needs to be 1971 | var success = EnumDeviceDrivers(null, 0, out bytesNeeded); 1972 | _debugLog.WriteLine("EnumDeviceDrivers Finished"); 1973 | _debugLog.Flush(); 1974 | 1975 | // Check error conditions 1976 | if (!success) 1977 | { 1978 | return false; 1979 | } 1980 | if (bytesNeeded == 0) 1981 | { 1982 | return false; 1983 | } 1984 | 1985 | // Allocate the array; as each ID is a 4-byte int, it should be 1/4th the size of bytesNeeded 1986 | uint arraySizeBytes = bytesNeeded; 1987 | #if X86 1988 | uint ArraySize = BytesNeeded / 4; 1989 | UInt32[] Addresses = new UInt32[ArraySize]; 1990 | #else 1991 | uint arraySize = bytesNeeded/8; 1992 | UInt64[] addresses = new UInt64[arraySize]; 1993 | #endif 1994 | 1995 | // Now fill the array with device driver information 1996 | success = EnumDeviceDrivers(addresses, arraySizeBytes, out bytesNeeded); 1997 | _debugLog.WriteLine("Second EnumDeviceDrivers Finished"); 1998 | _debugLog.Flush(); 1999 | // Check error conditions 2000 | if (!success) 2001 | { 2002 | return false; 2003 | } 2004 | 2005 | // Iterate over all the device drivers until we find the kernel 2006 | // Assume the base name is no more than 1000 characters 2007 | StringBuilder driverName = new StringBuilder(1000); 2008 | for (int i = 0; i < arraySize; i++) 2009 | { 2010 | GetDeviceDriverBaseName(addresses[i], driverName, driverName.Capacity); 2011 | 2012 | String driverNameString = driverName.ToString(); 2013 | 2014 | // Kernel has different names on different windows versions 2015 | String[] possibleNames = {"ntoskrnl.exe", "ntkrnlpa.exe", "ntkrnlmp.exe", "ntkrpamp.exe"}; 2016 | 2017 | foreach (String name in possibleNames) 2018 | { 2019 | if (driverNameString == name) 2020 | { 2021 | _debugLog.WriteLine("Found " + name); 2022 | _debugLog.WriteLine(addresses[i]); 2023 | _debugLog.Flush(); 2024 | _ntKernelAddress = addresses[i]; 2025 | _ntKernelImageName = name; 2026 | break; 2027 | } 2028 | } 2029 | } 2030 | _debugLog.WriteLine("StringBuilder Finished"); 2031 | _debugLog.Flush(); 2032 | return (_ntKernelAddress > 0); 2033 | } 2034 | 2035 | /// 2036 | /// Starts data collection 2037 | /// 2038 | public void Start() 2039 | { 2040 | _endService = false; 2041 | 2042 | // Setup Profiling firsst 2043 | if (_profileCode) 2044 | { 2045 | foreach (string str in _codeProfileKeys) 2046 | { 2047 | _codeProfileTimers.Add(str, new Stopwatch()); 2048 | _codeProfileCounters.Add(str, 0); 2049 | } 2050 | } 2051 | 2052 | // Reset Last SyscallEnter time and deletion check 2053 | _lastDeletionCheck = -110000; 2054 | _lastCommit = -1; 2055 | 2056 | // Create data directory (if it doesn't already exist). 2057 | Directory.CreateDirectory(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory)); 2058 | 2059 | // Create a subdirectory to store the data 2060 | _dataSubFolder = DateTime.Now.ToString("yyyyMMdd_HHmmss"); 2061 | Directory.CreateDirectory(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, 2062 | _dataSubFolder)); 2063 | 2064 | // Create the logfile 2065 | _debugLog = 2066 | new StreamWriter(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, 2067 | _dataSubFolder, Properties.SystemCallServiceSettings.Default.DebugLogFilename)); 2068 | 2069 | // Dump some config information in the debug log 2070 | foreach (string prop in _properties) 2071 | { 2072 | _debugLog.WriteLine(prop + " " + Properties.SystemCallServiceSettings.Default[prop]); 2073 | } 2074 | 2075 | _debugLog.Flush(); 2076 | 2077 | // Start the database interface 2078 | _database = 2079 | new DatabaseInterface( 2080 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, _dataSubFolder, 2081 | "database.sqlite"), _debugLog); 2082 | 2083 | _debugLog.WriteLine("Started Database Interface"); 2084 | _debugLog.Flush(); 2085 | 2086 | // Get base kernel addresses -- must be done first to get correct image name because of x86 implementation 2087 | if (!GetBaseAddresses()) 2088 | { 2089 | _debugLog.WriteLine("Unable to fetch base addresses for the kernel. Unable to continue."); 2090 | _debugLog.Flush(); 2091 | throw new Exception("Unable to fetch base addresses for the kernel. Unable to continue."); 2092 | } 2093 | 2094 | _debugLog.WriteLine("Done GetBaseAddresses"); 2095 | _debugLog.Flush(); 2096 | 2097 | // Get system information 2098 | GetSystemInformation(); 2099 | _debugLog.WriteLine("Done adding SystemInformation"); 2100 | _debugLog.Flush(); 2101 | 2102 | // Load address mappings 2103 | _ntMap = LoadAddressMaps(_ntKernelImageName, _systemInfo.NtoskrnlVersion, 2104 | Properties.SystemCallServiceSettings.Default.NtSensorList, out _syscallNameList, out _ntLowestAddress, 2105 | out _ntMaxAddress, 0, _ntKernelAddress); 2106 | _debugLog.WriteLine("Done LoadAddressMaps"); 2107 | _debugLog.Flush(); 2108 | 2109 | 2110 | if (_ntMap == null) 2111 | { 2112 | // TODO: Exit cleanly? This was put here for the case when automatic downloading was enabled. 2113 | // We don't want to quit forever, but retry in whatever the specified interval is. 2114 | Thread.Sleep((int) Properties.SystemCallServiceSettings.Default.AutoResetMs); 2115 | return; 2116 | } 2117 | 2118 | _debugLog.WriteLine(_syscallNameList.Count() + " nt sensors active"); 2119 | _debugLog.Flush(); 2120 | 2121 | // Setup the data table creation and insertion queries and create one for the system-wide data 2122 | _systemWideCounter = 2123 | new SystemCallTracer( 2124 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, _dataSubFolder, 2125 | "host_data"), _debugLog); 2126 | if (Properties.SystemCallServiceSettings.Default.TraceHostLevel) 2127 | { 2128 | _systemWideCounter.InitializeFullTrace(-1, 0); 2129 | } 2130 | 2131 | // Start the timer 2132 | _resetTimer.Interval = Properties.SystemCallServiceSettings.Default.AutoResetMs; 2133 | _resetTimer.Start(); 2134 | 2135 | // Clear all the data structures that are populated during a trace 2136 | _tableCreations.Clear(); 2137 | _processesToDelete.Clear(); 2138 | _threadsToDelete.Clear(); 2139 | _activeThreadsByProcess.Clear(); 2140 | _unkownThreads.Clear(); 2141 | _activeProcesses.Clear(); 2142 | _timer.Restart(); 2143 | 2144 | // Setup Thread and Process tracking, initialize to default values 2145 | _processorActiveThreads = new int[_logicalProcessorCount]; 2146 | _processorActiveProcesses = new int[_logicalProcessorCount]; 2147 | 2148 | for (int i = 0; i < _logicalProcessorCount; i++) 2149 | { 2150 | _processorActiveThreads[i] = DefaultProcessorValue; 2151 | _processorActiveProcesses[i] = DefaultProcessorValue; 2152 | } 2153 | 2154 | // Create the last cswitch time vector 2155 | _lastCSwitch = new double[_logicalProcessorCount]; 2156 | for (int i = 0; i < _lastCSwitch.Count(); i++) 2157 | { 2158 | // Start it at a very negative value since timestamps usually start out negative 2159 | _lastCSwitch[i] = -110000; 2160 | } 2161 | 2162 | // Kernel addresses 2163 | _debugLog.WriteLine("ntoskrnl.exe version: " + 2164 | FileVersionInfo.GetVersionInfo( 2165 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), 2166 | _ntKernelImageName)).ProductVersion); 2167 | _debugLog.WriteLine("NT: {0:X}", _ntKernelAddress); 2168 | _debugLog.Flush(); 2169 | 2170 | // The session name for the ETW trace has to be NT Kernel Logger for doing the kernel logging. 2171 | // Relevant links: 2172 | // http://stackoverflow.com/questions/16068051/consuming-an-etw-kernel-trace-using-c-sharp 2173 | // http://blogs.msdn.com/b/vancem/archive/2013/03/09/using-traceevent-to-mine-information-in-os-registered-etw-providers.aspx 2174 | 2175 | // Opens up a real time session for the trace events. Details about using statement http://msdn.microsoft.com/en-us/library/yh598w02.aspx 2176 | using (var eventTracingSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName)) 2177 | // the null second parameter means 'real time session' 2178 | { 2179 | // Save it as an instance variable 2180 | _eventTracingSession = eventTracingSession; 2181 | 2182 | // Select those providers that we want data from: PRocess, Thread, and Context switch. 2183 | eventTracingSession.EnableKernelProvider(KernelTraceEventParser.Keywords.ContextSwitch | 2184 | KernelTraceEventParser.Keywords.Process | 2185 | KernelTraceEventParser.Keywords.Thread | 2186 | KernelTraceEventParser.Keywords.SystemCall); 2187 | // Need to figure out whether DPC or anything else belongs here. 2188 | 2189 | // Setup the handlers 2190 | eventTracingSession.Source.Kernel.PerfInfoSysClEnter += SystemCallEnter; 2191 | eventTracingSession.Source.Kernel.ThreadCSwitch += ContextSwitch; 2192 | 2193 | 2194 | eventTracingSession.Source.Kernel.ThreadStart += ThreadStart; 2195 | eventTracingSession.Source.Kernel.ThreadDCStart += ThreadDcStart; 2196 | eventTracingSession.Source.Kernel.ThreadStop += ThreadStop; 2197 | eventTracingSession.Source.Kernel.ThreadDCStop += ThreadStop; 2198 | 2199 | eventTracingSession.Source.Kernel.ProcessStop += ProcessStop; 2200 | eventTracingSession.Source.Kernel.ProcessDCStop += ProcessStop; 2201 | 2202 | 2203 | eventTracingSession.Source.Kernel.ProcessStart += ProcessStart; 2204 | eventTracingSession.Source.Kernel.ProcessDCStart += ProcessDcStart; 2205 | 2206 | // Start the timer 2207 | _timer.Start(); 2208 | 2209 | // Start Processing 2210 | try 2211 | { 2212 | eventTracingSession.Source.Process(); 2213 | } 2214 | catch (Exception e) 2215 | { 2216 | _debugLog.WriteLine("FATAL ERROR: Exception in event processing."); 2217 | _debugLog.WriteLine(e.ToString()); 2218 | _debugLog.WriteLine(e.StackTrace); 2219 | _eventLog.WriteEntry("Exception in event processing", EventLogEntryType.Error); 2220 | _eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error); 2221 | } 2222 | 2223 | _debugLog.Flush(); 2224 | 2225 | // If processing has stopped, commit! 2226 | _database.Commit(); 2227 | 2228 | if (_profileCode) 2229 | { 2230 | foreach (string str in _codeProfileKeys) 2231 | { 2232 | _debugLog.WriteLine(str + " " + _codeProfileCounters[str] + " calls " + 2233 | _codeProfileTimers[str].ElapsedMilliseconds + " ms " + 2234 | _codeProfileTimers[str].ElapsedMilliseconds/ 2235 | (float) _codeProfileCounters[str] + " ms per"); 2236 | } 2237 | } 2238 | _eventLog.WriteEntry("Processing stopped", EventLogEntryType.Information); 2239 | _debugLog.WriteLine("Lost events: " + eventTracingSession.Source.EventsLost + 2240 | " Ideally, this number should be zero"); 2241 | _debugLog.Flush(); 2242 | } 2243 | 2244 | 2245 | //Cleanup all the old data lying around. 2246 | foreach (var process in _activeThreadsByProcess.Values) 2247 | { 2248 | foreach (var thread in process.Values) 2249 | { 2250 | if (thread.Counter != null) 2251 | { 2252 | thread.Counter.Close(); 2253 | thread.Counter = null; 2254 | } 2255 | } 2256 | } 2257 | 2258 | foreach (var process in _unkownThreads.Values) 2259 | { 2260 | if (process.Counter != null) 2261 | { 2262 | process.Counter.Close(); 2263 | process.Counter = null; 2264 | } 2265 | } 2266 | 2267 | foreach (var process in _processesToDelete) 2268 | { 2269 | if (process.Counter != null) 2270 | { 2271 | process.Counter.Close(); 2272 | process.Counter = null; 2273 | } 2274 | } 2275 | 2276 | foreach (var process in _threadsToDelete) 2277 | { 2278 | if (process.Counter != null) 2279 | { 2280 | process.Counter.Close(); 2281 | process.Counter = null; 2282 | } 2283 | } 2284 | 2285 | foreach (var process in _activeProcesses.Values) 2286 | { 2287 | if (process.Counter != null) 2288 | { 2289 | process.Counter.Close(); 2290 | process.Counter = null; 2291 | } 2292 | } 2293 | 2294 | _database.Commit(); 2295 | _database.CloseConnection(); 2296 | 2297 | _debugLog.Flush(); 2298 | _debugLog.Close(); 2299 | _debugLog = null; 2300 | 2301 | _systemWideCounter.Close(); 2302 | 2303 | SQLiteConnection.ClearAllPools(); 2304 | GC.Collect(); 2305 | GC.WaitForPendingFinalizers(); 2306 | } 2307 | 2308 | /// 2309 | /// Stops the event tracing session 2310 | /// 2311 | /// Indicates service should be stopped. 2312 | public void Stop(bool stopService) 2313 | { 2314 | _endService = stopService; 2315 | _debugLog.WriteLine("SyscallCounter.Stop()"); 2316 | _eventTracingSession.Stop(); 2317 | } 2318 | 2319 | /// 2320 | /// Timer for resetting the service 2321 | /// 2322 | /// Timer source 2323 | /// Time arguments 2324 | private void ResetTimerEvent(object source, ElapsedEventArgs e) 2325 | { 2326 | _debugLog.WriteLine("SyscallCounter.ResetTimerEvent()"); 2327 | Stop(false); 2328 | } 2329 | } 2330 | } --------------------------------------------------------------------------------