librex 0.0.5 → 0.0.6

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 (68) hide show
  1. data/README.md +1 -1
  2. data/Rakefile +13 -0
  3. data/lib/rex.rb +4 -1
  4. data/lib/rex/assembly/nasm.rb +4 -0
  5. data/lib/rex/compat.rb +31 -1
  6. data/lib/rex/encoder/alpha2/generic.rb +11 -10
  7. data/lib/rex/exceptions.rb +1 -1
  8. data/lib/rex/exploitation/egghunter.rb +27 -0
  9. data/lib/rex/file.rb +13 -0
  10. data/lib/rex/io/stream.rb +9 -1
  11. data/lib/rex/io/stream_abstraction.rb +18 -7
  12. data/lib/rex/io/stream_server.rb +2 -2
  13. data/lib/rex/job_container.rb +1 -1
  14. data/lib/rex/mime/message.rb +5 -4
  15. data/lib/rex/ole.rb +83 -6
  16. data/lib/rex/ole/propset.rb +144 -0
  17. data/lib/rex/parser/ip360_aspl_xml.rb +102 -0
  18. data/lib/rex/parser/ip360_xml.rb +93 -0
  19. data/lib/rex/parser/nessus_xml.rb +118 -0
  20. data/lib/rex/parser/netsparker_xml.rb +94 -0
  21. data/lib/rex/parser/retina_xml.rb +109 -0
  22. data/lib/rex/post/meterpreter/channel.rb +15 -8
  23. data/lib/rex/post/meterpreter/client.rb +32 -3
  24. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +1 -1
  25. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +14 -5
  26. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +1 -1
  27. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +3 -3
  28. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +1 -1
  29. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +1 -1
  30. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +5 -0
  31. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +16 -8
  32. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -7
  33. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +1 -1
  34. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +15 -4
  35. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +13 -7
  36. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +20 -0
  37. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +63 -0
  38. data/lib/rex/post/meterpreter/packet_dispatcher.rb +18 -7
  39. data/lib/rex/post/meterpreter/packet_response_waiter.rb +10 -17
  40. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +1 -1
  41. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +16 -6
  42. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +4 -5
  43. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +2 -0
  44. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +4 -2
  45. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +157 -0
  46. data/lib/rex/proto/dhcp/server.rb +8 -4
  47. data/lib/rex/proto/http/client.rb +19 -45
  48. data/lib/rex/proto/http/packet.rb +8 -5
  49. data/lib/rex/proto/http/response.rb +8 -3
  50. data/lib/rex/proto/http/server.rb +1 -1
  51. data/lib/rex/proto/proxy/socks4a.rb +4 -4
  52. data/lib/rex/proto/rfb.rb +19 -0
  53. data/lib/rex/proto/rfb.rb.ut.rb +37 -0
  54. data/lib/rex/proto/rfb/cipher.rb +78 -0
  55. data/lib/rex/proto/rfb/client.rb +207 -0
  56. data/lib/rex/proto/rfb/constants.rb +52 -0
  57. data/lib/rex/proto/tftp/server.rb +20 -17
  58. data/lib/rex/services/local_relay.rb +1 -1
  59. data/lib/rex/socket.rb +69 -10
  60. data/lib/rex/socket/comm/local.rb +7 -4
  61. data/lib/rex/socket/range_walker.rb +14 -1
  62. data/lib/rex/text.rb +28 -3
  63. data/lib/rex/text.rb.ut.rb +14 -0
  64. data/lib/rex/thread_factory.rb +42 -0
  65. data/lib/rex/ui/text/input/buffer.rb +1 -1
  66. data/lib/rex/zip/archive.rb +74 -9
  67. data/lib/rex/zip/entry.rb +6 -1
  68. metadata +22 -7
@@ -141,7 +141,7 @@ class LocalRelay
141
141
  #
142
142
  def start
143
143
  if (!self.relay_thread)
144
- self.relay_thread = Thread.new {
144
+ self.relay_thread = Rex::ThreadFactory.spawn("LocalRelay", false) {
145
145
  begin
146
146
  monitor_relays
147
147
  rescue ::Exception
@@ -138,9 +138,31 @@ module Socket
138
138
  # These calls can be quite slow. This also fixes an issue with the
139
139
  # Resolv.getaddress() call being non-functional on Ruby 1.9.1 (Win32).
140
140
  #
141
- def self.getaddress(addr)
141
+ def self.getaddress(addr, accept_ipv6 = true)
142
142
  begin
143
- dotted_ip?(addr) ? addr : self.addr_ntoa( ::Socket.gethostbyname(addr)[3] )
143
+
144
+ if dotted_ip?(addr)
145
+ return addr
146
+ end
147
+
148
+ res = ::Socket.gethostbyname(addr)
149
+ return nil if not res
150
+
151
+ # Shift the first three elements out
152
+ rname = res.shift
153
+ ralias = res.shift
154
+ rtype = res.shift
155
+
156
+ # Reject IPv6 addresses if we don't accept them
157
+ if not accept_ipv6
158
+ res.reject!{|nbo| nbo.length != 4}
159
+ end
160
+
161
+ # Make sure we have at least one name
162
+ return nil if res.length == 0
163
+
164
+ # Return the first address of the result
165
+ self.addr_ntoa( res[0] )
144
166
  rescue ::ArgumentError # Win32 bug
145
167
  nil
146
168
  end
@@ -441,7 +463,14 @@ module Socket
441
463
  #
442
464
  ##
443
465
 
444
- def self.source_address(dest='50.50.50.50', comm = ::Rex::Socket::Comm::Local)
466
+ #
467
+ # This method does NOT send any traffic to the destination, instead, it uses a
468
+ # "bound" UDP socket to determine what source address we would use to
469
+ # communicate with the specified destination. The destination defaults to
470
+ # Google's DNS server to make the standard behavior determine which IP
471
+ # we would use to communicate with the internet.
472
+ #
473
+ def self.source_address(dest='8.8.8.8', comm = ::Rex::Socket::Comm::Local)
445
474
  begin
446
475
  s = self.create_udp(
447
476
  'PeerHost' => dest,
@@ -450,11 +479,32 @@ module Socket
450
479
  )
451
480
  r = s.getsockname[1]
452
481
  s.close
453
- return r
482
+
483
+ # Trim off the trailing interface ID for link-local IPv6
484
+ return r.split('%').first
454
485
  rescue ::Exception
455
486
  return '127.0.0.1'
456
487
  end
457
488
  end
489
+
490
+ #
491
+ # Identifies the link-local address of a given interface (if IPv6 is enabled)
492
+ #
493
+ def self.ipv6_link_address(intf)
494
+ r = source_address("FF02::1%#{intf}")
495
+ return if not (r and r =~ /^fe80/i)
496
+ r
497
+ end
498
+
499
+ #
500
+ # Identifies the mac address of a given interface (if IPv6 is enabled)
501
+ #
502
+ def self.ipv6_mac(intf)
503
+ r = ipv6_link_address(intf)
504
+ return if not r
505
+ raw = addr_aton(r)[-8, 8]
506
+ (raw[0,3] + raw[5,3]).unpack("C*").map{|c| "%.2x" % c}.join(":")
507
+ end
458
508
 
459
509
  #
460
510
  # Create a TCP socket pair.
@@ -463,6 +513,8 @@ module Socket
463
513
  # on Windows where ::Socket.pair is not implemented.
464
514
  # Note: OpenSSL requires native ruby sockets for its io.
465
515
  #
516
+ # Note: Even though sub-threads are smashing the parent threads local, there
517
+ # is no concurrent use of the same locals and this is safe.
466
518
  def self.tcp_socket_pair
467
519
  lsock = nil
468
520
  rsock = nil
@@ -471,18 +523,25 @@ module Socket
471
523
  threads = []
472
524
  mutex = ::Mutex.new
473
525
 
474
- threads << ::Thread.new {
526
+ threads << Rex::ThreadFactory.spawn('TcpSocketPair', false) {
475
527
  server = nil
476
528
  mutex.synchronize {
477
- threads << ::Thread.new {
529
+ threads << Rex::ThreadFactory.spawn('TcpSocketPairClient', false) {
478
530
  mutex.synchronize {
479
531
  rsock = ::TCPSocket.new( laddr, lport )
480
532
  }
481
533
  }
482
- server = ::Socket.new( ::Socket::AF_INET, ::Socket::SOCK_STREAM, 0 )
483
- server.bind( ::Socket.sockaddr_in( 0, laddr ) )
484
- lport, caddr = ::Socket.unpack_sockaddr_in( server.getsockname )
485
- server.listen( 1 )
534
+ server = ::TCPServer.new(laddr, 0)
535
+ if (server.getsockname =~ /127\.0\.0\.1:/)
536
+ # JRuby ridiculousness
537
+ caddr, lport = server.getsockname.split(":")
538
+ caddr = caddr[1,caddr.length]
539
+ lport = lport.to_i
540
+ else
541
+ # Sane implementations where Socket#getsockname returns a
542
+ # sockaddr
543
+ lport, caddr = ::Socket.unpack_sockaddr_in( server.getsockname )
544
+ end
486
545
  }
487
546
  lsock, saddr = server.accept
488
547
  server.close
@@ -193,7 +193,7 @@ class Rex::Socket::Comm::Local
193
193
 
194
194
  sock.bind(Rex::Socket.to_sockaddr(param.localhost, param.localport))
195
195
 
196
- rescue Errno::EADDRINUSE
196
+ rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
197
197
  sock.close
198
198
  raise Rex::AddressInUse.new(param.localhost, param.localport), caller
199
199
  end
@@ -206,7 +206,7 @@ class Rex::Socket::Comm::Local
206
206
 
207
207
  # If a server TCP instance is being created...
208
208
  if (param.server?)
209
- sock.listen(32)
209
+ sock.listen(128)
210
210
 
211
211
  if (param.bare? == false)
212
212
  klass = Rex::Socket::TcpServer
@@ -242,10 +242,14 @@ class Rex::Socket::Comm::Local
242
242
  raise ::Errno::ETIMEDOUT
243
243
  end
244
244
 
245
- rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
245
+ rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL
246
246
  sock.close
247
247
  raise Rex::HostUnreachable.new(param.peerhost, param.peerport), caller
248
248
 
249
+ rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
250
+ sock.close
251
+ raise Rex::AddressInUse.new(param.peerhost, param.peerport), caller
252
+
249
253
  rescue Errno::ETIMEDOUT
250
254
  sock.close
251
255
  raise Rex::ConnectionTimeout.new(param.peerhost, param.peerport), caller
@@ -406,4 +410,3 @@ class Rex::Socket::Comm::Local
406
410
  end
407
411
 
408
412
  end
409
-
@@ -150,13 +150,26 @@ class RangeWalker
150
150
  addr = Rex::Socket.addr_atoi(addr)
151
151
  end
152
152
  @ranges.map { |r|
153
- if r.start <= addr and addr <= r.stop
153
+ if r[0] <= addr and addr <= r[1]
154
154
  return true
155
155
  end
156
156
  }
157
157
  return false
158
158
  end
159
159
 
160
+ #
161
+ # Returns true if this RangeWalker includes all of the addresses in the
162
+ # given RangeWalker
163
+ #
164
+ def include_range?(range_walker)
165
+ range_walker.ranges.all? do |start, stop|
166
+ ranges.any? do |self_start, self_stop|
167
+ r = (self_start..self_stop)
168
+ r.include?(start) and r.include?(stop)
169
+ end
170
+ end
171
+ end
172
+
160
173
  #
161
174
  # Calls the given block with each address
162
175
  #
@@ -760,13 +760,15 @@ module Text
760
760
  # Make sure there's something in sets even if we were given an explicit nil
761
761
  sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
762
762
 
763
+ # Return stupid uses
764
+ return "" if length.to_i < 1
765
+ return sets[0][0] * length if sets.size == 1 and sets[0].size == 1
766
+
763
767
  sets.length.times { offsets << 0 }
764
768
 
765
769
  until buf.length >= length
766
770
  begin
767
771
  buf << converge_sets(sets, 0, offsets, length)
768
- rescue RuntimeError
769
- break
770
772
  end
771
773
  end
772
774
 
@@ -778,6 +780,28 @@ module Text
778
780
  buf[0,length]
779
781
  end
780
782
 
783
+ # Step through an arbitrary number of sets of bytes to build up a findable pattern.
784
+ # This is mostly useful for experimentially determining offset lengths into memory
785
+ # structures. Note that the supplied sets should never contain duplicate bytes, or
786
+ # else it can become impossible to measure the offset accurately.
787
+ def self.patt2(len, sets = nil)
788
+ buf = ""
789
+ counter = []
790
+ sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
791
+ len ||= len.to_i
792
+ return "" if len.zero?
793
+
794
+ sets = sets.map {|a| a.split(//)}
795
+ sets.size.times { counter << 0}
796
+ 0.upto(len-1) do |i|
797
+ setnum = i % sets.size
798
+
799
+ puts counter.inspect
800
+ end
801
+
802
+ return buf
803
+ end
804
+
781
805
  #
782
806
  # Calculate the offset to a pattern
783
807
  #
@@ -1029,8 +1053,9 @@ protected
1029
1053
  # If we reached the point where the idx fell below zero, then that
1030
1054
  # means we've reached the maximum threshold for permutations.
1031
1055
  if (idx < 0)
1032
- raise RuntimeError, "Maximum permutations reached"
1056
+ return buf
1033
1057
  end
1058
+
1034
1059
  end
1035
1060
 
1036
1061
  buf
@@ -7,6 +7,20 @@ require 'rex/text'
7
7
  require 'rex/exceptions'
8
8
  class Rex::Text::UnitTest < Test::Unit::TestCase
9
9
 
10
+ def test_pattern_create
11
+ set1 = %w{AB ab 12}
12
+ assert_equal 'Aa1Aa2', Rex::Text.pattern_create(6,set1)
13
+ set2 = %w{ABC abc 123}
14
+ assert_equal 'Aa1Aa2Aa3Ab1Ab2Ab3', Rex::Text.pattern_create(18,set2)
15
+ assert_equal 'Zz8Zz9', Rex::Text.pattern_create(20280)[-6,6] # Bug #2952
16
+ end
17
+
18
+ def test_pattern_create_silly
19
+ assert_equal "", Rex::Text.pattern_create(nil)
20
+ assert_equal "", Rex::Text.pattern_create(0)
21
+ assert_equal 'AAAAAAAAA', Rex::Text.pattern_create(9,['A'])
22
+ end
23
+
10
24
  def test_uri_encode
11
25
  srand(0)
12
26
  assert_equal('A1%21', Rex::Text.uri_encode('A1!'), 'uri encode')
@@ -0,0 +1,42 @@
1
+ module Rex
2
+
3
+ ###
4
+ #
5
+ # This class provides a wrapper around Thread.new that can provide
6
+ # additional features if a corresponding thread provider is set.
7
+ #
8
+ ###
9
+
10
+ class ThreadFactory
11
+
12
+ @@provider = nil
13
+
14
+ def self.provider=(val)
15
+ @@provider = val
16
+ end
17
+
18
+ def self.spawn(name, crit, *args, &block)
19
+ if @@provider
20
+ if block
21
+ return @@provider.spawn(name, crit, *args){ |*args_copy| block.call(*args_copy) }
22
+ else
23
+ return @@provider.spawn(name, crit, *args)
24
+ end
25
+ else
26
+ t = nil
27
+ if block
28
+ t = ::Thread.new(*args){ |*args_copy| block.call(*args_copy) }
29
+ else
30
+ t = ::Thread.new(*args)
31
+ end
32
+ t[:tm_name] = name
33
+ t[:tm_crit] = crit
34
+ t[:tm_time] = Time.now
35
+ t[:tm_call] = caller
36
+ return t
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ end
@@ -72,4 +72,4 @@ end
72
72
 
73
73
  end
74
74
  end
75
- end
75
+ end
@@ -1,5 +1,5 @@
1
1
  ##
2
- # $Id: archive.rb 10073 2010-08-20 07:01:23Z egypt $
2
+ # $Id: archive.rb 11175 2010-11-30 07:10:57Z egypt $
3
3
  ##
4
4
 
5
5
  module Rex
@@ -86,6 +86,10 @@ class Archive
86
86
  ret
87
87
  end
88
88
 
89
+ def inspect
90
+ "#<#{self.class} entries = [#{@entries.map{|e| e.name}.join(",")}]>"
91
+ end
92
+
89
93
  end
90
94
 
91
95
  class Jar < Archive
@@ -93,17 +97,24 @@ class Jar < Archive
93
97
 
94
98
  def build_manifest(opts={})
95
99
  main_class = opts[:main_class] || nil
96
- skip = opts[:skip] || /^$/
100
+ existing_manifest = nil
97
101
 
98
- @manifest = ''
99
-
100
- @manifest = "Main-Class: #{main_class}\n\n" if main_class
102
+ @manifest = "Manifest-Version: 1.0\r\n"
103
+ @manifest << "Main-Class: #{main_class}\r\n" if main_class
104
+ @manifest << "\r\n"
101
105
  @entries.each { |e|
102
- next if e.name =~ skip
103
- @manifest << "Name: #{e.name}\n\n"
106
+ existing_manifest = e if e.name == "META-INF/MANIFEST.MF"
107
+ next unless e.name =~ /\.class$/
108
+ @manifest << "Name: #{e.name}\r\n"
109
+ #@manifest << "SHA1-Digest: #{Digest::SHA1.base64digest(e.data)}\r\n"
110
+ @manifest << "\r\n"
104
111
  }
105
- add_file("META-INF/", '')
106
- add_file("META-INF/MANIFEST.MF", @manifest)
112
+ if existing_manifest
113
+ existing_manifest.data = @manifest
114
+ else
115
+ add_file("META-INF/", '')
116
+ add_file("META-INF/MANIFEST.MF", @manifest)
117
+ end
107
118
  end
108
119
 
109
120
  def to_s
@@ -113,6 +124,60 @@ class Jar < Archive
113
124
  def length
114
125
  pack.length
115
126
  end
127
+
128
+ #
129
+ # Add multiple files from an array
130
+ #
131
+ # +files+ should be structured like so:
132
+ # [
133
+ # [ "path", "to", "file1" ],
134
+ # [ "path", "to", "file2" ]
135
+ # ]
136
+ # and +path+ should be the location on the file system to find the files to
137
+ # add. +base_dir+ will be prepended to the path inside the jar.
138
+ #
139
+ # Example:
140
+ # <code>
141
+ # war = Rex::Zip::Jar.new
142
+ # war.add_file("WEB-INF/", '')
143
+ # war.add_file("WEB-INF/", "web.xml", web_xml)
144
+ # war.add_file("WEB-INF/classes/", '')
145
+ # files = [
146
+ # [ "servlet", "examples", "HelloWorld.class" ],
147
+ # [ "Foo.class" ],
148
+ # [ "servlet", "Bar.class" ],
149
+ # ]
150
+ # war.add_files(files, "./class_files/", "WEB-INF/classes/")
151
+ # </code>
152
+ #
153
+ # The above code would create a jar with the following structure from files
154
+ # found in ./class_files/ :
155
+ #
156
+ # +- WEB-INF/
157
+ # +- web.xml
158
+ # +- classes/
159
+ # +- Foo.class
160
+ # +- servlet/
161
+ # +- Bar.class
162
+ # +- examples/
163
+ # +- HelloWorld.class
164
+ #
165
+ def add_files(files, path, base_dir="")
166
+ files.each do |file|
167
+ # Add all of the subdirectories if they don't already exist
168
+ 1.upto(file.length - 1) do |idx|
169
+ full = base_dir + file[0,idx].join("/") + "/"
170
+ if !(entries.map{|e|e.name}.include?(full))
171
+ add_file(full, '')
172
+ end
173
+ end
174
+ # Now add the actual file, grabbing data from the filesystem
175
+ fd = File.open(File.join( path, file ), "rb")
176
+ data = fd.read(fd.stat.size)
177
+ fd.close
178
+ add_file(base_dir + file.join("/"), data)
179
+ end
180
+ end
116
181
  end
117
182
 
118
183
  end
@@ -1,5 +1,5 @@
1
1
  ##
2
- # $Id: entry.rb 10056 2010-08-19 17:04:42Z egypt $
2
+ # $Id: entry.rb 11173 2010-11-30 03:52:46Z egypt $
3
3
  ##
4
4
 
5
5
  module Rex
@@ -8,6 +8,7 @@ module Zip
8
8
  class Entry
9
9
 
10
10
  attr_accessor :name, :flags, :info, :xtra, :comment, :attrs
11
+ attr_reader :data
11
12
 
12
13
  def initialize(fname, data, compmeth, timestamp=nil, attrs=nil, xtra=nil, comment=nil)
13
14
  @name = fname
@@ -32,6 +33,10 @@ class Entry
32
33
  @compdata ||= ''
33
34
  end
34
35
 
36
+ def data=(val)
37
+ @data = val
38
+ compress
39
+ end
35
40
 
36
41
  def compress
37
42
  @crc = Zlib.crc32(@data, 0)