librex 0.0.32 → 0.0.33
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.
- data/README.markdown +1 -1
- data/lib/rex/exploitation/egghunter.rb +90 -1
- data/lib/rex/exploitation/javascriptosdetect.rb +9 -1
- data/lib/rex/io/ring_buffer.rb.ut.rb +134 -0
- data/lib/rex/io/stream_server.rb +11 -2
- data/lib/rex/parser/nessus_xml.rb +4 -2
- data/lib/rex/parser/nexpose_xml.rb +45 -15
- data/lib/rex/parser/nmap_nokogiri.rb +385 -0
- data/lib/rex/parser/nmap_xml.rb +71 -51
- data/lib/rex/parser/nokogiri_doc_mixin.rb +99 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +1 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb +4 -128
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +146 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb +63 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +8 -2
- data/lib/rex/proto/http/handler/proc.rb +1 -1
- data/lib/rex/proto/http/server.rb +15 -10
- data/lib/rex/socket/parameters.rb +16 -0
- data/lib/rex/socket/ssl_tcp_server.rb +47 -38
- data/lib/rex/ui/text/dispatcher_shell.rb +49 -29
- data/lib/rex/zip.rb +3 -0
- data/lib/rex/zip/archive.rb +13 -89
- data/lib/rex/zip/entry.rb +11 -1
- data/lib/rex/zip/jar.rb +224 -0
- metadata +9 -3
data/lib/rex/zip/entry.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
##
|
2
|
-
# $Id: entry.rb
|
2
|
+
# $Id: entry.rb 12718 2011-05-25 16:45:20Z egypt $
|
3
3
|
##
|
4
4
|
|
5
5
|
module Rex
|
6
6
|
module Zip
|
7
7
|
|
8
|
+
#
|
9
|
+
# An Entry represents a logical file or directory to be stored in an Archive
|
10
|
+
#
|
8
11
|
class Entry
|
9
12
|
|
10
13
|
attr_accessor :name, :flags, :info, :xtra, :comment, :attrs
|
@@ -38,6 +41,10 @@ class Entry
|
|
38
41
|
compress
|
39
42
|
end
|
40
43
|
|
44
|
+
#
|
45
|
+
# Compress the #data and store it for later use. If this entry's compression method
|
46
|
+
# produces a larger blob than the original data, the method is changed to CM_STORE.
|
47
|
+
#
|
41
48
|
def compress
|
42
49
|
@crc = Zlib.crc32(@data, 0)
|
43
50
|
case @flags.compmeth
|
@@ -73,6 +80,9 @@ class Entry
|
|
73
80
|
end
|
74
81
|
|
75
82
|
|
83
|
+
#
|
84
|
+
# Return the compressed data in a format suitable for adding to an Archive
|
85
|
+
#
|
76
86
|
def pack
|
77
87
|
ret = ''
|
78
88
|
|
data/lib/rex/zip/jar.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
|
2
|
+
require 'rex/zip/archive'
|
3
|
+
|
4
|
+
module Rex
|
5
|
+
module Zip
|
6
|
+
|
7
|
+
#
|
8
|
+
# A Jar is a zip archive containing Java class files and a MANIFEST.MF listing
|
9
|
+
# those classes. Several variations exist based on the same idea of class
|
10
|
+
# files inside a zip, most notably:
|
11
|
+
# - WAR files store XML files, Java classes, JSPs and other stuff for
|
12
|
+
# servlet-based webservers (e.g.: Tomcat and Glassfish)
|
13
|
+
# - APK files are Android Package files
|
14
|
+
#
|
15
|
+
class Jar < Archive
|
16
|
+
attr_accessor :manifest
|
17
|
+
|
18
|
+
#
|
19
|
+
# Create a MANIFEST.MF file based on the current Archive#entries.
|
20
|
+
#
|
21
|
+
# See http://download.oracle.com/javase/1.4.2/docs/guide/jar/jar.html for
|
22
|
+
# some explanation of the format.
|
23
|
+
#
|
24
|
+
# Example MANIFEST.MF
|
25
|
+
# Manifest-Version: 1.0
|
26
|
+
# Main-Class: metasploit.Payload
|
27
|
+
#
|
28
|
+
# Name: metasploit.dat
|
29
|
+
# SHA1-Digest: WJ7cUVYUryLKfQFmH80/ADfKmwM=
|
30
|
+
#
|
31
|
+
# Name: metasploit/Payload.class
|
32
|
+
# SHA1-Digest: KbAIMttBcLp1zCewA2ERYkcnRU8=
|
33
|
+
#
|
34
|
+
# The SHA1-Digest lines are optional unless the jar is signed (see #sign).
|
35
|
+
#
|
36
|
+
def build_manifest(opts={})
|
37
|
+
main_class = opts[:main_class] || nil
|
38
|
+
existing_manifest = nil
|
39
|
+
|
40
|
+
@manifest = "Manifest-Version: 1.0\r\n"
|
41
|
+
@manifest << "Main-Class: #{main_class}\r\n" if main_class
|
42
|
+
@manifest << "\r\n"
|
43
|
+
@entries.each { |e|
|
44
|
+
next if e.name =~ %r|/$|
|
45
|
+
if e.name == "META-INF/MANIFEST.MF"
|
46
|
+
existing_manifest = e
|
47
|
+
next
|
48
|
+
end
|
49
|
+
#next unless e.name =~ /\.class$/
|
50
|
+
@manifest << "Name: #{e.name}\r\n"
|
51
|
+
#@manifest << "SHA1-Digest: #{Digest::SHA1.base64digest(e.data)}\r\n"
|
52
|
+
@manifest << "\r\n"
|
53
|
+
}
|
54
|
+
if existing_manifest
|
55
|
+
existing_manifest.data = @manifest
|
56
|
+
else
|
57
|
+
add_file("META-INF/", '')
|
58
|
+
add_file("META-INF/MANIFEST.MF", @manifest)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
pack
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Length of the *compressed* blob
|
68
|
+
#
|
69
|
+
def length
|
70
|
+
pack.length
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Add multiple files from an array
|
75
|
+
#
|
76
|
+
# +files+ should be structured like so:
|
77
|
+
# [
|
78
|
+
# [ "path", "to", "file1" ],
|
79
|
+
# [ "path", "to", "file2" ]
|
80
|
+
# ]
|
81
|
+
# and +path+ should be the location on the file system to find the files to
|
82
|
+
# add. +base_dir+ will be prepended to the path inside the jar.
|
83
|
+
#
|
84
|
+
# Example:
|
85
|
+
# war = Rex::Zip::Jar.new
|
86
|
+
# war.add_file("WEB-INF/", '')
|
87
|
+
# war.add_file("WEB-INF/web.xml", web_xml)
|
88
|
+
# war.add_file("WEB-INF/classes/", '')
|
89
|
+
# files = [
|
90
|
+
# [ "servlet", "examples", "HelloWorld.class" ],
|
91
|
+
# [ "Foo.class" ],
|
92
|
+
# [ "servlet", "Bar.class" ],
|
93
|
+
# ]
|
94
|
+
# war.add_files(files, "./class_files/", "WEB-INF/classes/")
|
95
|
+
#
|
96
|
+
# The above code would create a jar with the following structure from files
|
97
|
+
# found in ./class_files/ :
|
98
|
+
#
|
99
|
+
# +- WEB-INF/
|
100
|
+
# +- web.xml
|
101
|
+
# +- classes/
|
102
|
+
# +- Foo.class
|
103
|
+
# +- servlet/
|
104
|
+
# +- Bar.class
|
105
|
+
# +- examples/
|
106
|
+
# +- HelloWorld.class
|
107
|
+
#
|
108
|
+
def add_files(files, path, base_dir="")
|
109
|
+
files.each do |file|
|
110
|
+
# Add all of the subdirectories if they don't already exist
|
111
|
+
1.upto(file.length - 1) do |idx|
|
112
|
+
full = base_dir + file[0,idx].join("/") + "/"
|
113
|
+
if !(entries.map{|e|e.name}.include?(full))
|
114
|
+
add_file(full, '')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
# Now add the actual file, grabbing data from the filesystem
|
118
|
+
fd = File.open(File.join( path, file ), "rb")
|
119
|
+
data = fd.read(fd.stat.size)
|
120
|
+
fd.close
|
121
|
+
add_file(base_dir + file.join("/"), data)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Add a signature to this jar given a +key+ and a +cert+. +cert+ should be
|
127
|
+
# an instance of OpenSSL::X509::Certificate and +key+ is expected to be an
|
128
|
+
# instance of one of OpenSSL::PKey::DSA or OpenSSL::PKey::RSA.
|
129
|
+
#
|
130
|
+
# This method aims to create signature files compatible with the jarsigner
|
131
|
+
# tool destributed with the JDK and any JVM should accept the resulting
|
132
|
+
# jar.
|
133
|
+
#
|
134
|
+
# === Signature contents
|
135
|
+
# Modifies the META-INF/MANIFEST.MF entry adding SHA1-Digest attributes in
|
136
|
+
# each Name section. The signature consists of two files, a .SF and a .DSA
|
137
|
+
# (or .RSA if signing with an RSA key). The .SF file is similar to the
|
138
|
+
# manifest with Name sections but the SHA1-Digest is not optional. The
|
139
|
+
# difference is in what gets hashed for the SHA1-Digest line -- in the
|
140
|
+
# manifest, it is the file's contents, in the .SF, it is the file's section
|
141
|
+
# in the manifest (including trailing newline!). The .DSA/.RSA file is a
|
142
|
+
# PKCS7 signature of the .SF file contents.
|
143
|
+
#
|
144
|
+
# === Links
|
145
|
+
# A short description of the format:
|
146
|
+
# http://download.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Signed%20JAR%20File
|
147
|
+
#
|
148
|
+
# Some info on importing a private key into a keystore which is not
|
149
|
+
# directly supported by keytool for some unfathomable reason
|
150
|
+
# http://www.agentbob.info/agentbob/79-AB.html
|
151
|
+
#
|
152
|
+
def sign(key, cert)
|
153
|
+
m = self.entries.find { |e| e.name == "META-INF/MANIFEST.MF" }
|
154
|
+
raise RuntimeError.new("Jar has no manifest") unless m
|
155
|
+
new_manifest = ''
|
156
|
+
sigdata = "Signature-Version: 1.0\r\n"
|
157
|
+
sigdata << "Created-By: 1.6.0_18 (Sun Microsystems Inc.)\r\n"
|
158
|
+
sigdata << "\r\n"
|
159
|
+
|
160
|
+
# Grab the sections of the manifest
|
161
|
+
files = m.data.split(/\r?\n\r?\n/)
|
162
|
+
if files[0] =~ /Manifest-Version/
|
163
|
+
# keep the header as is
|
164
|
+
new_manifest << files[0]
|
165
|
+
new_manifest << "\r\n\r\n"
|
166
|
+
files = files[1,files.length]
|
167
|
+
end
|
168
|
+
|
169
|
+
# The file sections should now look like this:
|
170
|
+
# "Name: metasploit/Payload.class\r\nSHA1-Digest: KbAIMttBcLp1zCewA2ERYkcnRU8=\r\n\r\n"
|
171
|
+
files.each do |f|
|
172
|
+
next unless f =~ /Name: (.*)/
|
173
|
+
name = $1
|
174
|
+
e = self.entries.find { |e| e.name == name }
|
175
|
+
if e
|
176
|
+
digest = OpenSSL::Digest::SHA1.digest(e.data)
|
177
|
+
manifest_section = "Name: #{name}\r\n"
|
178
|
+
manifest_section << "SHA1-Digest: #{[digest].pack('m').strip}\r\n"
|
179
|
+
manifest_section << "\r\n"
|
180
|
+
|
181
|
+
manifest_digest = OpenSSL::Digest::SHA1.digest(manifest_section)
|
182
|
+
|
183
|
+
sigdata << "Name: #{name}\r\n"
|
184
|
+
sigdata << "SHA1-Digest: #{[manifest_digest].pack('m')}\r\n"
|
185
|
+
new_manifest << manifest_section
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Now overwrite with the new manifest
|
190
|
+
m.data = new_manifest
|
191
|
+
|
192
|
+
flags = 0
|
193
|
+
flags |= OpenSSL::PKCS7::BINARY
|
194
|
+
flags |= OpenSSL::PKCS7::DETACHED
|
195
|
+
# SMIME and ATTRs are technically valid in the signature but they both
|
196
|
+
# screw up the java verifier, so don't include them.
|
197
|
+
flags |= OpenSSL::PKCS7::NOSMIMECAP
|
198
|
+
flags |= OpenSSL::PKCS7::NOATTR
|
199
|
+
|
200
|
+
signature = OpenSSL::PKCS7.sign(cert, key, sigdata, [cert], flags)
|
201
|
+
sigalg = case key
|
202
|
+
when OpenSSL::PKey::RSA; "RSA"
|
203
|
+
when OpenSSL::PKey::DSA; "DSA"
|
204
|
+
# Don't really know what to do if it's not DSA or RSA. Can
|
205
|
+
# OpenSSL::PKCS7 actually sign stuff with it in that case?
|
206
|
+
# Regardless, the java spec says signatures can only be RSA, DSA,
|
207
|
+
# or PGP, so just assume it's PGP and hope for the best
|
208
|
+
else; "PGP"
|
209
|
+
end
|
210
|
+
|
211
|
+
# SIGNFILE is the default name in documentation. MYKEY is probably
|
212
|
+
# more common, though because that's what keytool defaults to. We can
|
213
|
+
# probably randomize this with no ill effects.
|
214
|
+
add_file("META-INF/SIGNFILE.SF", sigdata)
|
215
|
+
add_file("META-INF/SIGNFILE.#{sigalg}", signature.to_der)
|
216
|
+
|
217
|
+
return true
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: librex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.33
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Metasploit Development Team
|
@@ -11,11 +11,11 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-05-
|
14
|
+
date: 2011-05-25 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
18
|
-
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision
|
18
|
+
description: Rex provides a variety of classes useful for security testing and exploit development. Based on SVN Revision 12724
|
19
19
|
email:
|
20
20
|
- hdm@metasploit.com
|
21
21
|
- jacob.hammack@hammackj.com
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/rex/io/bidirectional_pipe.rb
|
108
108
|
- lib/rex/io/datagram_abstraction.rb
|
109
109
|
- lib/rex/io/ring_buffer.rb
|
110
|
+
- lib/rex/io/ring_buffer.rb.ut.rb
|
110
111
|
- lib/rex/io/stream.rb
|
111
112
|
- lib/rex/io/stream_abstraction.rb
|
112
113
|
- lib/rex/io/stream_server.rb
|
@@ -159,7 +160,9 @@ files:
|
|
159
160
|
- lib/rex/parser/nessus_xml.rb
|
160
161
|
- lib/rex/parser/netsparker_xml.rb
|
161
162
|
- lib/rex/parser/nexpose_xml.rb
|
163
|
+
- lib/rex/parser/nmap_nokogiri.rb
|
162
164
|
- lib/rex/parser/nmap_xml.rb
|
165
|
+
- lib/rex/parser/nokogiri_doc_mixin.rb
|
163
166
|
- lib/rex/parser/retina_xml.rb
|
164
167
|
- lib/rex/payloads/win32/common.rb
|
165
168
|
- lib/rex/payloads/win32/kernel/common.rb
|
@@ -242,8 +245,10 @@ files:
|
|
242
245
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb
|
243
246
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb
|
244
247
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb
|
248
|
+
- lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb
|
245
249
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb
|
246
250
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb
|
251
|
+
- lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb
|
247
252
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb
|
248
253
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb
|
249
254
|
- lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb
|
@@ -458,6 +463,7 @@ files:
|
|
458
463
|
- lib/rex/zip/archive.rb
|
459
464
|
- lib/rex/zip/blocks.rb
|
460
465
|
- lib/rex/zip/entry.rb
|
466
|
+
- lib/rex/zip/jar.rb
|
461
467
|
- lib/rex/zip/samples/comment.rb
|
462
468
|
- lib/rex/zip/samples/mkwar.rb
|
463
469
|
- lib/rex/zip/samples/mkzip.rb
|