0

已编辑:下面的代码有效,并且对更改进行了注释。如前所述,在 python3 中,必须在字符串文字前加上“b”,以生成 byte 类型的实例,而不是 Unicode str 类型。

我正在尝试在 Python 3 中使用 msfrpc(用 Python 2 编写),但遇到了身份验证错误。我正在使用的代码如下;请参阅代码中的注释以了解我所做的更改。

该程序在 python2 中成功运行(使用 httplib 而不是 http.client 时),似乎与使用 python3 时看到的身份验证交换相同。

import msgpack
import http.client #Changed from httplib

class Msfrpc:
  class MsfError(Exception):
    def __init__(self,msg):
      self.msg = msg
    def __str__(self):
      return repr(self.msg)

  class MsfAuthError(MsfError):
    def __init__(self,msg):
      self.msg = msg

  def __init__(self,opts=[]):
    self.host = opts.get('host') or "127.0.0.1"
    self.port = opts.get('port') or 55552
    self.uri = opts.get('uri') or "/api/"
    self.ssl = opts.get('ssl') or False
    self.authenticated = False
    self.token = False
    self.headers = {"Content-type" : "binary/message-pack" }
    if self.ssl:
      self.client = http.client.HTTPSConnection(self.host,self.port)  #Changed httplib -> http.client
    else:
      self.client = http.client.HTTPConnection(self.host,self.port)        #Changed httplib -> http.client

  def encode(self,data):
    return msgpack.packb(data)
  def decode(self,data):
    return msgpack.unpackb(data)

   def call(self,meth,opts = []):
    if meth != "auth.login":
      if not self.authenticated:
        raise self.MsfAuthError("MsfRPC: Not Authenticated")

    if meth != "auth.login":
      opts.insert(0,self.token)

    opts.insert(0,meth)
    params = self.encode(opts)
    self.client.request("POST",self.uri,params,self.headers)
    resp = self.client.getresponse()
    return self.decode(resp.read()) 

  def login(self,user,password):
    ret = self.call('auth.login',[user,password])
    if ret.get(b'result') == b'success': #Added b
      self.authenticated = True
      self.token = ret.get(b'token') #Added b
      return True
    else:
      raise self.MsfAuthError("MsfRPC: Authentication failed")

if __name__ == '__main__':

  # Create a new instance of the Msfrpc client with the default options
  client = Msfrpc({})

  # Login to the msfmsg server using the password "abc123"
  client.login('msf','abc123')

  # Get a list of the exploits from the server
  mod = client.call('module.exploits')

  # Grab the first item from the modules value of the returned dict
  print ("Compatible payloads for : %s\n" % mod[b'modules'][0]) #Added () #Added b

  # Get the list of compatible payloads for the first option
  ret = client.call('module.compatible_payloads',[mod[b'modules'][0]]) #Added b
  for i in (ret.get(b'payloads')): #Added b
    print ("\t%s" % i)  #Added ()

运行程序时,结果是:

root@kali:~/Dropbox/PythonStuff/python-nmap-test# python3 test3.py
Traceback (most recent call last):
  File "test3.py", line 20, in <module>
    client.login('msf','abc123')
  File "/usr/local/lib/python3.7/dist-packages/msfrpc.py", line 64, in login  
    raise self.MsfAuthError("MsfRPC: Authentication failed")
msfrpc.MsfAuthError: 'MsfRPC: Authentication failed'

奇怪的是,在程序执行时运行 tcpdump 会显示成功的身份验证和授予的令牌:

在此处输入图像描述

当程序使用 python2 成功执行时,身份验证交换看起来相同,但如果有人觉得发布程序的数据包捕获(在 python2 中运行)成功完成将有助于回答我可以轻松添加的问题。

4

1 回答 1

0

对此没有太大兴趣,但如果其他人有问题,我会发布答案;解决方案非常简单,我注意到上面发布的代码中的更改。

问题是 msfrpc 最初是用 Python 2 编写的,因此来自 Metasploit 主机的 msgpack RPC 响应中的前缀“b”被忽略了,但在 Python 3 中需要指示该文字应该成为字节文字而不是字符串类型。

有关更多信息,请查看以下链接;一旦我读到它,答案就很明显了: https ://timothybramlett.com/Strings_Bytes_and_Unicode_in_Python_2_and_3.html

上面的代码工作正常,但真正更好的解决方案是使用由 Dan McInerney 编写的 msfrpc 模块,它使用 'requests' 包。

https://github.com/DanMcInerney/msfrpc

于 2019-08-17T03:05:47.243 回答