Batch Example via WinRPC

Parsing the piped input

As mentioned above, a BASE64 string will be piped into your script, which includes the username and new password (among other data), which you will use to rotate the Windows Service's credentials.

Using the below snippet, we can take the piped input and use certutil to decode the BASE64 string. These will be saved to temporary files and cleaned up later, as is the custom in bat scripts, as certutil only accepts files as input.

@echo off
for /f "tokens=*" %%a in ('more') do set input=%%a

set base64tmp=%temp%\base64.tmp
set json=%temp%\json.tmp

echo %input% > %base64tmp%

certutil -decode %base64tmp% %json%

jq can be used on the resulting JSON file to get the values of user and newPassword.

for /f "usebackq delims=" %%a in (`jq -r .user %json%`) do set "user=%%a"
for /f "usebackq delims=" %%a in (`jq -r .newPassword %json%`) do set "newPassword=%%a"

Updating the Service

The sc command is used to update the desired Windows service using the values you just extracted. Replace the server and service names with your specific server and service details.

After updating the Windows Service, we will restart it, which will confirm that the credentials have been updated successfully.

sc "\\your-server" stop "Service Name"
sc "\\your-server" config "Service Name" obj= %user% password= "%newPassword%"
sc "\\your-server" start "Service Name"

Note: Server hostnames should start with a double backslash. The newPassword variable is enclosed in quotes to handle symbols

Full Example

@echo off

:: Set the server name and service name as variables
set server=\\your-server
set service=SERVICENAME

for /f "tokens=*" %%a in ('more') do set input=%%a

set base64tmp=%temp%\base64.tmp
set json=%temp%\json.tmp

echo %input% > %base64tmp%

certutil -decode %base64tmp% %json%

for /f "usebackq delims=" %%a in (`jq -r .user %json%`) do set "user=%%a"
for /f "usebackq delims=" %%a in (`jq -r .newPassword %json%`) do set "newPassword=%%a"

del %base64tmp%
del %json%

echo "Stopping..."

sc "%server%" query "%service%" | find "STOPPED"
if errorlevel 1 (
    echo "Stopping"
    sc "%server%" stop "%service%"
)

echo "Waiting for service to stop"

set count=1
set limit=120
:loop
sc "%server%" query "%service%" | find "STOPPED"
if errorlevel 1 (
    ping 127.0.0.1 -n 1 > NUL 
    set /a count += 1
    if %count% lss %limit% goto loop
)

sc "%server%" query "%service%" | find "STOPPED"
if errorlevel 1 (
    echo "Timed out"
    exit /b 1
)

echo "Service stopped, waiting 5 seconds"
timeout /t 5 /nobreak >nul

echo "Setting new password"
sc "%server%" config "%service%" obj=%user% password="%newPassword%"
if %errorlevel% neq 0 exit /b %errorlevel%

echo "Updated, waiting 2 seconds"
timeout /t 5 /nobreak >nul

echo "Starting service"
sc "%server%" start "%service%"
if %errorlevel% neq 0 exit /b %errorlevel%

Last updated