01閱讀須知
此文所提供的信息只為網絡安全人員對自己所負責的網站、服務器等(包括但不限于)進行檢測或維護參考,未經授權請勿利用文章中的技術資料對任何計算機系統進行入侵操作。利用此文所提供的信息而造成的直接或間接后果和損失,均由使用者本人負責。本文所提供的工具僅用于學習,禁止用于其他方面
02SCM函數基本介紹
在Windows操作系統中,Services服務是以后臺進程的形式運行的,通常以高權限啟動并運行。因此,紅隊經常利用.NET框架,通過創建和管理Windows服務來實現權限維持。
2.1 SCM函數原型
OpenSCManager是Windows API中的一個核心函數,用于打開服務控制管理器 (Service Control Manager, SCM) 數據庫。服務控制管理器是Windows操作系統中管理服務的組件。通過這個函數,我們可以獲取一個句柄,用于后續操作(如創建、查詢、啟動或停止服務)。函數原型如下所示。
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
OpenSCManager函數需要提供三個參數,machineName: 指定目標計算機名稱,databaseName: 指定要打開的數據庫名稱。dwAccess: 指定所需的訪問權限,例如SC_MANAGER_CREATE_SERVICE (值為2U),允許創建系統服務,詳細的權限說明如下所示。
當成功時,返回一個非零值 (IntPtr),表示服務控制管理器數據庫的句柄,如果遇到失敗:返回IntPtr.Zero,可以通過調用Marshal.GetLastWin32Error獲取詳細的錯誤信息。
2.2?使用SCM函數
以下是一個使用OpenSCManager函數打開本地服務控制管理器并創建服務的完整示例,具體代碼如下所示。
using System;
using System.Runtime.InteropServices;class Program
{[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]private static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);const uint SC_MANAGER_CREATE_SERVICE = 0x2;static void Main(){// 打開服務控制管理器IntPtr scmHandle = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);// 檢查返回值是否為零if (scmHandle == IntPtr.Zero){int errorCode = Marshal.GetLastWin32Error();Console.WriteLine($"Failed to open SCM. Error Code: {errorCode}");return;}Console.WriteLine("Successfully opened the Service Control Manager.");// 后續邏輯:創建服務、啟動服務等// ...// 記得關閉句柄(如果需要)}
}
上述代碼,通過P/Invoke調用OpenSCManager函數,打開服務管理器的句柄,OpenSCManager是服務管理的起點,其返回的句柄直接影響后續操作的成功與否。使用時需注意提供正確的權限和參數,避免運行時錯誤。
03CreateService基本介紹
成功獲取SCM句柄后,可以通過調用CreateService函數創建一個新的系統服務,函數的原型如下所示。
[DllImport("Advapi32.dll")]
public static extern IntPtr CreateService(IntPtr serviceControlManagerHandle,string lpSvcName,string lpDisplayName,Program.SERVICE_ACCESS dwDesiredAccess,uint dwServiceType,uint dwStartType,uint dwErrorControl,string lpPathName,string lpLoadOrderGroup,IntPtr lpdwTagId,string lpDependencies,string lpServiceStartName,string lpPassword);
通常,創建服務時,需要提供服務的名稱、顯示名稱、啟動類型和服務路徑等關鍵信息,詳細參數列表如下所示。
以下代碼演示如何創建服務,服務創建失敗,會返回IntPtr.Zero,需要處理錯誤,具體代碼如下所示。
string serviceName = "MyService";
string serviceDisplayName = "My Custom Service";
string binPath = @"C:\Path\To\YourService.exe";IntPtr serviceHandle = Program.CreateService(scmHandle,serviceName,serviceDisplayName,SERVICE_ACCESS.SERVICE_ALL_ACCESS,16U, 2U, 1U, binPath,null,IntPtr.Zero,null,null,null);if (serviceHandle == IntPtr.Zero)
{throw new Exception("Failed to create service.");
}
04工具實現
攻擊者通過?Sharp4Stay.exe 工具,利用?OpenSCManager 和?CreateService 函數打開服務控制管理器數據庫、創建系統服務以及啟動服務等這些步驟,實現目標權限維持。
因為圖片過長,不便于文章展示,因此通過隱藏部分用法達到縮短圖片長度,不便之處請讀者朋友們諒解。
05.NET安全星球
dot.Net安全矩陣星球已成為中國.NET安全領域最知名、最活躍的技術知識庫之一,從.NET Framework到.NET Core,從Web應用到PC端軟件應用,無論您是初學者還是經驗豐富的開發人員,都能在這里找到對應的安全指南和最佳實踐。
星球匯聚了各行業安全攻防技術大咖,并且每日分享.NET安全技術干貨以及交流解答各類技術等問題,社區中發布很多高質量的.NET安全資源,可以說市面上很少見,都是干貨。
星球文化始終認為授人以魚不如授人以漁!加入星球后可以跟星主和嘉賓們一對一提問交流,20+個專題欄目涵蓋了點、線、面、體等知識面,助力師傅們快速成長!其中主題包括.NET Tricks、漏洞分析、內存馬、代碼審計、預編譯、反序列化、webshell免殺、命令執行、C#工具庫等等。
????我們傾力打造專刊、視頻等配套學習資源,循序漸進的方式引導加深安全攻防技術提高以及崗位內推等等服務。
.NET?免殺WebShell
.NET?反序列化漏洞
.NET?安全防御繞過
.NET?內網信息收集
.NET?本地權限提升
.NET?內網橫向移動
.NET?目標權限維持
.NET?數據外發傳輸
這些階段所涉及的工具集不僅代表了當前.NET安全領域的最前沿技術,更是每一位網絡安全愛好者不可或缺的實戰利器。
文章涉及的工具已打包,請加/入/后下/載:https://wx.zsxq.com/group/51121224455454