winrm的全称是Windows Remote Management,翻译就是windows的远程管理,说白了就是通过网络http请求在对windows进行管理,由于我之前是用python开发,所以此次我记录的使用python的pywinrm模块来实现对windows的远程访问。
winrm这个模块windows是自带的,但是好像默认功能是关闭的,需要去命令行执行命令开启这个功能,具体命令是啥也忘记了,不过网上应该能搜到,有很多。我这里主要记录的是pywinrm这个模块的时间笔记。
我们一般使用的是winrm模块向远程主机执行命令行命令,主要实现远程对账户的控制命令,我另外一篇文章有写哪些命令来完成账户的远程控制:命令行管理账户,此时就会存在cmd命令和PowerShell命令,一般python的winrm模块里面存在此封装,如下所示
import winrm
shell="net user"
s = winrm.Session(ip, auth=(username, password), transport='ntlm') # 远程连接windows
r = s.run_ps(shell) #是powershell命令就执行此函数
r = s.run_cmd(shell) #是命令行提示符cmd命令就执行此函数
上面代码里面有两个执行命令的函数,一个是run_ps,一个是run_cmd,分别对应执行PowerShell的命令和cmd的命令,这两个命令,其实背后都是调用Protocol,然后进行了封装,我测试了,好像运行起来速度有点慢,而且有些命令还执行有问题,然后我就自己重构了Protocol类,让这个类既可以支持PowerShell命令,又可以支持cmd命令。一般情况下Protocol默认只支持cmd命令的。我的源码如下:
from winrm.protocol import Protocol
from base64 import b64encode
class NewProtocol(Protocol):
def run_command_ps(self, newshell_id, newcommand):
encoded_ps = b64encode(newcommand.encode('utf_16_le')).decode('ascii')
newcmd = 'powershell -encodedcommand {0}'.format(encoded_ps)
return self.run_command(shell_id=newshell_id, command=newcmd)
#上面NewProtocol类是我重构的Protocol类,下面有实例怎么调用
class PowerShellCmdClass():
def __init__(self,assitsip,adminname,adminpd):
self.end_point = "http://%s:5985/wsman" % assitsip
self.adminname = adminname
self.adminpd = adminpd
self.p = None
self.shell_id = None
self.command_id = None
def initconnect(self):
try:
self.p = NewProtocol(
endpoint=self.end_point,
transport='ntlm',
username=self.adminname,
password=self.adminpd,
server_cert_validation='ignore')
self.shell_id = self.p.open_shell() # 打开shell
return 0
except Exception as e:
return -1
def cmdtest(self):
try:
cmd = "net user" #命令行提示符cmd柯执行的命令
self.command_id = self.p.run_command(self.shell_id, cmd)
std_out, std_err, status_code = self.p.get_command_output(self.shell_id, self.command_id) # 获取返回结果
# print(status_code)
#print(str(std_out, 'utf-8'))
return status_code
except Exception as e:
return -1
def powershelltest(self):
try:
cmd = "Get-ACL -Path C:\Users" #PowerShell才能执行的命令
self.command_id = self.p.run_command_ps(self.shell_id, cmd)
std_out, std_err, status_code = self.p.get_command_output(self.shell_id, self.command_id) # 获取返回结果
# print(status_code)
#print(str(std_out, 'utf-8'))
return status_code
except Exception as e:
return -1
def freeinit(self):
self.p.cleanup_command(self.shell_id, self.command_id)
self.p.close_shell(self.shell_id) # 关闭shell
# 测试程序
newcmd = UserCmdClass("192.168.10.192","admin","1") #参数为远程主机ip地址、管理账户和管理员账户密码
newcmd .initconnect()
newcmd .cmdtest()
newcmd .powershelltest()
newcmd .freeinit
在上面的源码中可以看到,我重构了Protocol类,让其多了一个功能为run_command_ps的函数,此函数支持PowerShell命令的远程调用,我测试了这run_command_ps和run_command发送的命令,速度很快,比run_ps和run_cmd要好用一些。