Skip to content

tripplet/remote-shutdown

Repository files navigation

Remote Shutdown

Allows easy shutdown of a windows pc via network.

The program runs as a windows service and opens the TCP port 10102.

Download

Features

  • Less then 1MB memory usage
  • No need to store windows credentials on external systems
  • Secure and simple challenge response protocol
  • Easy installation with ready to use msi setup
  • Command exchange can easily be implemented in almost any programming language (even on and ESP8266)
  • The generated key is stored securely using Protected Storage.
  • The generated key cannot be retrieved again, only reset. Access to the protected storage would only be possible for Administrator users.

Existing clients

  • Python

  • Go

  • Home Assistant Easy usage via HACS by adding

    https://github.com/tripplet/remote-shutdown to the user defined repositories.

Limitations / TODOs

  • Only one active TCP connection can be handled.

Generating/Retrieving the secret

The following command will generate a new secret and print it once. If the command is executed a second time a new secret will be generated overwriting the old one.

"C:\Program Files\RemoteShutdown\RemoteShutdown.exe" -t

This assumes RemoteShutdown was installed using the msi and the service is running.

Details

There are currently two commands:

  • shutdown: This will only shutdown the PC if there is no active UI session. A locked screen also counts as an active session. Only if no user is logged on this command will shutdown the PC. This can be useful if the pc was started using wake on lan to retrieve files via smb. In this case the shutdown command can savely be used as the pc will only shutdown if no user logged in.
  • admin_shutdown: This will always shutdown the pc regardless of any active UI session.

The user is given a message from windows that the shutdown will be performed in 1 minute. This allows the user to cancel the shutdown with the normal windows command: shutdown /a.

Detailed protocol example (python)

The complete python code can be found here. All packet must be terminated with the line break \n and all text is ASCII encoded. The client has a window of 5 seconds to send a valid response.

  1. The client opens a TCP connection to the windows PC on port 10102.

    conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    conn.connect(('windows pc', 10102))
  2. The client sends the ASCII text "request_challenge".

    conn.send(b'request_challange\n')
  3. The windows pc response with an UTC timestamp and a challenge. The timestamp encodes the expiration of the challenge (now() + 5 seconds). Example: 12345678.RANDOM_LONG_HEX_CHALLENGE_STRING

  4. The client receives the challenge and calculates the response with the shared secret.

    challenge = conn.recv(2048).decode('ascii').strip()
    
    cmd = 'admin_shutdown'
    message = f'{cmd}.{challenge}'.encode('ascii')
    mac = hmac.new(secret.encode('ascii'), message, hashlib.sha256)
  5. The client sends the response with the hex encoded HMAC.

    conn.send((f'{cmd}.{challenge}.{mac.hexdigest()}\n').encode('ascii'))
  6. The windows pc response with the ascii number "1" (0x31) if the shutdown will be performed. Any other response indicates an error. As with all commands the final response is terminated with \n. The server will not activly close the TCP session, this is the responsibility of the client.

    Be aware that the shutdown can still be canceled by the user.

Sequence diagram

Sequence diagram

Example exchange

The secret used in the example below is: test

client <=> windows_pc
 => request_challenge
<=  1619638694.7dc4b36ec0a0bd4d7f71edaa6d87879b62ba4f9cc7ac846d2618a8ed4231097f
 => shutdown.1619638694.7dc4b36ec0a0bd4d7f71edaa6d87879b62ba4f9cc7ac846d2618a8ed4231097f.eff9e46c45741c2efd581ce86b94cb1665cf298f61c55343d28b496b8cd74de9
<=  Error: active user logged in