So in the last day, A buddy of mine pointed out an issue with LanDesk ISSUR. I got to a stopping point but basically when you try to Kill the process while it is in a hung state it. So my thoughts were the ACL in memory for the process was adjusted to prevent administrators from killing the process. After running this code I found the process does not even have a handle to begin pulling its ACL. Interesting trick, Something that warrants further research.
Update: I am unable to get access to the process handle due to the ACL’s I must escalate to system first before this API will work.
Src: http://csharptest.net/1043/how-to-prevent-users-from-killing-your-service-process/index.html Also an interesting read.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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 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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; using System.ServiceProcess; using System.Text; using System.Windows.Forms; namespace ProcessPermissions { public partial class Form1 : Form { [StructLayoutAttribute(LayoutKind.Sequential)] struct SECURITY_DESCRIPTOR { public byte revision; public byte size; public short control; public IntPtr owner; public IntPtr group; public IntPtr sacl; public IntPtr dacl; } [DllImport("advapi32.dll", SetLastError = true)] static extern bool QueryServiceObjectSecurity(IntPtr serviceHandle, System.Security.AccessControl.SecurityInfos secInfo, ref SECURITY_DESCRIPTOR lpSecDesrBuf, uint bufSize, out uint bufSizeNeeded); [DllImport("advapi32.dll", SetLastError = true)] static extern bool QueryServiceObjectSecurity(SafeHandle serviceHandle, System.Security.AccessControl.SecurityInfos secInfo, byte[] lpSecDesrBuf, uint bufSize, out uint bufSizeNeeded); [DllImport("advapi32.dll", SetLastError = true)] static extern bool SetServiceObjectSecurity(SafeHandle serviceHandle, System.Security.AccessControl.SecurityInfos secInfos, byte[] lpSecDesrBuf); public void SetServicePermissions(string service, string username) { System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(service, "."); ServiceControllerStatus status = sc.Status; byte[] psd = new byte[0]; uint bufSizeNeeded; bool ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, 0, out bufSizeNeeded); if (!ok) { int err = Marshal.GetLastWin32Error(); if (err == 122 || err == 0) { // ERROR_INSUFFICIENT_BUFFER // expected; now we know bufsize psd = new byte[bufSizeNeeded]; ok = QueryServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, psd, bufSizeNeeded, out bufSizeNeeded); } else { throw new ApplicationException("error calling QueryServiceObjectSecurity() to get DACL for : error code=" + err); } } if (!ok) throw new ApplicationException("error calling QueryServiceObjectSecurity(2) to get DACL for : error code=" + Marshal.GetLastWin32Error()); // get security descriptor via raw into DACL form so ACE // ordering checks are done for us. RawSecurityDescriptor rsd = new RawSecurityDescriptor(psd, 0); RawAcl racl = rsd.DiscretionaryAcl; DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, racl); // Add start/stop/read access NTAccount acct = new NTAccount(username); SecurityIdentifier sid = (SecurityIdentifier)acct.Translate(typeof(SecurityIdentifier)); // 0xf7 is SERVICE_QUERY_CONFIG|SERVICE_CHANGE_CONFIG|SERVICE_QUERY_STATUS| // SERVICE_START|SERVICE_STOP|SERVICE_PAUSE_CONTINUE|SERVICE_INTERROGATE dacl.AddAccess(AccessControlType.Allow, sid, 0xf7, InheritanceFlags.None, PropagationFlags.None); // convert discretionary ACL back to raw form; looks like via byte[] is only way byte[] rawdacl = new byte[dacl.BinaryLength]; dacl.GetBinaryForm(rawdacl, 0); rsd.DiscretionaryAcl = new RawAcl(rawdacl, 0); // set raw security descriptor on service again byte[] rawsd = new byte[rsd.BinaryLength]; rsd.GetBinaryForm(rawsd, 0); ok = SetServiceObjectSecurity(sc.ServiceHandle, SecurityInfos.DiscretionaryAcl, rawsd); if (!ok) { throw new ApplicationException("error calling SetServiceObjectSecurity(); error code=" + Marshal.GetLastWin32Error()); } } [DllImport("advapi32.dll", SetLastError = true)] static extern bool GetKernelObjectSecurity(IntPtr Handle, int securityInformation, [Out] byte[] pSecurityDescriptor, uint nLength, out uint lpnLengthNeeded); public static RawSecurityDescriptor GetProcessSecurityDescriptor(IntPtr processHandle) { const int DACL_SECURITY_INFORMATION = 0x00000004; byte[] psd = new byte[0]; uint bufSizeNeeded; // Call with 0 size to obtain the actual size needed in bufSizeNeeded GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, psd, 0, out bufSizeNeeded); if (bufSizeNeeded < 0 || bufSizeNeeded > short.MaxValue) throw new Win32Exception(); // Allocate the required bytes and obtain the DACL if (!GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, psd = new byte[bufSizeNeeded], bufSizeNeeded, out bufSizeNeeded)) throw new Win32Exception(); // Use the RawSecurityDescriptor class from System.Security.AccessControl to parse the bytes: return new RawSecurityDescriptor(psd, 0); } string GetNameFromSID(SecurityIdentifier sid) { try { NTAccount ntAccount = (NTAccount)sid.Translate(typeof(NTAccount)); return ntAccount.ToString(); } catch { return null; } } public Form1() { InitializeComponent(); } [DllImport("kernel32.dll")] public static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress, byte lpBuffer, int nSize, int lpNumberOfBytesWritten); [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); int PROCESS_ALL_ACCESS = (0x1F0FFF); private void Form1_Load(object sender, EventArgs e) { //IntPtr hProcess = IntPtr.Zero; IntPtr hProcessToken = IntPtr.Zero; IntPtr securityDescriptorPtr = IntPtr.Zero; //Process[] hProcess = Process.GetProcessesByName("issuser"); Process[] hProcess = Process.GetProcessesByName("notepad"); IntPtr xAsIntPtr = new IntPtr(hProcess[0].Id); RawSecurityDescriptor Desc = GetProcessSecurityDescriptor(xAsIntPtr); System.Diagnostics.Debug.WriteLine(Desc.Owner); foreach (CommonAce item in Desc.DiscretionaryAcl) { System.Diagnostics.Debug.WriteLine(item.SecurityIdentifier.Value + " - " + item.SecurityIdentifier.AccountDomainSid); System.Diagnostics.Debug.WriteLine(GetNameFromSID(item.SecurityIdentifier)); System.Diagnostics.Debug.WriteLine(item.AceFlags); System.Diagnostics.Debug.WriteLine(item.AceType); System.Diagnostics.Debug.WriteLine(item.AuditFlags); System.Diagnostics.Debug.WriteLine(item.BinaryLength); System.Diagnostics.Debug.WriteLine(item.InheritanceFlags); System.Diagnostics.Debug.WriteLine(item.IsInherited); System.Diagnostics.Debug.WriteLine(item.PropagationFlags); System.Diagnostics.Debug.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="); } Application.Exit(); } } } |