├── LICENSE
├── README.md
├── SDDLViewer.sln
├── SDDLViewer
├── App.xaml
├── App.xaml.cs
├── BoolStringClass.cs
├── Logic
│ ├── DirectorySearcher.cs
│ ├── Model.cs
│ ├── SecurityUnit
│ │ ├── ACE.cs
│ │ └── SecurityDescriptor.cs
│ └── Win32Native.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── SDDLViewer.csproj
├── UIFolderRegPicker
│ ├── FolderRegPickerWindow.xaml
│ └── FolderRegPickerWindow.xaml.cs
├── UIPerformWork
│ ├── UIPerformWorkWindow.xaml
│ └── UIPerformWorkWindow.xaml.cs
├── UIReport
│ ├── ReportModel.cs
│ ├── UIReportWindow.xaml
│ └── UIReportWindow.xaml.cs
└── sddl_terminal.ico
└── Screenshots
└── MainWindow.png
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Advanced monitoring
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SDDL Viewer
2 |
3 | This is a small tool to view SDDL-strings. Allows to filter users, SIDs and rights.
4 |
5 | # Screenshots
6 |
7 | 
8 |
9 | # Links
10 |
11 | Short view: https://habr.com/ru/company/pm/blog/442662/
--------------------------------------------------------------------------------
/SDDLViewer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26228.9
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SDDLViewer", "SDDLViewer\SDDLViewer.csproj", "{6929B669-D82D-49B5-B4ED-7172BC900D18}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {6929B669-D82D-49B5-B4ED-7172BC900D18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {6929B669-D82D-49B5-B4ED-7172BC900D18}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {6929B669-D82D-49B5-B4ED-7172BC900D18}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {6929B669-D82D-49B5-B4ED-7172BC900D18}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/SDDLViewer/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/SDDLViewer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Windows;
7 |
8 | namespace SDDLViewer
9 | {
10 | ///
11 | /// Interaction logic for App.xaml
12 | ///
13 | public partial class App : Application
14 | {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SDDLViewer/BoolStringClass.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Media;
2 |
3 | namespace SDDLViewer
4 | {
5 | public class BoolStringClass
6 | {
7 | public BoolStringClass(string text, string tag)
8 | {
9 | Text = text;
10 | Tag = tag;
11 | IsSelected = true;
12 | TextBrush = new SolidColorBrush(Color.FromRgb(0, 0, 0));
13 | }
14 |
15 | public string Text { get; }
16 | public string Tag { get; }
17 | public bool IsSelected { get; set; }
18 | public SolidColorBrush TextBrush { get; set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/SDDLViewer/Logic/DirectorySearcher.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace SDDLViewer.Logic
5 | {
6 | static class DirectorySearcher
7 | {
8 | public static List MyGetDirectories(string path)
9 | {
10 | return Search(path, false);
11 | }
12 |
13 | public static List MyGetFiles(string path)
14 | {
15 | return Search(path, true);
16 | }
17 |
18 | private static List Search(string path, bool isFiles)
19 | {
20 | var fullPath = Path.GetFullPath(path);
21 | var searchPath = Path.Combine(fullPath, "*.*");
22 | var rv = new List();
23 | var findData = new Win32Native.WIN32_FIND_DATA();
24 | using (var hndFindFile = Win32Native.FindFirstFile(searchPath, findData))
25 | {
26 | if (hndFindFile == null)
27 | return rv;
28 | var retval = true;
29 | while (retval)
30 | {
31 | if ((findData.cFileName == ".") || (findData.cFileName == ".."))
32 | {
33 | retval = Win32Native.FindNextFile(hndFindFile, findData);
34 | continue;
35 | }
36 | if (((findData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory) != isFiles)
37 | rv.Add(Path.Combine(fullPath, findData.cFileName));
38 | retval = Win32Native.FindNextFile(hndFindFile, findData);
39 | }
40 | }
41 | return rv;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/SDDLViewer/Logic/Model.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Security.AccessControl;
8 | using System.ServiceProcess;
9 | using System.Text;
10 | using System.Threading;
11 | using System.Windows.Controls;
12 | using System.Windows.Media;
13 | using System.Windows.Threading;
14 | using Microsoft.Win32;
15 | using SDDLViewer.UIFolderRegPicker;
16 | using SDDLViewer.UIPerformWork;
17 | using SDDLViewer.UIReport;
18 |
19 | namespace SDDLViewer.Logic
20 | {
21 | public static class Model
22 | {
23 | public static MainWindow MW { set; private get; }
24 |
25 | public static void SelectionChangedRightsCombobox()
26 | {
27 | var selected = ((ComboBoxItem)MW.CmbxRightsType.SelectedItem).Content as string;
28 | MW.RightsList.Clear();
29 | foreach (var r in new List {"GA", "GX", "GW", "GR", "SD", "RC", "WD", "WO"})
30 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r), r));
31 | switch (selected)
32 | {
33 | case "Service Access Rights":
34 | foreach (var r in new List { "CC", "DC", "LC", "DW", "RP", "WP", "DT", "LO", "CR" })
35 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r, 0), r));
36 | break;
37 |
38 | case "Directory Access Rights":
39 | foreach (var r in new List { "CC", "DC", "LC", "SW", "RP", "WP", "DT", "LO", "CR" })
40 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r, 1), r));
41 | break;
42 |
43 | case "File Access Rights":
44 | foreach (var r in new List { "CC", "DC", "LC", "SW", "RP", "WP", "LO", "CR", "FA", "FR", "FW", "FX" })
45 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r, 2), r));
46 | break;
47 |
48 | case "File and Directory Access Rights":
49 | foreach (var r in new List { "CC", "DC", "LC", "SW", "RP", "WP", "DT", "LO", "CR", "FA", "FR", "FW", "FX" })
50 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r, 3), r));
51 | break;
52 |
53 | case "Registry Key Access Rights":
54 | foreach (var r in new List { "CC", "DC", "LC", "SW", "RP", "WP", "KA", "KR", "KW", "KX" })
55 | MW.RightsList.Add(new BoolStringClass(ACE.RigthToLong(r, 4), r));
56 | break;
57 | }
58 | TextChangedContentEdit();
59 | }
60 |
61 | private static readonly ManualResetEvent TextChangedEvent = new ManualResetEvent(false);
62 | private static Thread _textChangedThread;
63 | private static Thread _textChangedSpinnerThread;
64 |
65 | public static void TextChangedContentEdit()
66 | {
67 | if (_textChangedThread != null && _textChangedThread.IsAlive)
68 | {
69 | TextChangedEvent.Set();
70 | _textChangedThread.Join();
71 | }
72 | TextChangedEvent.Reset();
73 | _textChangedThread = new Thread(TextChangedFunc);
74 | _textChangedThread.Start(MW.GetContent());
75 | _textChangedSpinnerThread = new Thread(TextChangedSpinnerFunc);
76 | _textChangedSpinnerThread.Start();
77 | }
78 |
79 | private static int _textChangedIndex;
80 |
81 | private static void TextChangedSpinnerFunc()
82 | {
83 | while (true)
84 | {
85 | Thread.Sleep(300);
86 | var head = "User/Group/SID";
87 | if (_textChangedThread != null && _textChangedThread.IsAlive)
88 | {
89 | _textChangedIndex = (_textChangedIndex + 1) % 4;
90 | head = "[" + "|/-\\"[_textChangedIndex] + "] " + head;
91 | }
92 | MW.Dispatcher.BeginInvoke(DispatcherPriority.Background,
93 | new Action((x) => MW.grpUGS.Header = x), head);
94 | if (TextChangedEvent.WaitOne(0))
95 | {
96 | MW.Dispatcher.BeginInvoke(DispatcherPriority.Background,
97 | new Action(() => MW.grpUGS.Header = "User/Group/SID"));
98 | Thread.CurrentThread.Abort();
99 | return;
100 | }
101 | }
102 | }
103 |
104 | private static void TextChangedFunc(object o)
105 | {
106 | var data = (string)o;
107 | var lines = data.Split('\r', '\n');
108 | var allSIDs = new List();
109 | var allRights = new List();
110 | var prevSids = 0;
111 | var prevRights = 0;
112 | foreach (var line in lines)
113 | {
114 | if (!string.IsNullOrWhiteSpace(line))
115 | {
116 | var sd = new SecurityDescriptor(line.Trim());
117 | if (!sd.IsOk)
118 | continue;
119 |
120 | var lSIDs = sd.GetAllSIDs();
121 | foreach (var sid in lSIDs)
122 | if (!allSIDs.Contains(sid))
123 | allSIDs.Add(sid);
124 |
125 | var lRights = sd.GetAllRights();
126 | foreach (var right in lRights)
127 | if (!allRights.Contains(right))
128 | allRights.Add(right);
129 |
130 | if (allSIDs.Count != prevSids)
131 | {
132 | prevSids = allSIDs.Count;
133 | var sortedSIDs = allSIDs.OrderBy(q => q[1] == '-' ? "ZZ" + q : q).ToList();
134 | MW.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action>((x) =>
135 | {
136 | MW.SIDList.Clear();
137 | foreach (var sid in x)
138 | MW.SIDList.Add(new BoolStringClass(SecurityDescriptor.SIDToLong(sid, MW.IsTranslateSID), sid));
139 | }), sortedSIDs);
140 | }
141 |
142 | if (allRights.Count != prevRights)
143 | {
144 | prevRights = allRights.Count;
145 | MW.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
146 | {
147 | var newRightsList = new ObservableCollection();
148 | foreach (var element in MW.RightsList)
149 | {
150 | if (allRights.Contains(element.Tag))
151 | element.TextBrush = new SolidColorBrush(Color.FromRgb(50, 150, 255));
152 | newRightsList.Add(element);
153 | }
154 | MW.RightsList.Clear();
155 | foreach (var element in newRightsList)
156 | MW.RightsList.Add(element);
157 | }));
158 | }
159 | }
160 | if (TextChangedEvent.WaitOne(0))
161 | {
162 | if (_textChangedSpinnerThread != null && _textChangedSpinnerThread.IsAlive)
163 | _textChangedSpinnerThread.Join();
164 | Thread.CurrentThread.Abort();
165 | return;
166 | }
167 | }
168 |
169 | TextChangedEvent.Set();
170 | if (_textChangedSpinnerThread != null && _textChangedSpinnerThread.IsAlive)
171 | _textChangedSpinnerThread.Join();
172 | Thread.CurrentThread.Abort();
173 | }
174 |
175 | private static string _fillData;
176 |
177 | public static void ButtonFillServicesClicked()
178 | {
179 | var work = new Thread(ServiceFill);
180 | var abortEvent = new ManualResetEvent(false);
181 | var dlg = new UIPerformWorkWindow(MW, abortEvent, "Count services...");
182 | work.Start(dlg);
183 | if (dlg.ShowDialog() ?? false)
184 | {
185 | MW.SetContent();
186 | if (MW.CmbxRightsType.SelectedIndex != 0)
187 | MW.CmbxRightsType.SelectedIndex = 0;
188 | MW.SetContent(_fillData);
189 | }
190 | work.Join();
191 | }
192 |
193 | private static void ServiceFill(object o)
194 | {
195 | var ww = (UIPerformWorkWindow) o;
196 | var sb = new StringBuilder();
197 | var services = ServiceController.GetServices();
198 | var managerHandle = Win32Native.OpenSCManager(null, null, 0x20004);
199 | for (var i = 0; i < services.Length; i++)
200 | {
201 | var service = services[i];
202 | try
203 | {
204 | var localSb = new StringBuilder();
205 | localSb.AppendLine($"{service.DisplayName} ({service.ServiceName})");
206 | var serviceHandle = Win32Native.OpenService(managerHandle, service.ServiceName, 0x20000);
207 | uint sdSize;
208 | var result = Win32Native.QueryServiceObjectSecurity(serviceHandle, 7, null, 0, out sdSize);
209 | var gle = Marshal.GetLastWin32Error();
210 | if (result || (gle != 122))
211 | {
212 | Win32Native.CloseServiceHandle(serviceHandle);
213 | throw new System.ComponentModel.Win32Exception(gle);
214 | }
215 | var binarySd = new byte[sdSize];
216 | result = Win32Native.QueryServiceObjectSecurity(serviceHandle, 7, binarySd, binarySd.Length, out sdSize);
217 | gle = Marshal.GetLastWin32Error();
218 | if (!result)
219 | {
220 | Win32Native.CloseServiceHandle(serviceHandle);
221 | throw new System.ComponentModel.Win32Exception(gle);
222 | }
223 | var cd = new CommonSecurityDescriptor(false, false, binarySd, 0);
224 | localSb.AppendLine(cd.GetSddlForm(AccessControlSections.All));
225 | sb.AppendLine(localSb.ToString());
226 | Win32Native.CloseServiceHandle(serviceHandle);
227 | ww.Percentage = (int) ((i + 0.0) * 100.0 / (services.Length + 0.0));
228 | if (ww.AbortEvent.WaitOne(0))
229 | break;
230 | }
231 | catch
232 | {
233 | // continue
234 | }
235 | }
236 | Win32Native.CloseServiceHandle(managerHandle);
237 | _fillData = sb.ToString();
238 | ww.AbortEvent.Set();
239 | }
240 |
241 | public static void ButtonFillDirectoryClicked()
242 | {
243 | var dlg = new UIFolderRegPickerWindow(MW, true);
244 | if (dlg.ShowDialog() ?? false)
245 | {
246 | var work = new Thread(DirectoryFill);
247 | var abortEvent = new ManualResetEvent(false);
248 | var w = new UIPerformWorkWindow(MW, abortEvent, "Count directories...");
249 | work.Start(new Tuple(dlg, w));
250 | if (w.ShowDialog() ?? false)
251 | {
252 | int target = 1;
253 | if (dlg.IsFilesInclude)
254 | target = 3;
255 | MW.SetContent();
256 | if (MW.CmbxRightsType.SelectedIndex != target)
257 | MW.CmbxRightsType.SelectedIndex = target;
258 | MW.SetContent(_fillData);
259 | }
260 | work.Join();
261 | }
262 | }
263 |
264 | private static int _maxFiles;
265 | private static int _currentFiles;
266 | private static bool _isFileInclude;
267 | private static bool _isRecursing;
268 | private static UIPerformWorkWindow _ww;
269 | private static StringBuilder _sb;
270 |
271 | private static void DirectoryFill(object o)
272 | {
273 | var t = (Tuple) o;
274 | _sb = new StringBuilder();
275 | _ww = t.Item2;
276 | _currentFiles = 0;
277 | _isFileInclude = t.Item1.IsFilesInclude;
278 | _isRecursing = t.Item1.IsRecursing;
279 | _maxFiles = CalcDirCount(t.Item1.PathName) + 1;
280 | UpdateDirectory(t.Item1.PathName);
281 | _fillData = _sb.ToString();
282 | t.Item2.AbortEvent.Set();
283 | }
284 |
285 | private static int CalcDirCount(string path)
286 | {
287 | if (_ww.AbortEvent.WaitOne(0))
288 | return 0;
289 | List dirs;
290 | try
291 | {
292 | dirs = DirectorySearcher.MyGetDirectories(path);
293 | }
294 | catch
295 | {
296 | return 1;
297 | }
298 | var c = 1;
299 | if (_isRecursing)
300 | foreach (var dir in dirs)
301 | c += CalcDirCount(dir);
302 | if (_isFileInclude)
303 | c += DirectorySearcher.MyGetFiles(path).Count;
304 | return c;
305 | }
306 |
307 | private static void UpdateDirectory(string path)
308 | {
309 | var localSb = new StringBuilder();
310 | localSb.AppendLine(path);
311 | _currentFiles++;
312 | var sddlString = "Unable obtain SDDL";
313 | try
314 | {
315 | sddlString = Directory.GetAccessControl(path).GetSecurityDescriptorSddlForm(AccessControlSections.All);
316 | }
317 | catch
318 | {
319 | // ignore
320 | }
321 | localSb.AppendLine(sddlString);
322 | _sb.AppendLine(localSb.ToString());
323 | foreach (var dir in DirectorySearcher.MyGetDirectories(path))
324 | {
325 | try
326 | {
327 | if (_isRecursing)
328 | UpdateDirectory(dir);
329 | else
330 | {
331 | localSb.Clear();
332 | localSb.AppendLine(dir);
333 | _currentFiles++;
334 | localSb.AppendLine(Directory.GetAccessControl(dir).GetSecurityDescriptorSddlForm(AccessControlSections.All));
335 | _sb.AppendLine(localSb.ToString());
336 | }
337 | }
338 | catch
339 | {
340 | // ignore
341 | }
342 | _ww.Percentage = (int)((_currentFiles + 0.0) * 100.0 / (_maxFiles + 0.0));
343 | if (_ww.AbortEvent.WaitOne(0))
344 | return;
345 | }
346 | if (_isFileInclude)
347 | foreach (var file in DirectorySearcher.MyGetFiles(path))
348 | {
349 | try
350 | {
351 | localSb.Clear();
352 | localSb.AppendLine(file);
353 | _currentFiles++;
354 | localSb.AppendLine(File.GetAccessControl(file).GetSecurityDescriptorSddlForm(AccessControlSections.All));
355 | _sb.AppendLine(localSb.ToString());
356 | }
357 | catch
358 | {
359 | // ignore
360 | }
361 | _ww.Percentage = (int)((_currentFiles + 0.0) * 100.0 / (_maxFiles + 0.0));
362 | if (_ww.AbortEvent.WaitOne(0))
363 | return;
364 | }
365 | }
366 |
367 | public static void ButtonFillFilesClicked()
368 | {
369 | var dlg = new OpenFileDialog
370 | {
371 | Multiselect = true,
372 | Filter = "All files (*.*)|*.*"
373 | };
374 | if (dlg.ShowDialog() ?? false)
375 | {
376 | MW.SetContent();
377 | if (MW.CmbxRightsType.SelectedIndex != 2)
378 | MW.CmbxRightsType.SelectedIndex = 2;
379 | var sb = new StringBuilder();
380 | foreach (var file in dlg.FileNames)
381 | {
382 | try
383 | {
384 | if ((string.IsNullOrWhiteSpace(file)) || (!File.Exists(file)))
385 | continue;
386 | var localSb = new StringBuilder();
387 | localSb.AppendLine($"{file}");
388 | var sddlString = "Unable obtain SDDL";
389 | try
390 | {
391 | sddlString = File.GetAccessControl(file).GetSecurityDescriptorSddlForm(AccessControlSections.All);
392 | }
393 | catch
394 | {
395 | // ignore
396 | }
397 | localSb.AppendLine(sddlString);
398 | sb.AppendLine(localSb.ToString());
399 | }
400 | catch
401 | {
402 | // continue
403 | }
404 | }
405 | MW.SetContent(sb.ToString());
406 | }
407 | }
408 |
409 | public static void ButtonFillRegistryClicked()
410 | {
411 | var dlg = new UIFolderRegPickerWindow(MW, false);
412 | if (dlg.ShowDialog() ?? false)
413 | {
414 | var work = new Thread(RegistryFill);
415 | var abortEvent = new ManualResetEvent(false);
416 | var w = new UIPerformWorkWindow(MW, abortEvent, "Count reg-keys...");
417 | work.Start(new Tuple(dlg, w));
418 | if (w.ShowDialog() ?? false)
419 | {
420 | MW.SetContent();
421 | if (MW.CmbxRightsType.SelectedIndex != 4)
422 | MW.CmbxRightsType.SelectedIndex = 4;
423 | MW.SetContent(_fillData);
424 | }
425 | work.Join();
426 | }
427 | }
428 |
429 | private static void RegistryFill(object o)
430 | {
431 | var t = (Tuple)o;
432 | _sb = new StringBuilder();
433 | _ww = t.Item2;
434 | _currentFiles = 0;
435 | _isFileInclude = t.Item1.IsFilesInclude;
436 | _isRecursing = t.Item1.IsRecursing;
437 | var key = UIFolderRegPickerWindow.GetKeyFromString(t.Item1.PathName);
438 | _maxFiles = CalcKeyCount(key) + 1;
439 | UpdateRegKey(key);
440 | _fillData = _sb.ToString();
441 | t.Item2.AbortEvent.Set();
442 | }
443 |
444 | private static int CalcKeyCount(RegistryKey key)
445 | {
446 | if (_ww.AbortEvent.WaitOne(0))
447 | return 0;
448 | string[] keys;
449 | try
450 | {
451 | keys = key.GetSubKeyNames();
452 | }
453 | catch
454 | {
455 | return 1;
456 | }
457 | var c = 1;
458 | if (_isRecursing)
459 | foreach (var k in keys)
460 | try
461 | {
462 | c += CalcKeyCount(key.OpenSubKey(k));
463 | }
464 | catch
465 | {
466 | c++;
467 | }
468 | return c;
469 | }
470 |
471 | private static void UpdateRegKey(RegistryKey key)
472 | {
473 | var localSb = new StringBuilder();
474 | localSb.AppendLine(key.Name);
475 | _currentFiles++;
476 | var sddlString = "Unable obtain SDDL";
477 | try
478 | {
479 | sddlString = key.GetAccessControl().GetSecurityDescriptorSddlForm(AccessControlSections.All);
480 | }
481 | catch
482 | {
483 | // ignore
484 | }
485 | localSb.AppendLine(sddlString);
486 | _sb.AppendLine(localSb.ToString());
487 | if (key.SubKeyCount != 0)
488 | foreach (var sub in key.GetSubKeyNames())
489 | {
490 | try
491 | {
492 | var oKey = key.OpenSubKey(sub);
493 | if (oKey != null)
494 | if (_isRecursing)
495 | UpdateRegKey(oKey);
496 | else
497 | {
498 | localSb.Clear();
499 | localSb.AppendLine(oKey.Name);
500 | _currentFiles++;
501 | localSb.AppendLine(
502 | oKey.GetAccessControl().GetSecurityDescriptorSddlForm(AccessControlSections.All));
503 | _sb.AppendLine(localSb.ToString());
504 | }
505 | }
506 | catch
507 | {
508 | // ignored
509 | }
510 | _ww.Percentage = (int) ((_currentFiles + 0.0) * 100.0 / (_maxFiles + 0.0));
511 | if (_ww.AbortEvent.WaitOne(0))
512 | return;
513 | }
514 | }
515 |
516 | public static void ButtonSaveClicked()
517 | {
518 | var dlg = new SaveFileDialog
519 | {
520 | FileName = "raw_sddl",
521 | DefaultExt = ".txt",
522 | Filter = "Text documents (*.txt)|*.txt|All files (*.*)|*.*",
523 | FilterIndex = 0,
524 | OverwritePrompt = true
525 | };
526 | if (dlg.ShowDialog() ?? false)
527 | File.WriteAllText(dlg.FileName, MW.GetContent());
528 | }
529 |
530 | public static void ButtonAll(int listboxNumber, bool state)
531 | {
532 | ListBox lb = null;
533 | switch (listboxNumber)
534 | {
535 | case 0:
536 | lb = MW.LstChkSIDs;
537 | break;
538 |
539 | case 1:
540 | lb = MW.LstChkRights;
541 | break;
542 | }
543 | if (lb != null)
544 | foreach (var lbItem in lb.ItemsSource)
545 | if (lbItem is BoolStringClass)
546 | (lbItem as BoolStringClass).IsSelected = state;
547 | List tmp;
548 | switch (listboxNumber)
549 | {
550 | case 0:
551 | tmp = new List(MW.SIDList);
552 | MW.SIDList.Clear();
553 | foreach (var element in tmp)
554 | MW.SIDList.Add(element);
555 | break;
556 |
557 | case 1:
558 | tmp = new List(MW.RightsList);
559 | MW.RightsList.Clear();
560 | foreach (var element in tmp)
561 | MW.RightsList.Add(element);
562 | break;
563 | }
564 | }
565 |
566 | public static void ButtonMakeReport()
567 | {
568 | var listInterestSIDs = (from sid in MW.SIDList where sid.IsSelected select sid.Tag).ToList();
569 | var listInterestRights = (from right in MW.RightsList where right.IsSelected select right.Tag).ToList();
570 |
571 | new UIReportWindow(MW, MW.GetContent(), listInterestSIDs, listInterestRights, MW.CmbxRightsType.SelectedIndex).ShowDialog();
572 | }
573 |
574 | public static void OnClose()
575 | {
576 | if (!TextChangedEvent.WaitOne(0))
577 | TextChangedEvent.Set();
578 | }
579 |
580 | public static void ButtonOpenClicked()
581 | {
582 | var dlg = new OpenFileDialog
583 | {
584 | FileName = "raw_sddl",
585 | DefaultExt = ".txt",
586 | Filter = "Text documents (*.txt)|*.txt|All files (*.*)|*.*",
587 | FilterIndex = 0,
588 | CheckFileExists = true,
589 | CheckPathExists = true
590 | };
591 | if (dlg.ShowDialog() ?? false)
592 | {
593 | MW.SetContent();
594 | MW.SetContent(File.ReadAllText(dlg.FileName));
595 | }
596 | }
597 |
598 | public static void ButtonTranslateClicked()
599 | {
600 | TextChangedContentEdit();
601 | }
602 | }
603 | }
604 |
--------------------------------------------------------------------------------
/SDDLViewer/Logic/SecurityUnit/ACE.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Text;
5 |
6 | namespace SDDLViewer
7 | {
8 | public class ACE
9 | {
10 | public const int AllowRule = 0;
11 | public const int DenyRule = 1;
12 | public const int OtherRule = 2;
13 |
14 | private readonly string _ace;
15 | public readonly bool IsOk;
16 |
17 | private readonly string _type;
18 | private readonly string _righs;
19 | private readonly string _sid;
20 |
21 | private static readonly List> RightsValues = new List>()
22 | {
23 | new Tuple(0x001200A0, "FX"),
24 | new Tuple(0x00120116, "FW"),
25 | new Tuple(0x00120089, "FR"),
26 | new Tuple(0x001F01FF, "FA"),
27 | new Tuple(0x00120116, "FW"),
28 |
29 | new Tuple(0x00000100, "CR"),
30 | new Tuple(0x00000080, "LO"),
31 | new Tuple(0x00000040, "DT"),
32 | new Tuple(0x00000020, "WP"),
33 | new Tuple(0x00000010, "RP"),
34 | new Tuple(0x00000008, "SW"),
35 | new Tuple(0x00000004, "LC"),
36 | new Tuple(0x00000002, "DC"),
37 | new Tuple(0x00000001, "CC"),
38 |
39 | new Tuple(0x00010000, "SD"),
40 | new Tuple(0x00020000, "RC"),
41 | new Tuple(0x00040000, "Wd"),
42 | new Tuple(0x00080000, "WO"),
43 | };
44 |
45 | public ACE(string ace)
46 | {
47 | _ace = ace;
48 | try
49 | {
50 | var lst = _ace.Substring(1, _ace.Length - 2).Split(';');
51 | if (lst.Length != 6)
52 | throw new Exception();
53 | _type = lst[0];
54 | _righs = lst[2];
55 | if (_righs.StartsWith("0x"))
56 | {
57 | var r = "";
58 | UInt32 v = UInt32.Parse(_righs.Substring(2), NumberStyles.AllowHexSpecifier);
59 | UInt32 v2 = 0;
60 | foreach (var value in RightsValues)
61 | {
62 | if ((v & value.Item1) == value.Item1)
63 | {
64 | r += value.Item2;
65 | v2 |= value.Item1;
66 | }
67 | }
68 | if (v2 != v)
69 | r += "??";
70 | _righs = r;
71 | }
72 | _sid = lst[5];
73 | IsOk = true;
74 | }
75 | catch
76 | {
77 | IsOk = false;
78 | }
79 | }
80 |
81 | public string GetSID()
82 | {
83 | return _sid;
84 | }
85 |
86 | public List GetAllRights()
87 | {
88 | var rv = new List();
89 | for (var i = 0; i < _righs.Length / 2; i++)
90 | rv.Add(_righs.Substring(2 * i, 2));
91 | return rv;
92 | }
93 |
94 | public string WithNewRights(List newRights)
95 | {
96 | var sb = new StringBuilder();
97 | sb.Append('(');
98 | var lst = _ace.Substring(1, _ace.Length - 2).Split(';');
99 | for (int i = 0; i < lst.Length; i++)
100 | {
101 | if (i != 0)
102 | sb.Append(';');
103 | if (i == 2)
104 | foreach (var r in newRights)
105 | sb.Append(r);
106 | else
107 | sb.Append(lst[i]);
108 | }
109 | sb.Append(')');
110 | return sb.ToString();
111 | }
112 |
113 | public static string RigthToLong(string right, int rightsType = -1)
114 | {
115 | switch (right)
116 | {
117 | case "GA": return "[GA] Generic All";
118 | case "GX": return "[GX] Generic Execute/Traverse";
119 | case "GW": return "[GW] Generic Write";
120 | case "GR": return "[GR] Generic Read";
121 | case "SD": return "[SD] Standard Delete";
122 | case "RC": return "[RC] Read Control";
123 | case "WD": return "[WD] Write Discretionary Access Control";
124 | case "WO": return "[WO] Write Owner";
125 | }
126 | switch (rightsType)
127 | {
128 | case 0:
129 | switch (right)
130 | {
131 | case "CC": return "[CC] Query Configuration";
132 | case "DC": return "[DC] Change Configuration";
133 | case "LC": return "[LC] Query Status";
134 | case "DW": return "[SW] Enumerate Dependencies";
135 | case "RP": return "[RP] Start";
136 | case "WP": return "[WP] Stop";
137 | case "DT": return "[DT] Pause";
138 | case "LO": return "[LO] Interrogate";
139 | case "CR": return "[CR] User Defined";
140 | }
141 | break;
142 |
143 | case 1:
144 | switch (right)
145 | {
146 | case "CC": return "[CC] List Directory";
147 | case "DC": return "[DC] Create File";
148 | case "LC": return "[LC] Create Subdirectory";
149 | case "SW": return "[SW] Read Extended Attributes";
150 | case "RP": return "[RP] Write Extended Attributes";
151 | case "WP": return "[WP] Traverse Directory";
152 | case "DT": return "[DT] Delete Tree";
153 | case "LO": return "[LO] Read Attributes";
154 | case "CR": return "[CR] Write Attributes";
155 | }
156 | break;
157 |
158 | case 2:
159 | switch (right)
160 | {
161 | case "CC": return "[CC] Read Data";
162 | case "DC": return "[DC] Write Data";
163 | case "LC": return "[LC] Append Data";
164 | case "SW": return "[SW] Read Extended Attributes";
165 | case "RP": return "[RP] Write Extended Attributes";
166 | case "WP": return "[WP] Execute File";
167 | case "LO": return "[LO] Read Attributes";
168 | case "CR": return "[CR] Write Attributes";
169 | case "FA": return "[FA] File All";
170 | case "FR": return "[FR] File Read";
171 | case "FW": return "[FW] File Write";
172 | case "FX": return "[FX] File Execute";
173 | }
174 | break;
175 |
176 | case 3:
177 | switch (right)
178 | {
179 | case "CC": return "[CC] Read Data / List Directory";
180 | case "DC": return "[DC] Write Data / Create File";
181 | case "LC": return "[LC] Append Data / Create Subdirectory";
182 | case "SW": return "[SW] Read Extended Attributes";
183 | case "RP": return "[RP] Write Extended Attributes";
184 | case "WP": return "[WP] Execute File / Traverse Directory";
185 | case "DT": return "[DT] Delete Tree";
186 | case "LO": return "[LO] Read Attributes";
187 | case "CR": return "[CR] Write Attributes";
188 | case "FA": return "[FA] File All";
189 | case "FR": return "[FR] File Read";
190 | case "FW": return "[FW] File Write";
191 | case "FX": return "[FX] File Execute";
192 | }
193 | break;
194 |
195 | case 4:
196 | switch (right)
197 | {
198 | case "CC": return "[CC] Query Value";
199 | case "DC": return "[DC] Set Value";
200 | case "LC": return "[LC] Create Subkey";
201 | case "SW": return "[SW] Enumerate Subkeys";
202 | case "RP": return "[RP] Notify";
203 | case "WP": return "[WP] Create Link";
204 | case "KA": return "[KA] Key All";
205 | case "KR": return "[KR] Key Read";
206 | case "KW": return "[KW] Key Write";
207 | case "KX": return "[KX] Key Execute";
208 | }
209 | break;
210 | }
211 | return $"[{right}] ??";
212 | }
213 |
214 | public static string RightType(int rightsType)
215 | {
216 | switch (rightsType)
217 | {
218 | case 0:
219 | return "Service Access Rights";
220 | case 1:
221 | return "Directory Access Rights";
222 | case 2:
223 | return "File Access Rights";
224 | case 3:
225 | return "File and Directory Access Rights";
226 | case 4:
227 | return "Registry Key Access Rights";
228 | default:
229 | return "??";
230 | }
231 | }
232 |
233 | public int GetRuleType()
234 | {
235 | switch (_type)
236 | {
237 | case "A":
238 | return ACE.AllowRule;
239 | case "D":
240 | return ACE.DenyRule;
241 | default:
242 | return ACE.OtherRule;
243 | }
244 | }
245 | }
246 | }
--------------------------------------------------------------------------------
/SDDLViewer/Logic/SecurityUnit/SecurityDescriptor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Security.Principal;
4 |
5 | namespace SDDLViewer
6 | {
7 | public class SecurityDescriptor
8 | {
9 | private readonly string _sddl;
10 |
11 | private readonly string _owner;
12 | private readonly string _group;
13 | private readonly List _dacl;
14 | private readonly List _sacl;
15 |
16 | public readonly bool IsOk;
17 |
18 | public SecurityDescriptor(string sddl)
19 | {
20 | _sddl = sddl.Trim();
21 | _owner = "";
22 | _group = "";
23 | _dacl = new List();
24 | _sacl = new List();
25 | var state = 0; // 1 - dacl, 2-sacl
26 |
27 | try
28 | {
29 | var index = 0;
30 | while (index < _sddl.Length)
31 | {
32 | if (_sddl[index] == 'O')
33 | {
34 | if (_sddl[index+1] != ':')
35 | {
36 | IsOk = false;
37 | return;
38 | }
39 | index += 2;
40 | _owner = ParseSID(_sddl, ref index);
41 | continue;
42 | }
43 | if (_sddl[index] == 'G')
44 | {
45 | if (_sddl[index + 1] != ':')
46 | {
47 | IsOk = false;
48 | return;
49 | }
50 | index += 2;
51 | _group = ParseSID(_sddl, ref index);
52 | continue;
53 | }
54 | if (_sddl[index] == 'D')
55 | {
56 | if (_sddl[index + 1] != ':')
57 | {
58 | IsOk = false;
59 | return;
60 | }
61 | index += 2;
62 | ParseFlags(_sddl, ref index);
63 | state = 1;
64 | continue;
65 | }
66 | if (_sddl[index] == 'S')
67 | {
68 | if (_sddl[index + 1] != ':')
69 | {
70 | IsOk = false;
71 | return;
72 | }
73 | index += 2;
74 | ParseFlags(_sddl, ref index);
75 | state = 2;
76 | continue;
77 | }
78 | if (_sddl[index] == '(')
79 | {
80 | var ace = ParseACE(_sddl, ref index);
81 | if (!ace.IsOk)
82 | {
83 | IsOk = false;
84 | return;
85 | }
86 | switch (state)
87 | {
88 | case 1:
89 | _dacl.Add(ace);
90 | break;
91 | case 2:
92 | _sacl.Add(ace);
93 | break;
94 | default:
95 | IsOk = false;
96 | return;
97 | }
98 | continue;
99 | }
100 | IsOk = false;
101 | return;
102 | }
103 | IsOk = true;
104 | }
105 | catch
106 | {
107 | IsOk = false;
108 | }
109 | }
110 |
111 | private static readonly List KnownSIDsList = new List
112 | {
113 | "AA", "AC", "AN", "AO", "AU", "BA", "BG", "BO", "BU", "CA",
114 | "CD", "CG", "CN", "CO", "CY", "DA", "DC", "DD", "DG", "DU",
115 | "EA", "ED", "ER", "ES", "HA", "HI", "IS", "IU", "LA", "LG",
116 | "LS", "LU", "LW", "ME", "MP", "MS", "MU", "NO", "NS", "NU",
117 | "OW", "PA", "PO", "PS", "PU", "RA", "RC", "RD", "RE", "RM",
118 | "RO", "RS", "RU", "SA", "SI", "SO", "SU", "SY", "UD", "WD",
119 | "WR"
120 | };
121 |
122 | private string ParseSID(string s, ref int index)
123 | {
124 | var tmp = s.Substring(index, 2);
125 | if (KnownSIDsList.Contains(tmp))
126 | {
127 | index += 2;
128 | return tmp;
129 | }
130 | if (tmp != "S-")
131 | throw new Exception();
132 | var start = index;
133 | index += 2;
134 | while (index < s.Length)
135 | {
136 | if ("0123456789-".IndexOf(s[index]) == -1)
137 | break;
138 | index++;
139 | }
140 | var sid = s.Substring(start, index - start);
141 | if ((sid.IndexOf("--") != -1) || (sid[sid.Length - 1] == '-'))
142 | throw new Exception();
143 | return sid;
144 | }
145 |
146 | private void ParseFlags(string s, ref int index)
147 | {
148 | while (index < s.Length)
149 | {
150 | if (s[index] == 'P')
151 | {
152 | index++;
153 | continue;
154 | }
155 | var tmp = s.Substring(index, 2);
156 | if ((tmp == "AI") || (tmp == "AR"))
157 | {
158 | index += 2;
159 | continue;
160 | }
161 | return;
162 | }
163 | }
164 |
165 | private ACE ParseACE(string s, ref int index)
166 | {
167 | var start = index;
168 | while (s[index] != ')')
169 | index++;
170 | index++;
171 | var rv = new ACE(s.Substring(start, index - start));
172 | return rv;
173 | }
174 |
175 | public List GetAllSIDs()
176 | {
177 | var rv = new List();
178 | if (!string.IsNullOrWhiteSpace(_owner))
179 | if (!rv.Contains(_owner))
180 | rv.Add(_owner);
181 | if (!string.IsNullOrWhiteSpace(_group))
182 | if (!rv.Contains(_group))
183 | rv.Add(_group);
184 | foreach (var ace in _dacl)
185 | if (!string.IsNullOrWhiteSpace(ace.GetSID()))
186 | if (!rv.Contains(ace.GetSID()))
187 | rv.Add(ace.GetSID());
188 | foreach (var ace in _sacl)
189 | if (!string.IsNullOrWhiteSpace(ace.GetSID()))
190 | if (!rv.Contains(ace.GetSID()))
191 | rv.Add(ace.GetSID());
192 | return rv;
193 | }
194 |
195 | public static string SIDToLong(string sid, bool translateSID)
196 | {
197 | if (sid.Length < 2)
198 | return sid;
199 | if (sid[1] == '-')
200 | {
201 | if (!translateSID)
202 | return "\t" + sid;
203 | try
204 | {
205 | var t = new SecurityIdentifier(sid).Translate(typeof(NTAccount)).ToString();
206 | return "[??]\t" + sid + " \t" + (string.IsNullOrWhiteSpace(t) ? "??" : t);
207 | }
208 | catch
209 | {
210 | return "[??]\t" + sid;
211 | }
212 | }
213 | switch (sid)
214 | {
215 | case "AA": return "[AA]\tS-1-5-32-579 \tAccess Control Assistance Operators";
216 | case "AC": return "[AC]\tS-1-15-2-1 \tAll App Packages";
217 | case "AN": return "[AN]\tS-1-5-7 \tAnonymous Logged-on Users";
218 | case "AO": return "[AO]\tS-1-5-32-548 \tAccount Operators";
219 | case "AU": return "[AU]\tS-1-5-11 \tAuthenticated Users";
220 | case "BA": return "[BA]\tS-1-5-32-544 \tBuilt-in (Local) Administrators";
221 | case "BG": return "[BG]\tS-1-5-32-546 \tBuilt-in (Local) Guests";
222 | case "BO": return "[BO]\tS-1-5-32-551 \tBackup Operators";
223 | case "BU": return "[BU]\tS-1-5-32-545 \tBuilt-in (Local) Users";
224 | case "CA": return "[CA]\tS-1-5-32-517 \tCertificate Server Administrators";
225 | case "CD": return "[CD]\tS-1-5-32-574 \tUsers who can connect to certification authorities using Distributed Component Object Model (DCOM)";
226 | case "CG": return "[CG]\tS-1-3-1 \tCreator Group";
227 | case "CN": return "[CN]\tS-1-5-32-522 \tCloneable Controllers";
228 | case "CO": return "[CO]\tS-1-3-0 \tCreator Owner";
229 | case "CY": return "[CY]\tS-1-5-32-569 \tCrypto Operators";
230 | case "DA": return "[DA]\tS-1-5-32-512 \tDomain Administrators";
231 | case "DC": return "[DC]\tS-1-5-32-515 \tDomain Computers";
232 | case "DD": return "[DD]\tS-1-5-32-516 \tDomain Controllers";
233 | case "DG": return "[DG]\tS-1-5-32-514 \tDomain Guests";
234 | case "DU": return "[DU]\tS-1-5-32-513 \tDomain Users";
235 | case "EA": return "[EA]\tS-1-5-32-519 \tEnterprise Administrators";
236 | case "ED": return "[ED]\tS-1-5-9 \tEnterprise Domain Controllers";
237 | case "ER": return "[ER]\tS-1-5-32-573 \tEvent Log Readers";
238 | case "ES": return "[ES]\tS-1-5-32-576 \tRDS Endpoint Servers";
239 | case "HA": return "[HA]\tS-1-5-32-578 \tHyper-V Administrators";
240 | case "HI": return "[HI]\tS-1-16-12288 \tHigh Integrity Level";
241 | case "IS": return "[IS]\tS-1-5-32-568 \tAnonymous Internet Users";
242 | case "IU": return "[IU]\tS-1-5-4 \tInteractive Logged-on Users";
243 | case "LA": return "[LS]\tS-1-5-21-*-*-*-500 \tLocal Administrator Account";
244 | case "LG": return "[LG]\tS-1-5-21-*-*-*-501 \tLocal Guest Account";
245 | case "LS": return "[LS]\tS-1-5-19 \tLocal Service Account";
246 | case "LU": return "[LU]\tS-1-5-32-559 \tPerformance Log Users";
247 | case "LW": return "[LW]\tS-1-16-4096 \tLow Security Level";
248 | case "ME": return "[ME]\tS-1-16-8192 \tMedium Security Level";
249 | case "MP": return "[MP]\tS-1-16-8448 \tMedium Plus Security Level";
250 | case "MS": return "[MS]\tS-1-5-32-577 \tRDS Management Servers";
251 | case "MU": return "[MU]\tS-1-5-32-558 \tPerformance Monitor Users";
252 | case "NO": return "[NO]\tS-1-5-32-556 \tNetwork Configuration Operators";
253 | case "NS": return "[NS]\tS-1-5-20 \tNetwork Service Account";
254 | case "NU": return "[NU]\tS-1-5-2 \tNetwork Logged-on Users";
255 | case "OW": return "[OW]\tS-1-3-4 \tOwner Rights";
256 | case "PA": return "[PA]\tS-1-5-32-520 \tGroup Policy Administrators";
257 | case "PO": return "[PO]\tS-1-5-32-550 \tPrinter Operators";
258 | case "PS": return "[PS]\tS-1-5-10 \tPrincipal Self/Personal Self";
259 | case "PU": return "[PU]\tS-1-5-32-547 \tPower Users";
260 | case "RA": return "[RA]\tS-1-5-32-575 \tRDS Remote Access Servers";
261 | case "RC": return "[RC]\tS-1-5-12 \tRestricted Code";
262 | case "RD": return "[RD]\tS-1-5-32-555 \tTerminal Server Users (Remote Desktop)";
263 | case "RE": return "[RE]\tS-1-5-32-552 \tReplicator";
264 | case "RM": return "[RM]\tS-1-5-32-580 \tRemote Management Users";
265 | case "RO": return "[RO]\tS-1-5-32-498 \tEnterprise Read-Only Domain Controllers";
266 | case "RS": return "[RS]\tS-1-5-32-553 \tRemote Access Servers";
267 | case "RU": return "[RU]\tS-1-5-32-554 \tAlias to grant permissions to accounts using applications compatible with Windows NT 4.0 operating systems";
268 | case "SA": return "[SA]\tS-1-5-32-518 \tSchema Administrators";
269 | case "SI": return "[SI]\tS-1-16-16384 \tSystem Integrity Level";
270 | case "SO": return "[SO]\tS-1-5-32-549 \tServer Operators";
271 | case "SU": return "[SU]\tS-1-5-6 \tService Logged-on Users";
272 | case "SY": return "[SY]\tS-1-5-18 \tLocal System Account";
273 | case "UD": return "[UD]\tS-1-5-84-0-0-0-0-0 \tUser-Mode Drivers";
274 | case "WD": return "[WD]\tS-1-1-0 \tWorld (Everyone)";
275 | case "WR": return "[WR]\tS-1-5-33 \tWrite Restricted Code";
276 | default:
277 | return sid;
278 | }
279 | }
280 |
281 | public List GetAllRights()
282 | {
283 | var rv = new List();
284 | foreach (var ace in _dacl)
285 | {
286 | var l = ace.GetAllRights();
287 | foreach (var right in l)
288 | {
289 | if (!rv.Contains(right))
290 | rv.Add(right);
291 | }
292 | }
293 | foreach (var ace in _sacl)
294 | {
295 | var l = ace.GetAllRights();
296 | foreach (var right in l)
297 | {
298 | if (!rv.Contains(right))
299 | rv.Add(right);
300 | }
301 | }
302 | return rv;
303 | }
304 |
305 | public string GetOwner()
306 | {
307 | return _owner;
308 | }
309 |
310 | public string GetGroup()
311 | {
312 | return _group;
313 | }
314 |
315 | public List GetACEs()
316 | {
317 | return _dacl;
318 | }
319 | }
320 | }
--------------------------------------------------------------------------------
/SDDLViewer/Logic/Win32Native.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.ConstrainedExecution;
4 | using System.Runtime.InteropServices;
5 | using System.Security.Permissions;
6 | using Microsoft.Win32.SafeHandles;
7 |
8 | namespace SDDLViewer
9 | {
10 | public static class Win32Native
11 | {
12 | [DllImport("advapi32.dll", SetLastError = true)]
13 | public static extern bool QueryServiceObjectSecurity(IntPtr serviceHandle, UInt32 secInfo, byte[] lpSecDesrBuf, int bufSize, out uint bufSizeNeeded);
14 |
15 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
16 | public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
17 |
18 | [DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
19 | public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
20 |
21 | [DllImport("advapi32.dll", SetLastError = true)]
22 | [return: MarshalAs(UnmanagedType.Bool)]
23 | public static extern bool CloseServiceHandle(IntPtr hSCObject);
24 |
25 | [Serializable, StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto), BestFitMapping(false)]
26 | internal class WIN32_FIND_DATA
27 | {
28 | public FileAttributes dwFileAttributes;
29 | public uint ftCreationTime_dwLowDateTime;
30 | public uint ftCreationTime_dwHighDateTime;
31 | public uint ftLastAccessTime_dwLowDateTime;
32 | public uint ftLastAccessTime_dwHighDateTime;
33 | public uint ftLastWriteTime_dwLowDateTime;
34 | public uint ftLastWriteTime_dwHighDateTime;
35 | public uint nFileSizeHigh;
36 | public uint nFileSizeLow;
37 | public int dwReserved0;
38 | public int dwReserved1;
39 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
40 | public string cFileName;
41 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
42 | public string cAlternateFileName;
43 | }
44 |
45 | internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
46 | {
47 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
48 | [DllImport("kernel32.dll")]
49 | private static extern bool FindClose(IntPtr handle);
50 |
51 | ///
52 | /// Initializes a new instance of the class.
53 | ///
54 | [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
55 | internal SafeFindHandle()
56 | : base(true)
57 | {
58 | }
59 |
60 | ///
61 | /// When overridden in a derived class, executes the code required to free the handle.
62 | ///
63 | ///
64 | /// true if the handle is released successfully; otherwise, in the
65 | /// event of a catastrophic failure, false. In this case, it
66 | /// generates a releaseHandleFailed MDA Managed Debugging Assistant.
67 | ///
68 | protected override bool ReleaseHandle()
69 | {
70 | return FindClose(handle);
71 | }
72 | }
73 |
74 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
75 | internal static extern SafeFindHandle FindFirstFile(string fileName, [In, Out] WIN32_FIND_DATA data);
76 |
77 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
78 | internal static extern bool FindNextFile(SafeFindHandle hndFindFile, [In, Out, MarshalAs(UnmanagedType.LPStruct)] WIN32_FIND_DATA lpFindFileData);
79 | }
80 | }
--------------------------------------------------------------------------------
/SDDLViewer/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Service Access Rights
69 | Directory Access Rights
70 | File Access Rights
71 | File and Directory Access Rights
72 | Registry Key Access Rights
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/SDDLViewer/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.Threading;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Threading;
7 | using SDDLViewer.Logic;
8 | using SDDLViewer.UIPerformWork;
9 |
10 | namespace SDDLViewer
11 | {
12 | public partial class MainWindow : Window
13 | {
14 | public ObservableCollection RightsList { get; set; }
15 | public ObservableCollection SIDList { get; set; }
16 |
17 | public bool IsTranslateSID { get; set; }
18 | public bool IsIncludeAllow { get; set; }
19 | public bool IsIncludeDeny { get; set; }
20 |
21 | public MainWindow()
22 | {
23 | WindowStartupLocation = WindowStartupLocation.CenterScreen;
24 | Model.MW = this;
25 | SIDList = new ObservableCollection();
26 | RightsList = new ObservableCollection();
27 | IsTranslateSID = false;
28 | IsIncludeAllow = true;
29 | IsIncludeDeny = true;
30 | DataContext = this;
31 | InitializeComponent();
32 | }
33 |
34 | private void CmbxRightsType_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
35 | {
36 | Model.SelectionChangedRightsCombobox();
37 | }
38 |
39 | private void EdtContent_OnTextChanged(object sender, TextChangedEventArgs e)
40 | {
41 | Model.TextChangedContentEdit();
42 | }
43 |
44 | private void btnFillServices_OnClick(object sender, RoutedEventArgs e)
45 | {
46 | Model.ButtonFillServicesClicked();
47 | }
48 |
49 | private void btnFillDirectory_OnClick(object sender, RoutedEventArgs e)
50 | {
51 | Model.ButtonFillDirectoryClicked();
52 | }
53 |
54 | private void btnFillFiles_OnClick(object sender, RoutedEventArgs e)
55 | {
56 | Model.ButtonFillFilesClicked();
57 | }
58 |
59 | private void btnFillRegistry_OnClick(object sender, RoutedEventArgs e)
60 | {
61 | Model.ButtonFillRegistryClicked();
62 | }
63 |
64 | private void btnSave_OnClick(object sender, RoutedEventArgs e)
65 | {
66 | Model.ButtonSaveClicked();
67 | }
68 |
69 | private void btnCASIDS_OnClick(object sender, RoutedEventArgs e)
70 | {
71 | Model.ButtonAll(0, true);
72 | }
73 |
74 | private void btnUCASIDS_OnClick(object sender, RoutedEventArgs e)
75 | {
76 | Model.ButtonAll(0, false);
77 | }
78 |
79 | private void btnCARights_OnClick(object sender, RoutedEventArgs e)
80 | {
81 | Model.ButtonAll(1, true);
82 | }
83 |
84 | private void btnUCARights_OnClick(object sender, RoutedEventArgs e)
85 | {
86 | Model.ButtonAll(1, false);
87 | }
88 |
89 | private void btnMakeReport_OnClick(object sender, RoutedEventArgs e)
90 | {
91 | Model.ButtonMakeReport();
92 | }
93 |
94 | private void MainWindow_OnClosed(object sender, EventArgs e)
95 | {
96 | Model.OnClose();
97 | }
98 |
99 | private void btnOpen_OnClick(object sender, RoutedEventArgs e)
100 | {
101 | Model.ButtonOpenClicked();
102 | }
103 |
104 | private void chkTranslateSIDs_OnClick(object sender, RoutedEventArgs e)
105 | {
106 | Model.ButtonTranslateClicked();
107 | }
108 |
109 | public const int CONTENT_CHUNK_SIZE = 50000;
110 |
111 | public void SetContent(string content = null)
112 | {
113 | var setContent = content ?? string.Empty;
114 | if (setContent.Length < CONTENT_CHUNK_SIZE)
115 | {
116 | EdtContent.Text = setContent;
117 | return;
118 | }
119 | EdtContent.TextChanged -= EdtContent_OnTextChanged;
120 | var abortEvent = new ManualResetEvent(false);
121 | var dlg = new UIPerformWorkWindow(this, abortEvent, "Displaying content", "Displaying content: {0,3}%");
122 | Thread work = new Thread(ContentUpdate);
123 | work.Start(new Tuple(setContent, dlg));
124 | dlg.ShowDialog();
125 | work.Join();
126 | }
127 |
128 | private void ContentUpdate(object obj)
129 | {
130 | var t = (Tuple) obj;
131 | Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { EdtContent.Text = ""; }));
132 | var content = t.Item1.Substring(0, t.Item1.Length - 1);
133 | var last = t.Item1.Substring(content.Length);
134 | var all = content.Length + 1;
135 | var setted = 0;
136 | while (content.Length > CONTENT_CHUNK_SIZE)
137 | {
138 | Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action((x) => { EdtContent.AppendText(x); }), content.Substring(0, CONTENT_CHUNK_SIZE));
139 | content = content.Substring(CONTENT_CHUNK_SIZE);
140 | setted += CONTENT_CHUNK_SIZE;
141 | t.Item2.Percentage = (int) ((setted + 0.0) * 100 / (all + 0.0));
142 | if (t.Item2.AbortEvent.WaitOne(0))
143 | {
144 | Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { EdtContent.TextChanged += EdtContent_OnTextChanged; }));
145 | Thread.CurrentThread.Abort();
146 | return;
147 | }
148 | }
149 | if (content.Length > 0)
150 | Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action((x) => { EdtContent.AppendText(x); }), content);
151 | Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action((x) => { EdtContent.TextChanged += EdtContent_OnTextChanged; EdtContent.AppendText(x); }), last);
152 |
153 | var wait = new ManualResetEvent(false);
154 | Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action((x) => { x.Set(); }), wait);
155 | wait.WaitOne();
156 | t.Item2.AbortEvent.Set();
157 | Thread.CurrentThread.Abort();
158 | }
159 |
160 | public string GetContent()
161 | {
162 | return EdtContent.Text;
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/SDDLViewer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("SDDLViewer")]
11 | [assembly: AssemblyDescription("SDDL viewer")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("amonitoring.ru")]
14 | [assembly: AssemblyProduct("SDDLViewer")]
15 | [assembly: AssemblyCopyright("Copyright © 2019")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.1.0.0")]
55 | [assembly: AssemblyFileVersion("1.1.0.0")]
56 |
--------------------------------------------------------------------------------
/SDDLViewer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SDDLViewer.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SDDLViewer.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/SDDLViewer/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/SDDLViewer/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SDDLViewer.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SDDLViewer/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/SDDLViewer/SDDLViewer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6929B669-D82D-49B5-B4ED-7172BC900D18}
8 | WinExe
9 | SDDLViewer
10 | SDDLViewer
11 | v4.0
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | sddl_terminal.ico
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 4.0
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | MSBuild:Compile
57 | Designer
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | FolderRegPickerWindow.xaml
66 |
67 |
68 | UIPerformWorkWindow.xaml
69 |
70 |
71 |
72 | UIReportWindow.xaml
73 |
74 |
75 | MSBuild:Compile
76 | Designer
77 |
78 |
79 | App.xaml
80 | Code
81 |
82 |
83 |
84 | MainWindow.xaml
85 | Code
86 |
87 |
88 | MSBuild:Compile
89 | Designer
90 |
91 |
92 | Designer
93 | MSBuild:Compile
94 |
95 |
96 | Designer
97 | MSBuild:Compile
98 |
99 |
100 |
101 |
102 | Code
103 |
104 |
105 | True
106 | True
107 | Resources.resx
108 |
109 |
110 | True
111 | Settings.settings
112 | True
113 |
114 |
115 | ResXFileCodeGenerator
116 | Resources.Designer.cs
117 |
118 |
119 | SettingsSingleFileGenerator
120 | Settings.Designer.cs
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/SDDLViewer/UIFolderRegPicker/FolderRegPickerWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/SDDLViewer/UIFolderRegPicker/FolderRegPickerWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Security.AccessControl;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using Microsoft.Win32;
8 |
9 | namespace SDDLViewer.UIFolderRegPicker
10 | {
11 | ///
12 | /// Interaction logic for FolderRegPicker.xaml
13 | ///
14 | public partial class UIFolderRegPickerWindow
15 | {
16 | private readonly bool _isFolderPicker;
17 |
18 | public UIFolderRegPickerWindow(Window parent, bool isFolderPicker)
19 | {
20 | Owner = parent;
21 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
22 | IsRecursing = true;
23 | DataContext = this;
24 | InitializeComponent();
25 | _isFolderPicker = isFolderPicker;
26 | if (_isFolderPicker)
27 | {
28 | ChkIncludeFiles.Visibility = Visibility.Visible;
29 | var allDrives = DriveInfo.GetDrives();
30 | foreach (var d in allDrives)
31 | {
32 | var item = new TreeViewItem
33 | {
34 | Header = d.Name,
35 | Tag = d.Name,
36 | };
37 | try
38 | {
39 | if (Directory.GetDirectories(d.Name).Length != 0)
40 | item.Items.Add(new TreeViewItem {Header = ""});
41 | }
42 | catch
43 | {
44 | // ignored
45 | }
46 | item.Expanded += folder_OnExpanded;
47 | item.Selected += element_OnSelected;
48 | TreViewer.Items.Add(item);
49 | }
50 | }
51 | else
52 | {
53 | var allKeys = new List { "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CURRENT_CONFIG" };
54 | foreach (var k in allKeys)
55 | {
56 | var item = new TreeViewItem
57 | {
58 | Header = k,
59 | Tag = k,
60 | };
61 | item.Items.Add(new TreeViewItem { Header = "" });
62 | item.Expanded += keyreg_OnExpanded;
63 | item.Selected += element_OnSelected;
64 | TreViewer.Items.Add(item);
65 | }
66 | }
67 | }
68 |
69 | private void element_OnSelected(object sender, RoutedEventArgs e)
70 | {
71 | EdtPath.Text = ((TreeViewItem)sender).Tag.ToString().Trim();
72 | e.Handled = true;
73 | }
74 |
75 | private void folder_OnExpanded(object sender, RoutedEventArgs e)
76 | {
77 | var item = (TreeViewItem) sender;
78 | try
79 | {
80 | if (item.Items.Count == 1 && (item.Items[0] is TreeViewItem) && ( string.IsNullOrWhiteSpace((string)((TreeViewItem)item.Items[0]).Header)))
81 | {
82 | EdtPath.Text = item.Tag.ToString().Trim();
83 | item.Items.Clear();
84 | try
85 | {
86 | foreach (var s in Directory.GetDirectories(item.Tag.ToString()))
87 | {
88 | var subitem = new TreeViewItem
89 | {
90 | Header = s.Substring(s.LastIndexOf("\\") + 1),
91 | Tag = s
92 | };
93 | try
94 | {
95 | if (Directory.GetDirectories(s).Length != 0)
96 | subitem.Items.Add(new TreeViewItem {Header = ""});
97 | }
98 | catch { /* ignore */ }
99 | subitem.Expanded += folder_OnExpanded;
100 | subitem.Selected += element_OnSelected;
101 | item.Items.Add(subitem);
102 | }
103 | }
104 | catch { /* ignore */ }
105 | }
106 | }
107 | catch { /* ignore */ }
108 | }
109 |
110 | private void keyreg_OnExpanded(object sender, RoutedEventArgs e)
111 | {
112 | var item = (TreeViewItem)sender;
113 | try
114 | {
115 | if (item.Items.Count == 1 && (item.Items[0] is TreeViewItem) && (string.IsNullOrWhiteSpace((string)((TreeViewItem)item.Items[0]).Header)))
116 | {
117 | EdtPath.Text = item.Tag.ToString().Trim();
118 | item.Items.Clear();
119 | try
120 | {
121 | RegistryKey rk = GetKeyFromString(item.Tag.ToString());
122 | foreach (string s in rk.GetSubKeyNames())
123 | {
124 | TreeViewItem subitem = new TreeViewItem
125 | {
126 | Header = s,
127 | Tag = item.Tag + "\\" + s
128 | };
129 | try
130 | {
131 | var oSubKey = rk.OpenSubKey(s);
132 | if (oSubKey != null && oSubKey.SubKeyCount != 0)
133 | subitem.Items.Add(new TreeViewItem { Header = "" });
134 | }
135 | catch { /* ignore */ }
136 | subitem.Expanded += keyreg_OnExpanded;
137 | subitem.Selected += element_OnSelected;
138 | item.Items.Add(subitem);
139 | }
140 | }
141 | catch { /* ignore */ }
142 | }
143 | }
144 | catch { /* ignore */ }
145 | }
146 |
147 | public static RegistryKey GetKeyFromString(string path)
148 | {
149 | if (string.IsNullOrWhiteSpace(path))
150 | return null;
151 | path = path.Trim();
152 | if (path[path.Length - 1] == '\\')
153 | path = path.Substring(0, path.Length - 1);
154 | var index = path.IndexOf('\\');
155 | var start = (index == -1) ? path : path.Substring(0, index);
156 | RegistryKey rv;
157 | switch (start.ToUpperInvariant())
158 | {
159 | case "HKEY_CLASSES_ROOT":
160 | case "HKCR":
161 | rv = Registry.ClassesRoot;
162 | break;
163 |
164 | case "HKEY_CURRENT_USER":
165 | case "HKCU":
166 | rv = Registry.CurrentUser;
167 | break;
168 |
169 | case "HKEY_LOCAL_MACHINE":
170 | case "HKLM":
171 | rv = Registry.LocalMachine;
172 | break;
173 |
174 | case "HKEY_USERS":
175 | case "HKU":
176 | rv = Registry.Users;
177 | break;
178 |
179 | case "HKEY_CURRENT_CONFIG":
180 | rv = Registry.CurrentConfig;
181 | break;
182 |
183 | default:
184 | return null;
185 | }
186 | if (index == -1)
187 | {
188 | return rv;
189 | }
190 | try
191 | {
192 | path = path.Substring(index + 1);
193 | return rv.OpenSubKey(path);
194 | }
195 | catch
196 | {
197 | return null;
198 | }
199 | }
200 |
201 | public string PathName { get; set; }
202 | public bool IsRecursing { get; set; }
203 | public bool IsFilesInclude { get; set; }
204 |
205 | private void ButtonOk_OnClick(object sender, RoutedEventArgs e)
206 | {
207 | var p = EdtPath.Text.Trim();
208 | if (_isFolderPicker)
209 | {
210 | if (Directory.Exists(p))
211 | {
212 | PathName = p;
213 | DialogResult = true;
214 | Close();
215 | }
216 | else
217 | {
218 | MessageBox.Show("Unable to open directory (not found or access denied).", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
219 | }
220 | }
221 | else
222 | {
223 | if (GetKeyFromString(p) != null)
224 | {
225 | PathName = p;
226 | DialogResult = true;
227 | Close();
228 | }
229 | else
230 | {
231 | MessageBox.Show("Unable to open registry key (not found or access denied).", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
232 | }
233 | }
234 | }
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/SDDLViewer/UIPerformWork/UIPerformWorkWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/SDDLViewer/UIPerformWork/UIPerformWorkWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Threading;
4 | using System.Windows;
5 | using System.Windows.Media;
6 | using System.Windows.Shapes;
7 | using System.Windows.Threading;
8 |
9 | namespace SDDLViewer.UIPerformWork
10 | {
11 | ///
12 | /// Interaction logic for UIPerformWorkWindow.xaml
13 | ///
14 | public partial class UIPerformWorkWindow
15 | {
16 | private readonly Line[] _lines = new Line[8];
17 | private int _lIndex;
18 |
19 | private readonly Brush _brush1 = new SolidColorBrush(Color.FromRgb(0, 0, 0));
20 | private readonly Brush _brush2 = new SolidColorBrush(Color.FromRgb(80, 80, 80));
21 | private readonly Brush _brush3 = new SolidColorBrush(Color.FromRgb(160, 160, 160));
22 |
23 | public readonly ManualResetEvent AbortEvent;
24 |
25 | public UIPerformWorkWindow(Window parent, ManualResetEvent ev, string textPlaceholder, string percentFormat = "Complete: {0,3}%")
26 | {
27 | Owner = parent;
28 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
29 | _percentFormat = percentFormat;
30 | AbortEvent = ev;
31 | Percentage = 0;
32 | InitializeComponent();
33 | _lines[0] = L1;
34 | _lines[1] = L2;
35 | _lines[2] = L3;
36 | _lines[3] = L4;
37 | _lines[4] = L5;
38 | _lines[5] = L6;
39 | _lines[6] = L7;
40 | _lines[7] = L8;
41 | lblPercentage.Text = textPlaceholder;
42 | foreach (var line in _lines)
43 | line.Stroke = _brush3;
44 | var timer = new DispatcherTimer();
45 | timer.Tick += timer_Tick;
46 | timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
47 | timer.Start();
48 | }
49 |
50 | private int _percentage;
51 | public int Percentage { private get; set; }
52 |
53 | private readonly string _percentFormat;
54 |
55 | private void timer_Tick(object sender, EventArgs e)
56 | {
57 | _lIndex = (_lIndex + 1) % 8;
58 | _lines[_lIndex].Stroke = _brush1;
59 | _lines[(_lIndex + 7) % 8].Stroke = _brush2;
60 | _lines[(_lIndex + 6) % 8].Stroke = _brush3;
61 | if (_percentage != Percentage)
62 | {
63 | lblPercentage.Text = string.Format(_percentFormat, Percentage);
64 | _percentage = Percentage;
65 | }
66 | if (AbortEvent.WaitOne(0))
67 | Close();
68 | }
69 |
70 | private void Abort_OnClick(object sender, RoutedEventArgs e)
71 | {
72 | Close();
73 | }
74 |
75 | private void Window_OnClose(object sender, CancelEventArgs e)
76 | {
77 | DialogResult = true;
78 | AbortEvent.Set();
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/SDDLViewer/UIReport/ReportModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Controls;
7 | using Microsoft.Win32;
8 |
9 | namespace SDDLViewer.UIReport
10 | {
11 | static class ReportModel
12 | {
13 | public static void ButtonSave(string content)
14 | {
15 | var dlg = new SaveFileDialog
16 | {
17 | FileName = "report",
18 | DefaultExt = ".txt",
19 | Filter = "Text documents (*.txt)|*.txt|All files (*.*)|*.*",
20 | FilterIndex = 0,
21 | OverwritePrompt = true
22 | };
23 | if (dlg.ShowDialog() ?? false)
24 | File.WriteAllText(dlg.FileName, content);
25 | }
26 |
27 | public static string MakeReport(string sddl, List SIDs, List rights, bool isIncludeAllow, bool isIncludeDeny, bool translateSID)
28 | {
29 | var lines = sddl.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
30 | var prev = "";
31 | var sb = new StringBuilder();
32 | foreach (var line in lines)
33 | {
34 | if (!string.IsNullOrWhiteSpace(line))
35 | {
36 | var sd = new SecurityDescriptor(line.Trim());
37 | if (sd.IsOk)
38 | {
39 | var r = GetLineForReport(sd, SIDs, rights, isIncludeAllow, isIncludeDeny, translateSID);
40 | if (!string.IsNullOrWhiteSpace(r))
41 | {
42 | if (!string.IsNullOrWhiteSpace(prev))
43 | sb.AppendLine(prev);
44 | sb.AppendLine(r);
45 | sb.AppendLine();
46 | }
47 | prev = "";
48 | continue;
49 | }
50 | prev = line;
51 | }
52 | }
53 |
54 | return sb.ToString();
55 | }
56 |
57 | private static string GetLineForReport(SecurityDescriptor sd, List SIDs, List rights, bool isIncludeAllow, bool isIncludeDeny, bool translateSID)
58 | {
59 | var rv = "";
60 | var owner = sd.GetOwner();
61 | if (SIDs.Contains(owner))
62 | rv += "O:" + owner;
63 | var group = sd.GetGroup();
64 | if (SIDs.Contains(group))
65 | rv += "G:" + group;
66 | var sb = new StringBuilder();
67 | foreach (var ace in sd.GetACEs())
68 | {
69 | if (!SIDs.Contains(ace.GetSID()))
70 | continue;
71 | var type = ace.GetRuleType();
72 | if (!isIncludeAllow && (type == ACE.AllowRule))
73 | continue;
74 | if (!isIncludeDeny && (type == ACE.DenyRule))
75 | continue;
76 | var aceRights = ace.GetAllRights();
77 | var matchRights = aceRights.Where(rights.Contains).ToList();
78 | if (matchRights.Count != 0)
79 | sb.Append(ace.WithNewRights(matchRights));
80 | }
81 | var aces = sb.ToString();
82 | if (!string.IsNullOrWhiteSpace(aces))
83 | rv += "D:" + aces;
84 | return rv;
85 | }
86 |
87 | public static string GetHelperText(string line, int rightsType, out Tuple details, bool translateSID)
88 | {
89 | var sd = new SecurityDescriptor(line);
90 | if (sd.IsOk)
91 | {
92 | var lSIDs = sd.GetAllSIDs();
93 | var lRights = sd.GetAllRights();
94 | var sb = new StringBuilder();
95 | if (lSIDs.Count != 0)
96 | {
97 | sb.AppendLine();
98 | sb.AppendLine("SIDs:");
99 | sb.AppendLine("-----");
100 | foreach (var lSID in lSIDs)
101 | sb.AppendLine(SecurityDescriptor.SIDToLong(lSID, translateSID));
102 | sb.AppendLine("-----");
103 | }
104 | if (lRights.Count != 0)
105 | {
106 | sb.AppendLine();
107 | sb.AppendLine("Rights (" + ACE.RightType(rightsType)+"):");
108 | sb.AppendLine("-----");
109 | foreach (var lRight in lRights)
110 | sb.AppendLine(ACE.RigthToLong(lRight, rightsType));
111 | sb.AppendLine("-----");
112 | }
113 | var aces = sd.GetACEs();
114 | var treeElements = new TreeViewItem[aces.Count];
115 | for (var i = 0; i < aces.Count; i++)
116 | treeElements[i] = ACEToTreeViewItem(aces[i], rightsType, translateSID);
117 | details = new Tuple(sd.GetOwner(), sd.GetGroup(), treeElements);
118 | return sb.ToString();
119 | }
120 | details = new Tuple("", "", new TreeViewItem[0]);
121 | return string.Empty;
122 | }
123 |
124 | private static TreeViewItem ACEToTreeViewItem(ACE ace, int rightsType, bool translateSID)
125 | {
126 | var rv = new TreeViewItem {Header = SecurityDescriptor.SIDToLong(ace.GetSID(), translateSID) };
127 | rv.Items.Clear();
128 | foreach (var right in ace.GetAllRights())
129 | rv.Items.Add(ACE.RigthToLong(right, rightsType));
130 | return rv;
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/SDDLViewer/UIReport/UIReportWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SDDLViewer/UIReport/UIReportWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 |
6 | namespace SDDLViewer.UIReport
7 | {
8 | public partial class UIReportWindow
9 | {
10 | private readonly int _rightsType;
11 | private readonly bool _translateSID;
12 |
13 | private readonly string[] _lines;
14 |
15 | public UIReportWindow(MainWindow parent, string sddl, List SIDs, List rights, int rightsType)
16 | {
17 | Owner = parent;
18 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
19 | _rightsType = rightsType;
20 | InitializeComponent();
21 | _translateSID = parent.IsTranslateSID;
22 | EdtContent.Text = ReportModel.MakeReport(sddl, SIDs, rights, parent.IsIncludeAllow, parent.IsIncludeDeny, parent.IsTranslateSID);
23 | _lines = EdtContent.Text.Split(new [] {Environment.NewLine}, StringSplitOptions.None);
24 | }
25 |
26 | private void Save_OnClick(object sender, RoutedEventArgs e)
27 | {
28 | ReportModel.ButtonSave(EdtContent.Text);
29 | }
30 |
31 | private void EdtContent_OnSelectionChanged(object sender, RoutedEventArgs e)
32 | {
33 | try
34 | {
35 | var lNumber = EdtContent.GetLineIndexFromCharacterIndex(EdtContent.CaretIndex);
36 | var line = _lines[lNumber];
37 | var obj = line;
38 | Tuple detail;
39 | var r = ReportModel.GetHelperText(line, _rightsType, out detail, _translateSID);
40 | if (string.IsNullOrWhiteSpace(r))
41 | {
42 | line = _lines[lNumber + 1];
43 | r = ReportModel.GetHelperText(line, _rightsType, out detail, _translateSID);
44 | }
45 | else
46 | {
47 | obj = (lNumber == 0) ? string.Empty : _lines[lNumber - 1];
48 | }
49 | EdtHelper.Text = r;
50 | lblObject.Text = "Object:\n " + obj;
51 | lblObject.Visibility = string.IsNullOrWhiteSpace(obj) ? Visibility.Collapsed : Visibility.Visible;
52 | lblOwner.Text = "Owner:\n " + SecurityDescriptor.SIDToLong(detail.Item1, _translateSID);
53 | lblOwner.Visibility = string.IsNullOrWhiteSpace(detail.Item1) ? Visibility.Collapsed : Visibility.Visible;
54 | lblGroup.Text = "Group:\n " + SecurityDescriptor.SIDToLong(detail.Item2, _translateSID);
55 | lblGroup.Visibility = string.IsNullOrWhiteSpace(detail.Item2) ? Visibility.Collapsed : Visibility.Visible;
56 | treeACE.Items.Clear();
57 | foreach (var treeViewItem in detail.Item3)
58 | treeACE.Items.Add(treeViewItem);
59 | treeACE.Visibility = (detail.Item3.Length == 0) ? Visibility.Collapsed : Visibility.Visible;
60 | }
61 | catch
62 | {
63 | EdtHelper.Text = string.Empty;
64 | lblOwner.Visibility = Visibility.Collapsed;
65 | lblGroup.Visibility = Visibility.Collapsed;
66 | treeACE.Visibility = Visibility.Collapsed;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/SDDLViewer/sddl_terminal.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/advancedmonitoring/SDDLViewer/ba00a2b158f229ffd7cfeb27c66b7729936481e1/SDDLViewer/sddl_terminal.ico
--------------------------------------------------------------------------------
/Screenshots/MainWindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/advancedmonitoring/SDDLViewer/ba00a2b158f229ffd7cfeb27c66b7729936481e1/Screenshots/MainWindow.png
--------------------------------------------------------------------------------