Le script ci-dessous propose d’utiliser le module pypsrp (https://pypi.org/project/pypsrp/) pour executer n’importe quelle commande (cmd/powershell) sur une machine windows distante.
Dans cet exemple l’authentification se fait via kerberos, mais le parametre auth de wsman peut utiliser basic
, certificate
, negotiate
, ntlm
, kerberos
, credssp
wsman = WSMan(target, ssl=False, auth='kerberos')
Par defaut le mode winrm utilisé (–winrm-mode) est runspacepool qui est plus compatible avec des commandes ou des blocs de code powershell.
Un test de connectivité winrm (–test-winrm-port, par defaut activé) permet de tester la connexion avant d’executer la commande.
Le paramètre –execute-remote-action etant par defaut desactivé (False), il est necessaire de l’activer (–execute-remote-action True) pour executer effectivement la commande.
help = """
SCRIPT D'EXECUTION DE COMMANDES WINRM SUR UNE MACHINE WINDOWS CIBLE DEFINIE EN ARGUMENT.
Description :
Ce script a été développé à l'occasion d'une demande de reboots récurrents de nombreuses machines Windows. Il a été implémenté de manière à pouvoir être réutilisé pour d'autre commandes `winrm` que le reboot.
ARGUMENTS:
- --get-help True: Affiche l'aide.
- --win-computer: Nom de la machine cible Windows sur laquelle exécuter la commande. (Requis)
- --execute-remote-action True: Execute les actions sur les machines distantes. (Valeur par défaut: False)
- --remote-command: Commande à exécuter sur les machines distantes. (Valeur par défaut: whoami)
- --test-winrm-port True: Test de la connexion au port WinRM des machines distantes avec le module socket. (Valeur par défaut: True)
- --winrm-mode: methode d'execution de la commande sur la machine distante. (Valeur par défaut: runspacepool)
Exemple d'utilisation:
- Executer la commande "whoami" sur la machine "mycomputer" avec le test de connexion au port WinRM:
python run_winrm_cmd_on_host.py --win-computer mycomputer --execute-remote-action True --test-winrm-port True --remote-command "get-process"
"""
import sys
import os
import argparse
from pypsrp.shell import Process, WinRS
from pypsrp.powershell import PowerShell, RunspacePool
from pypsrp.wsman import WSMan
import socket
if __name__ == '__main__':
###########################################
# Arguments du script
###########################################
parser = argparse.ArgumentParser()
parser.add_argument(
'--get-help',
type=str,
choices=['True', 'False'],
default='False',
help='Affiche l\'aide.'
)
parser.add_argument(
'--win-computer',
type=str,
help='machine cible Windows'
)
parser.add_argument(
'--execute-remote-action',
type=str,
choices=['True', 'False'],
default='False',
help='Execute effectivement les actions sur les machines distantes.'
)
parser.add_argument(
'--remote-command',
type=str,
default="whoami",
help='Commande à exécuter sur les machines distantes.'
)
parser.add_argument(
'--test-winrm-port',
type=str,
choices=['True', 'False'],
default='True',
help='Test de la connexion au port WinRM des machines distantes avec le module socket.'
)
parser.add_argument(
'--winrm-mode',
type=str,
choices=['winrs', 'runspacepool'],
default='runspacepool',
help='methode d\'execution de la commande sur la machine distante.'
)
args = parser.parse_args()
if args.get_help == 'True':
print(
help
)
sys.exit(0)
############################################################################
### VERIFICATION DE LA CONNEXION A LA MACHINE CIBLE AVEC LE MODULE SOCKET
############################################################################
if args.test_winrm_port == 'True':
print("---------------------------------------------------------------------------------------------------------------------------------------------")
print(f"TEST DE RESOLUTION DE NOM ET CONNEXION AU PORT 5985 (WINRM) pour la machine {args.win_computer} avec le module socket")
print("---------------------------------------------------------------------------------------------------------------------------------------------")
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sockresult = sock.connect_ex((args.win_computer,5985))
if not socket.gethostbyname(args.win_computer):
print("!!! resolution KO pour " + args.win_computer +"!!!")
wincomputer_resolved = False
exit(1)
if not (sockresult == 0):
print("!!! WinRM TCP KO pour " + args.win_computer +"!!!")
wincomputer_resolved = True
winrm_port_open = False
exit(1)
else:
print("resolution OK et WinRM OK pour " + args.win_computer )
sock.close()
except Exception as error:
print(f"ERREUR: {error}")
exit(1)
print("---------------------------------------------------------------------------------------------------------------------------------------------")
########################################
### ACTION SUR LA MACHINE AVEC WINRM
########################################
# Action executee si argument execute_remote_action = True et si la machine est joignable
if args.execute_remote_action == 'True':
### METHODE 1: WINRS
if args.winrm_mode == 'winrs':
try:
target = args.win_computer
print(f"EXECUTION DE LA COMMANDE SUR LA MACHINE \"{target}\"")
print("------------------------------------------------------------------------------------------------------------------------------")
#creates a http connection with no encryption and kerberos auth
wsman = WSMan(target, ssl=False, auth='kerberos')
# # create a shell with wsman
with wsman, WinRS(wsman) as shell:
# execute a process with arguments in the background
process = Process(shell, args.remote_command)
process.begin_invoke() # start the invocation and return immediately
process.poll_invoke() # update the output stream
process.end_invoke() # finally wait until the process is finished
output = str(process.stdout, errors='ignore')
print(output)
print("------------------------------------------------------------------------------------------------------------------------------\r")
except Exception as error:
print(f"ERREUR: {error}")
pass
### METHODE 2: RUNSPACEPOOL
if args.winrm_mode == 'runspacepool':
try:
target = args.win_computer
print(f"EXECUTION DE LA COMMANDE SUR LA MACHINE \"{target}\"")
print("------------------------------------------------------------------------------------------------------------------------------")
# creates a https connection with explicit kerberos auth and implicit credentials
wsman = WSMan(target, ssl=False, auth="kerberos", cert_validation=False)
with wsman, RunspacePool(wsman) as pool:
# POUR EXECUTER UNE COMMANDE POWERSHELL SPECIFIQUE (IL FAUT FINIR AVEC OUT-STRING POUR AVOIR UN RETOUR DE TYPE STRING)
# EX: execute 'Get-Process | Select-Object Name | out-string'
ps = PowerShell(pool)
#ps.add_cmdlet("get-process").add_cmdlet("Select-Object").add_argument("Name").add_cmdlet("Out-String")
ps.add_script(args.remote_command + " | out-string")
ps.invoke()
for out in ps.output:
print(out)
except Exception as error:
print(f"ERREUR: {error}")
pass
0 commentaires