#!/usr/bin/env ruby

msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
$:.unshift(File.join(File.dirname(msfbase), 'lib'))
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_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|b)/)
	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)
	fmt = 'java'  if (cmd =~ /^b/)
	enc = options['ENCODER']
		
	begin
		buf = payload.generate_simple(
				'Format'    => fmt,
				'OptionStr' => options,
				'Encoder'   => enc)
	rescue
		puts "Error generating payload: #{$!}"
		exit
	end
			
	$stdout.binmode
	
	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


		
		if (arch.index(ARCH_X86))

			# Automatically prepend stack adjustment
			buf = Rex::Arch.adjust_stack_pointer('x86', -3500) + buf

			if (plat.index(Msf::Module::Platform::Windows))
				buf = Rex::Text.to_win32pe(buf, note)
				$stderr.puts(note)
				$stdout.write(buf)
				exit(0)
			end

			if (plat.index(Msf::Module::Platform::Linux))
				buf = Rex::Text.to_linux_x86_elf(buf, note)
				$stderr.puts(note)
				$stdout.write(buf)
				exit(0)
			end
			
			if(plat.index(Msf::Module::Platform::OSX))
				buf = Rex::Text.to_osx_x86_macho(buf, note)
				$stderr.puts(note)
				$stdout.write(buf)
				exit(0)			
			end						
		end

		if(arch.index(ARCH_ARMLE))
			if(plat.index(Msf::Module::Platform::OSX))
				buf = Rex::Text.to_osx_arm_macho(buf, note)
				$stderr.puts(note)
				$stdout.write(buf)
				exit(0)			
			end
		end

		if(arch.index(ARCH_PPC))
			if(plat.index(Msf::Module::Platform::OSX))
				buf = Rex::Text.to_osx_ppc_macho(buf, note)
				$stderr.puts(note)
				$stdout.write(buf)
				exit(0)			
			end
		end
						
		$stderr.puts "No executable format support for this arch/platform"
		exit(-1)
	end
	
	$stdout.puts(buf)
	
elsif (cmd =~ /^(s|o)/)
	puts Msf::Serializer::ReadableText.dump_module(payload)
end
