看到一篇文章講述了經過設置 DACL 隱藏 Windows 服務信息,便作一下總結。html
系統中每一個 Service 在 Windows 中屬於都一種對象(Object),用戶在訪問對象時的權限會被和對象綁定的安全描述信息(Security Descriptors)所限定,例如 修改、刪除、讀寫等權限。c++
既然 Service 也是一種對象,那麼也能夠經過某種方式對服務的安全描述信息進行適當的修改,使某一類用戶沒法查看、修改該服務的信息以及中止刪除服務。shell
經 MSDN 描述可知,一個安全描述信息結構體包括以下信息:windows
對應的結構體定義 SECURITY_DESCRIPTOR :api
typedef struct _SECURITY_DESCRIPTOR { BYTE Revision; BYTE Sbz1; SECURITY_DESCRIPTOR_CONTROL Control; PSID Owner; PSID Group; PACL Sacl; PACL Dacl; } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
可是程序或用戶並不能直接控制這些信息,必須經過 Windows 提供的 API 進行設置或查詢。安全
這就致使因爲對象種類的不一樣,設置這些安全描述信息的方式上可能各有不一樣:app
對於這些安全描述信息,Windows 單獨提供了一種簡單的字符串表述形式,官方稱其爲 「安全描述符定義語言」(SDDL),下面着重總結一下 SDDL 的東西。dom
參考 MSDN 可知,SDDL 和 SECURITY_DESCRIPTOR 結構體之間的轉換是經過兩個 API 進行互轉的:ide
因此,這爲安全描述符的設置提供了很大的便利,下面先了解一些基本概念。工具
ACE 構成了 DACL 和 SACL,能夠理解爲 SD(安全描述符)的最小存儲單元,他的格式以下:
ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute)
爲空表明不限制,常見的策略組合多是這樣的:
ace_type;;rights;;;account_sid;
ace_type 有不少,參見 MSDN,該字段能夠表示對這條規則應用的策略類型,例如:
"A" SDDL_ACCESS_ALLOWED ACCESS_ALLOWED_ACE_TYPE "D" SDDL_ACCESS_DENIED ACCESS_DENIED_ACE_TYPE
根據 MSDN 可看出,針對不一樣類型的對象,權限常量的名字不是很統一,Wayne Martin 在他的文章中給出了一部分 ADS、SCM、Service、value、SDDL 的映射關係:
"CC" ADS_RIGHT_DS_CREATE_CHILD = 0x1, SC_MANAGER_CONNECT, SERVICE_QUERY_CONFIG "DC" ADS_RIGHT_DS_DELETE_CHILD = 0x2, SC_MANAGER_CREATE_SERVICE, SERVICE_CHANGE_CONFIG "LC" ADS_RIGHT_ACTRL_DS_LIST = 0x4, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_STATUS "SW" ADS_RIGHT_DS_SELF = 0x8, SC_MANAGER_LOCK, SERVICE_ENUMERATE_DEPENDENTS "RP" ADS_RIGHT_DS_READ_PROP = 0x10, SC_MANAGER_QUERY_LOCK_STATUS, SERVICE_START, "WP" ADS_RIGHT_DS_WRITE_PROP = 0x20, SC_MANAGER_MODIFY_BOOT_CONFIG, SERVICE_STOP "DT" ADS_RIGHT_DS_DELETE_TREE = 0x40, SERVICE_PAUSE_CONTINUE "LO" ADS_RIGHT_DS_LIST_OBJECT = 0x80, SERVICE_INTERROGATE "CR" ADS_RIGHT_DS_CONTROL_ACCESS = 0x100 SERVICE_USER_DEFINED_CONTROL "RC" READ_CONTROL = 0x20000 READ_CONTROL "SD" ADS_RIGHT_DELETE = 0x10000 DELETE
SCM 和 Servcie 的權限描述符,來自 Service Security and Access Rights - MSDN :
SERVICE_QUERY_CONFIG (0x0001) Required to call the QueryServiceConfig and QueryServiceConfig2 functions to query the service configuration. SERVICE_CHANGE_CONFIG (0x0002) Required to call the ChangeServiceConfig or ChangeServiceConfig2 function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators. SERVICE_QUERY_STATUS (0x0004) Required to call the QueryServiceStatusEx function to ask the service control manager about the status of the service. SERVICE_ENUMERATE_DEPENDENTS (0x0008) Required to call the EnumDependentServices function to enumerate all the services dependent on the service. SERVICE_START (0x0010) Required to call the StartService function to start the service. SERVICE_STOP (0x0020) Required to call the ControlService function to stop the service. SERVICE_PAUSE_CONTINUE (0x0040) Required to call the ControlService function to pause or continue the service. SERVICE_INTERROGATE (0x0080) Required to call the ControlService function to ask the service to report its status immediately. SERVICE_USER_DEFINED_CONTROL(0x0100) Required to call the ControlService function to specify a user-defined control code. SERVICE_ALL_ACCESS (0xF01FF) Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table. READ_CONTROL Required to call the QueryServiceObjectSecurity function to query the security descriptor of the service object. SC_MANAGER_CONNECT (0x0001) Required to connect to the service control manager. SC_MANAGER_CREATE_SERVICE (0x0002) Required to call the CreateService function to create a service object and add it to the database. SC_MANAGER_ENUMERATE_SERVICE (0x0004) Required to call the EnumServicesStatusEx function to list the services that are in the database. SC_MANAGER_LOCK (0x0008) Required to call the LockServiceDatabase function to acquire a lock on the database. SC_MANAGER_QUERY_LOCK_STATUS (0x0010) SC_MANAGER_MODIFY_BOOT_CONFIG (0x0020) Required to call the NotifyBootConfigStatus function. SC_MANAGER_ALL_ACCESS (0xF003F) Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table.
SDDL 和 ADS 關係映射,來自 ACE Strings - MSDN :
"RC" SDDL_READ_CONTROL READ_CONTROL "RP" SDDL_READ_PROPERTY ADS_RIGHT_DS_READ_PROP "WP" SDDL_WRITE_PROPERTY ADS_RIGHT_DS_WRITE_PROP "CC" SDDL_CREATE_CHILD ADS_RIGHT_DS_CREATE_CHILD "DC" SDDL_DELETE_CHILD ADS_RIGHT_DS_DELETE_CHILD "LC" SDDL_LIST_CHILDREN ADS_RIGHT_ACTRL_DS_LIST "SW" SDDL_SELF_WRITE ADS_RIGHT_DS_SELF "LO" SDDL_LIST_OBJECT ADS_RIGHT_DS_LIST_OBJECT "DT" SDDL_DELETE_TREE ADS_RIGHT_DS_DELETE_TREE "CR" SDDL_CONTROL_ACCESS ADS_RIGHT_DS_CONTROL_ACCESS
ADS 的枚舉項值,來自 ads_rights_enum - systemmanager:
typedef enum { ADS_RIGHT_DELETE = 0x10000, ADS_RIGHT_READ_CONTROL = 0x20000, ADS_RIGHT_WRITE_DAC = 0x40000, ADS_RIGHT_WRITE_OWNER = 0x80000, ADS_RIGHT_SYNCHRONIZE = 0x100000, ADS_RIGHT_ACCESS_SYSTEM_SECURITY = 0x1000000, ADS_RIGHT_GENERIC_READ = 0x80000000, ADS_RIGHT_GENERIC_WRITE = 0x40000000, ADS_RIGHT_GENERIC_EXECUTE = 0x20000000, ADS_RIGHT_GENERIC_ALL = 0x10000000, ADS_RIGHT_DS_CREATE_CHILD = 0x1, ADS_RIGHT_DS_DELETE_CHILD = 0x2, ADS_RIGHT_ACTRL_DS_LIST = 0x4, ADS_RIGHT_DS_SELF = 0x8, ADS_RIGHT_DS_READ_PROP = 0x10, ADS_RIGHT_DS_WRITE_PROP = 0x20, ADS_RIGHT_DS_DELETE_TREE = 0x40, ADS_RIGHT_DS_LIST_OBJECT = 0x80, ADS_RIGHT_DS_CONTROL_ACCESS = 0x100 } ADS_RIGHTS_ENUM;
SID 用於標識 擁有者 或 所屬組,在 ACE 中的 account_sid 能夠是一個 SID(S-R-I-S-S)或者在 Sddl.h 中定義的字符串常量,這些字符串常量又稱 「周知 SID」:
"AN" SDDL_ANONYMOUS Anonymous logon. The corresponding RID is SECURITY_ANONYMOUS_LOGON_RID. "AO" SDDL_ACCOUNT_OPERATORS Account operators. The corresponding RID is DOMAIN_ALIAS_RID_ACCOUNT_OPS. "AU" SDDL_AUTHENTICATED_USERS Authenticated users. The corresponding RID is SECURITY_AUTHENTICATED_USER_RID. "BA" SDDL_BUILTIN_ADMINISTRATORS Built-in administrators. The corresponding RID is DOMAIN_ALIAS_RID_ADMINS. "BG" SDDL_BUILTIN_GUESTS Built-in guests. The corresponding RID is DOMAIN_ALIAS_RID_GUESTS. "BO" SDDL_BACKUP_OPERATORS Backup operators. The corresponding RID is DOMAIN_ALIAS_RID_BACKUP_OPS. "BU" SDDL_BUILTIN_USERS Built-in users. The corresponding RID is DOMAIN_ALIAS_RID_USERS. "CA" SDDL_CERT_SERV_ADMINISTRATORS Certificate publishers. The corresponding RID is DOMAIN_GROUP_RID_CERT_ADMINS. "CD" SDDL_CERTSVC_DCOM_ACCESS Users who can connect to certification authorities using Distributed Component Object Model (DCOM). The corresponding RID is DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP. "CG" SDDL_CREATOR_GROUP Creator group. The corresponding RID is SECURITY_CREATOR_GROUP_RID. "CO" SDDL_CREATOR_OWNER Creator owner. The corresponding RID is SECURITY_CREATOR_OWNER_RID. "DA" SDDL_DOMAIN_ADMINISTRATORS Domain administrators. The corresponding RID is DOMAIN_GROUP_RID_ADMINS. "DC" SDDL_DOMAIN_COMPUTERS Domain computers. The corresponding RID is DOMAIN_GROUP_RID_COMPUTERS. "DD" SDDL_DOMAIN_DOMAIN_CONTROLLERS Domain controllers. The corresponding RID is DOMAIN_GROUP_RID_CONTROLLERS. "DG" SDDL_DOMAIN_GUESTS Domain guests. The corresponding RID is DOMAIN_GROUP_RID_GUESTS. "DU" SDDL_DOMAIN_USERS Domain users. The corresponding RID is DOMAIN_GROUP_RID_USERS. "EA" SDDL_ENTERPRISE_ADMINS Enterprise administrators. The corresponding RID is DOMAIN_GROUP_RID_ENTERPRISE_ADMINS. "ED" SDDL_ENTERPRISE_DOMAIN_CONTROLLERS Enterprise domain controllers. The corresponding RID is SECURITY_SERVER_LOGON_RID. "HI" SDDL_ML_HIGH High integrity level. The corresponding RID is SECURITY_MANDATORY_HIGH_RID. "IU" SDDL_INTERACTIVE Interactively logged-on user. This is a group identifier added to the token of a process when it was logged on interactively. The corresponding logon type is LOGON32_LOGON_INTERACTIVE. The corresponding RID is SECURITY_INTERACTIVE_RID. "LA" SDDL_LOCAL_ADMIN Local administrator. The corresponding RID is DOMAIN_USER_RID_ADMIN. "LG" SDDL_LOCAL_GUEST Local guest. The corresponding RID is DOMAIN_USER_RID_GUEST. "LS" SDDL_LOCAL_SERVICE Local service account. The corresponding RID is SECURITY_LOCAL_SERVICE_RID. "LW" SDDL_ML_LOW Low integrity level. The corresponding RID is SECURITY_MANDATORY_LOW_RID. "ME" SDDL_MLMEDIUM Medium integrity level. The corresponding RID is SECURITY_MANDATORY_MEDIUM_RID. "MU" SDDL_PERFMON_USERS Performance Monitor users. "NO" SDDL_NETWORK_CONFIGURATION_OPS Network configuration operators. The corresponding RID is DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS. "NS" SDDL_NETWORK_SERVICE Network service account. The corresponding RID is SECURITY_NETWORK_SERVICE_RID. "NU" SDDL_NETWORK Network logon user. This is a group identifier added to the token of a process when it was logged on across a network. The corresponding logon type is LOGON32_LOGON_NETWORK. The corresponding RID is SECURITY_NETWORK_RID. "PA" SDDL_GROUP_POLICY_ADMINS Group Policy administrators. The corresponding RID is DOMAIN_GROUP_RID_POLICY_ADMINS. "PO" SDDL_PRINTER_OPERATORS Printer operators. The corresponding RID is DOMAIN_ALIAS_RID_PRINT_OPS. "PS" SDDL_PERSONAL_SELF Principal self. The corresponding RID is SECURITY_PRINCIPAL_SELF_RID. "PU" SDDL_POWER_USERS Power users. The corresponding RID is DOMAIN_ALIAS_RID_POWER_USERS. "RC" SDDL_RESTRICTED_CODE Restricted code. This is a restricted token created using the CreateRestrictedToken function. The corresponding RID is SECURITY_RESTRICTED_CODE_RID. "RD" SDDL_REMOTE_DESKTOP Terminal server users. The corresponding RID is DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS. "RE" SDDL_REPLICATOR Replicator. The corresponding RID is DOMAIN_ALIAS_RID_REPLICATOR. "RO" SDDL_ENTERPRISE_RO_DCs Enterprise Read-only domain controllers. The corresponding RID is DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS. "RS" SDDL_RAS_SERVERS RAS servers group. The corresponding RID is DOMAIN_ALIAS_RID_RAS_SERVERS. "RU" SDDL_ALIAS_PREW2KCOMPACC Alias to grant permissions to accounts that use applications compatible with operating systems previous to Windows 2000. The corresponding RID is DOMAIN_ALIAS_RID_PREW2KCOMPACCESS. "SA" SDDL_SCHEMA_ADMINISTRATORS Schema administrators. The corresponding RID is DOMAIN_GROUP_RID_SCHEMA_ADMINS. "SI" SDDL_ML_SYSTEM System integrity level. The corresponding RID is SECURITY_MANDATORY_SYSTEM_RID. "SO" SDDL_SERVER_OPERATORS Server operators. The corresponding RID is DOMAIN_ALIAS_RID_SYSTEM_OPS. "SU" SDDL_SERVICE Service logon user. This is a group identifier added to the token of a process when it was logged as a service. The corresponding logon type is LOGON32_LOGON_SERVICE. The corresponding RID is SECURITY_SERVICE_RID. "SY" SDDL_LOCAL_SYSTEM Local system. The corresponding RID is SECURITY_LOCAL_SYSTEM_RID. "WD" SDDL_EVERYONE Everyone. The corresponding RID is SECURITY_WORLD_RID.
暫略。
對於正常添加的普通服務,使用 powershell 或 sc.exe 能夠直接查看該服務的信息:
PS C:\WINDOWS\system32> Get-Service -Name SWCUEngine Status Name DisplayName ------ ---- ----------- Running SWCUEngine SWCUEngine
經過修改服務的 SD 以後,查詢該服務信息將報錯 」ObjectNotFound「,以此達到隱藏的目的:
PS C:\WINDOWS\system32> & $env:SystemRoot\System32\sc.exe sdset SWCUEngine "D:(D;;DCLCWPDTSD;;;IU)(D;;DCLCWPDTSD;;;SU)(D;;DCLCWPDTSD;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" [SC] SetServiceObjectSecurity SUCCESS PS C:\WINDOWS\system32> Get-Service -Name SWCUEngine Get-Service : Cannot find any service with service name 'SWCUEngine'. At line:1 char:1 + Get-Service -Name SWCUEngine + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (SWCUEngine:String) [Get-Service], ServiceCommandException + FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
看一下其中設置的 ACE,「D:」表示 DACL 表,多個 ACE 之間以分號小括號分割
「D;;DCLCWPDTSD;;;IU」:拒絕交互式用戶如下權限:
「S:」表示 SACL 表,「AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD」表示任何人對該服務的失敗操做都進行審計記錄。
隱藏後,不管是 services.exe、Get-Service、sc query 或任何其它關於服務的控制工具均沒法檢索出對應信息,效果以下:
#如下三種查詢服務信息的手段均無信息 PS C:\WINDOWS\system32> Get-Service | Select-Object Name | Select-String -Pattern 'SWCUEngine' PS C:\WINDOWS\system32> Get-WmiObject Win32_Service | Select-String -Pattern 'SWCUEngine' PS C:\WINDOWS\system32> & $env:SystemRoot\System32\sc.exe query | Select-String -Pattern 'SWCUEngine' PS C:\WINDOWS\system32
若是藍隊知道惡意服務的名稱的話,能夠經過中止該服務的回顯進行判斷,例如:
# 中止不存在的JoshNoSuchService服務獲得 InvalidOperationException 異常 PS C:\WINDOWS\system32> Set-Service -Name JoshNoSuchService -Status Stopped Set-Service : Service JoshNoSuchService was not found on computer '.'. At line:1 char:1 + Set-Service -Name JoshNoSuchService -Status Stopped + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (.:String) [Set-Service], InvalidOperationException + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.SetServiceCommand # 中止存在但被隱藏的SWCUEngine服務獲得ServiceCommandException異常 PS C:\WINDOWS\system32> Set-Service -Name SWCUEngine -Status Stopped Set-Service : Service 'SWCUEngine (SWCUEngine)' cannot be configured due to the following error: Access is denied At line:1 char:1 + Set-Service -Name SWCUEngine -Status Stopped + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (System.ServiceProcess.ServiceController:ServiceController) [Set-Service], ServiceCommandException + FullyQualifiedErrorId : CouldNotSetService,Microsoft.PowerShell.Commands.SetServiceCommand
判斷存在後,取消隱藏的方式也很簡單:
# 使用sc.exe修改目標服務的SDDL語法實現取消隱藏 PS C:\WINDOWS\system32> & $env:SystemRoot\System32\sc.exe sdset SWCUEngine "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)" [SC] SetServiceObjectSecurity SUCCESS # 如今使用 Get-Serice 指令能夠查看到對應的服務信息 PS C:\WINDOWS\system32> Get-Service -Name 'SWCUEngine' Status Name DisplayName ------ ---- ----------- Running SWCUEngine SWCUEngine