Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added deluserfromgroup bof #36

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions Remote/Remote.cna
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,36 @@ Usage: addusertogroup <USERNAME> <GROUPNAME> <SERVER> <DOMAIN>
"
);

#deluserfromgroup
alias deluserfromgroup
{
if(size(@_) != 5)
{
berror($1, beacon_command_detail("deluserfromgroup"));
berror($1, "Invalid number of parameters");
return;
}
beacon_inline_execute($1, readbof($1, "deluserfromgroup"), "go", bof_pack($1, "ZZZZ", $5, $4, $2, $3));
}

beacon_command_register(
"deluserfromgroup",
"Remove the specified user from the specified group",
"
Command: deluserfromgroup
Summary: Remove the specified user from the specified group.

Usage: deluserfromgroup <USERNAME> <GROUPNAME> <SERVER> <DOMAIN>
USERNAME Required. The user name to remove from group.
GROUPNAME Required. The group to remove the user from.
SERVER Required. The target computer to remove the user. use \"\" for the local machine
DOMAIN Required. The domain/computer for the account. You must give
the domain name for the user if it is a domain account, or
use \"\" to target an account on the local machine.

"
);

#adduser
alias adduser
{
Expand Down
Binary file added Remote/deluserfromgroup/deluserfromgroup.x64.o
Binary file not shown.
Binary file added Remote/deluserfromgroup/deluserfromgroup.x86.o
Binary file not shown.
25 changes: 25 additions & 0 deletions src/Remote/deluserfromgroup/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
BOFNAME := deluserfromgroup
COMINCLUDE := -I ../../common
LIBINCLUDE := -lnetapi32
CC_x64 := x86_64-w64-mingw32-gcc
CC_x86 := i686-w64-mingw32-gcc
CC := x86_64-w64-mingw32-clang

all:
$(CC_x64) -o $(BOFNAME).x64.o $(COMINCLUDE) -Os -c entry.c -DBOF
$(CC_x86) -o $(BOFNAME).x86.o $(COMINCLUDE) -Os -c entry.c -DBOF
mkdir -p ../../../Remote/$(BOFNAME)
mv $(BOFNAME)*.o ../../../Remote/$(BOFNAME)

test:
$(CC_x64) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x64.exe
$(CC_x86) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).x86.exe

scanbuild:
$(CC) entry.c $(COMINCLUDE) $(LIBINCLUDE) -o $(BOFNAME).scanbuild.exe

check:
cppcheck --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction $(COMINCLUDE) --platform=win64 entry.c

clean:
rm $(BOFNAME).*.exe
106 changes: 106 additions & 0 deletions src/Remote/deluserfromgroup/entry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <windows.h>
#include <stdio.h>
#include <lmaccess.h>
#include "beacon.h"
#include "bofdefs.h"
#include "base.c"


DWORD DelUserFromDomainGroup(LPCWSTR lpswzServer, LPCWSTR lpswzUserName, LPCWSTR lpswzGroupName)
{
NET_API_STATUS dwErrorCode = NERR_Success;
dwErrorCode = NETAPI32$NetGroupDelUser(lpswzServer, lpswzGroupName, lpswzUserName);
return dwErrorCode;
}

DWORD DelUserFromLocalGroup(LPCWSTR lpswzServer, LPCWSTR lpswzUserName, LPCWSTR lpswzGroupName, LPCWSTR lpswzDomainName)
{
NET_API_STATUS dwErrorCode = NERR_Success;
LOCALGROUP_MEMBERS_INFO_3 mi[1] = {0}; // https://learn.microsoft.com/en-us/windows/win32/api/lmaccess/ns-lmaccess-localgroup_members_info_3
mi[0].lgrmi3_domainandname = intAlloc(1024);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this memory should be freed using intFree()

if (lpswzDomainName != NULL)
{
MSVCRT$wcscat(mi[0].lgrmi3_domainandname, lpswzDomainName);
MSVCRT$wcscat(mi[0].lgrmi3_domainandname, L"\\");
}
MSVCRT$wcscat(mi[0].lgrmi3_domainandname, lpswzUserName);
dwErrorCode = NETAPI32$NetLocalGroupDelMembers(lpswzServer, lpswzGroupName, 3, (LPBYTE)mi, 1);
return dwErrorCode;
}

#ifdef BOF
VOID go(
IN PCHAR Buffer,
IN ULONG Length
)
{
DWORD dwErrorCode = ERROR_SUCCESS;
datap parser = {0};
BeaconDataParse(&parser, Buffer, Length);
LPCWSTR lpswzDomainName = (LPCWSTR)BeaconDataExtract(&parser, NULL); // $5
LPCWSTR lpswzHostName = (LPCWSTR)BeaconDataExtract(&parser, NULL); // $4
LPCWSTR lpswzUserName = (LPCWSTR)BeaconDataExtract(&parser, NULL); // $2
LPCWSTR lpswzGroupName = (LPCWSTR)BeaconDataExtract(&parser, NULL);// $3
if(lpswzHostName[0] == L'\0'){lpswzHostName = NULL;}
if(lpswzDomainName[0] == L'\0'){lpswzDomainName = NULL;}

if(!bofstart())
{
return;
}

if (lpswzDomainName == NULL && lpswzHostName != NULL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the description all of the available arguments are listed as required

If I give both a hostname and a domain name, SUCCESS. will be printed but nothing will happen.

I'd split this into two aliases one to remove a user from a computer local group and one to remove it from a domain group. Then you can enforce this logic in the cna script easily.

barring that the cna shouldn't list everything as required and should explain what is expected for local vs domain group deletion.

{
BeaconPrintf(CALLBACK_OUTPUT, "Removing %S from %S\n", lpswzUserName, lpswzGroupName);
dwErrorCode = DelUserFromDomainGroup(lpswzHostName, lpswzUserName, lpswzGroupName);
if ( ERROR_SUCCESS != dwErrorCode )
{
BeaconPrintf(CALLBACK_ERROR, "Removing user from domain group failed: %lX\n", dwErrorCode);
goto go_end;
}
}
else if (lpswzHostName == NULL)
{
BeaconPrintf(CALLBACK_OUTPUT, "Removing %S from local group %S\n", lpswzUserName, lpswzGroupName);
dwErrorCode = DelUserFromLocalGroup(lpswzHostName, lpswzUserName, lpswzGroupName, lpswzDomainName);
if (ERROR_SUCCESS != dwErrorCode)
{
BeaconPrintf(CALLBACK_ERROR, "Unable to remove user to local group %lX\n", dwErrorCode);
goto go_end;
}
}
internal_printf("SUCCESS.\n");

go_end:
printoutput(TRUE);
bofstop();
};
#else
#define TEST_USERNAME L"localadmin2"
#define TEST_HOSTNAME L""
#define TEST_GROUPNAME L"Remote Desktop Users"
#define TEST_DOMAIN L"WOOT"

int main(int argc, char ** argv)
{
DWORD dwErrorCode = ERROR_SUCCESS;
LPCWSTR lpswzHostName = TEST_HOSTNAME;
LPCWSTR lpswzUserName = TEST_USERNAME;
LPCWSTR lpswzGroupName = TEST_GROUPNAME;
LPCWSTR lpswzDomainName = TEST_DOMAIN;

internal_printf("Removing %S from %S\n", lpswzUserName, lpswzGroupName);

dwErrorCode = DelUserFromLocalGroup(lpswzHostName, lpswzUserName, lpswzGroupName, lpswzDomainName);
if ( ERROR_SUCCESS != dwErrorCode )
{
BeaconPrintf(CALLBACK_ERROR, "Removing user from group failed: %lX\n", dwErrorCode);
goto main_end;
}

internal_printf("SUCCESS.\n");

main_end:
return dwErrorCode;
}
#endif
3 changes: 2 additions & 1 deletion src/common/bofdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,13 @@ WINBASEAPI DWORD WINAPI NETAPI32$NetQueryDisplayInformation(LPCWSTR ServerName,D
WINBASEAPI DWORD WINAPI NETAPI32$NetLocalGroupEnum(LPCWSTR servername,DWORD level,LPBYTE *bufptr,DWORD prefmaxlen,LPDWORD entriesread,LPDWORD totalentries,PDWORD_PTR resumehandle);
WINBASEAPI DWORD WINAPI NETAPI32$NetLocalGroupGetMembers(LPCWSTR servername,LPCWSTR localgroupname,DWORD level,LPBYTE *bufptr,DWORD prefmaxlen,LPDWORD entriesread,LPDWORD totalentries,PDWORD_PTR resumehandle);
WINBASEAPI DWORD WINAPI NETAPI32$NetLocalGroupAddMembers(LPCWSTR servername,LPCWSTR groupname,DWORD level,LPBYTE buf,DWORD totalentries);
WINBASEAPI DWORD WINAPI NETAPI32$NetLocalGroupDelMembers(LPCWSTR servername,LPCWSTR groupname,DWORD level,LPBYTE buf,DWORD totalentries);
WINBASEAPI DWORD WINAPI NETAPI32$NetUserSetInfo(LPCWSTR servername,LPCWSTR username,DWORD level,LPBYTE buf,LPDWORD parm_err);
WINBASEAPI DWORD WINAPI NETAPI32$NetShareEnum(LMSTR servername,DWORD level,LPBYTE *bufptr,DWORD prefmaxlen,LPDWORD entriesread,LPDWORD totalentries,LPDWORD resume_handle);
WINBASEAPI DWORD WINAPI NETAPI32$NetSessionEnum(LPCWSTR servername, LPCWSTR UncClientName, LPCWSTR username, DWORD level, LPBYTE* bufptr, DWORD prefmaxlen, LPDWORD entriesread, LPDWORD totalentries, LPDWORD resumehandle);
WINBASEAPI DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID Buffer);
WINBASEAPI DWORD WINAPI NETAPI32$NetGroupAddUser(LPCWSTR servername,LPCWSTR GroupName,LPCWSTR userName);
WINBASEAPI DWORD WINAPI NETAPI32$NetGroupAddUser(LPCWSTR servername,LPCWSTR GroupName,LPCWSTR userName);
WINBASEAPI DWORD WINAPI NETAPI32$NetGroupDelUser(LPCWSTR servername,LPCWSTR GroupName,LPCWSTR userName);
WINBASEAPI DWORD WINAPI NETAPI32$NetUserAdd(LPCWSTR servername, DWORD level, LPBYTE buf, LPDWORD parm_err);

//MPR
Expand Down