Sun, 13 Oct 2013

In which we Metasploit via python over msgpack .:.permalink.:.

Recently metasploit changed it's rpc interface from xmlrpc to msgpack over http. Sad because it breaks kinectasploit but all things change, so this is a quick bit about interfacing python to metasploit via msgpack rpc.

First get the python dependencies: easy_install msgpack-python

Then fire up a metasploit rpc session: 

 msf3 # ./msfconsole 

     ,           ,
    /             \
   ((__---,,,---__))
      (_) O O (_)_________
         \ _ /            |\
          o_o \   M S F   | \
               \   _____  |  *
                |||   WW|||
                |||     |||


       =[ metasploit v4.2.0-dev [core:4.2 api:1.0]
+ -- --=[ 776 exploits - 415 auxiliary - 121 post
+ -- --=[ 238 payloads - 27 encoders - 8 nops
       =[ svn r14431 updated today (2011.12.20)

msf >  load msgrpc User=msf Pass='abc123'
[*] MSGRPC Service:  127.0.0.1:55552 
[*] MSGRPC Username: msf
[*] MSGRPC Password: abc123
[*] Successfully loaded plugin: msgrpc
msf >

HUGE Thanks to Ryan Linn (@sussurro) for figuring out the python bit. The short story is msgpack over http like so: 

#setup the headers, static client target
headers = {"Content-type" : "binary/message-pack" }
client =  httplib.HTTPConnection('localhost',55552)

#call an api function 
user='msf'
password='abc123'
token=''
params = msgpack.packb(['auth.login',user,password])
client.request("POST", "/api/", params, headers)
response = client.getresponse()
if response.status == 200:
        data = response.read()
else:
        print "Connection Failed"
        sys.exit()



Here's full python code to create a console, search for rpc modules and quit.
Happy pythonasploiting! 

#!/usr/bin/python
import time
import msgpack
import httplib
import sys

user='msf'
password='abc123'
token=''

#setup the headers, static client target
headers = {"Content-type" : "binary/message-pack" }
client =  httplib.HTTPConnection('localhost',55552)

params = msgpack.packb(['auth.login',user,password])
client.request("POST", "/api/", params, headers)
response = client.getresponse()
if response.status == 200:
        data = response.read()
else:
        print("Connection Failed")
        sys.exit()

res = msgpack.unpackb(data)
token = ""
if res['result'] == 'success':
        token = res['token']
else:
        print("Auth failed")
        sys.exit()

debug=True

params=msgpack.packb(['console.create',token])
client.request("POST","/api/",params, headers)
response = client.getresponse()
if response.status == 200:
	resdata=msgpack.unpackb(response.read())
	print(resdata) #{'busy': False, 'prompt': 'msf > ', 'id': '12'}
	consoleid=resdata['id']
else:
	print("Console.create failed")
	sys.exit()


params=msgpack.packb(['console.write',token,consoleid,''])
client.request("POST","/api/",params, headers)
response = client.getresponse()
if response.status==200:
	print (msgpack.unpackb(response.read()))
else:
	print("Console.write failed")
	sys.exit()

params=msgpack.packb(['console.read',token,consoleid])
client.request("POST","/api/",params, headers)
response = client.getresponse()
if response.status == 200:
	resdata=msgpack.unpackb(response.read())
	print(resdata['data'])
else:
	print("Console.read failed")
	sys.exit()


#search for rpc modules
command=b"search rpc \r\n"
if debug:
	print("sending " + command )

params=msgpack.packb(['console.write',token,consoleid,command])
client.request("POST","/api/",params, headers)
response = client.getresponse()
if response.status == 200:
	print (msgpack.unpackb(response.read()))
else:
	print("Console.write failed")
	sys.exit()	


#wait for results
while True:
	params=msgpack.packb(['console.read',token,consoleid])
	client.request("POST","/api/",params, headers)
	response = client.getresponse()
	if response.status == 200:
		resdata=msgpack.unpackb(response.read())
		if resdata['busy']==True and len(resdata['data'])==0:
			#not ready yet...
			print('waiting..')
			time.sleep(2)
		else:
			print(resdata['data'])
			break
	else:
		print("Console.read failed")
		sys.exit()	

#destroy the console
params=msgpack.packb(['console.destroy',token,consoleid])
client.request("POST","/api/",params, headers)
response = client.getresponse()
resdata=msgpack.unpackb(response.read())
if resdata['result'] == 'success':
	print("Console closed")
sys.exit()


Posted at: Sun, 13 Oct 2013 | category: /itsec