#!/usr/bin/env ruby

msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
$:.unshift(File.join(File.dirname(msfbase), 'lib'))

require 'rex'
require 'msf/ui'
require 'msf/base'

#
# Dump the list of payloads
#
def dump_payloads
	tbl = Rex::Ui::Text::Table.new(
		'Indent'  => 4,
		'Header'  => "Framework Payloads (#{$framework.stats.num_payloads} total)",
		'Columns' => 
			[
				"Name",
				"Description"
			])

	$framework.payloads.each_module { |name, mod|
		tbl << [ name, mod.new.description ]
	}

	"\n" + tbl.to_s + "\n"
end

# Initialize the simplified framework instance.
$framework = Msf::Simple::Framework.create

if (ARGV.length <= 1)
	puts "\n" + "    Usage: #{$0} <payload> [var=val] <S[ummary]|C|P[erl]|R[aw]|J[avascript]|e[X]ecutable>\n"
	puts dump_payloads
	exit
end

# Get the payload name we'll be using
payload_name = ARGV.shift

# Process special var/val pairs...
Msf::Ui::Common.process_cli_arguments($framework, ARGV)

# Create the payload instance
payload = $framework.payloads.create(payload_name)

if (payload == nil)
	puts "Invalid payload: #{payload_name}"
	exit
end

# Evalulate the command
cmd = ARGV.pop.downcase

# Populate the framework datastore
options = ARGV.join(',')

if (cmd =~ /^(p|r|c|j|x)/)
	fmt = 'perl' if (cmd =~ /^p/)
	fmt = 'raw' if (cmd =~ /^(r|x)/)
	fmt = 'c' if (cmd == 'c')
	fmt = 'js_be' if (cmd =~ /^j/ and Rex::Arch.endian(payload.arch) == ENDIAN_BIG)
	fmt = 'js_le' if (cmd =~ /^j/ and ! fmt)
		
	begin
		buf = payload.generate_simple(
				'Format'    => fmt,
				'OptionStr' => options)
	rescue
		puts "Error generating payload: #{$!}"
		exit
	end
	
	if (cmd =~ /^x/)
		note = 
			"Created by msfpayload (http://www.metasploit.com).\n" +
			"Payload: " + payload.refname + "\n" +
			" Length: " + buf.length.to_s + "\n" +
			"Options: " + options + "\n"
			
		arch = payload.arch
		plat = payload.platform.platforms

		# Automatically prepend stack adjustment
		buf = Rex::Arch.adjust_stack_pointer('x86', -3500) + buf
		
		if (plat.index(Msf::Module::Platform::Windows) and arch.index("x86"))
			buf = Rex::Text.to_win32pe(buf, note)
			$stderr.puts(note)
			$stdout.write(buf)
			exit(0)
		end
		
		$stderr.puts "No executable format support for this arch/platform"
		exit(-1)
	end
	
	puts buf
	
elsif (cmd =~ /^s/)
	puts Msf::Serializer::ReadableText.dump_module(payload)
end
