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.
@@ -1,10 +1,13 @@
1
1
  ##
2
- # $Id: entry.rb 11173 2010-11-30 03:52:46Z egypt $
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
 
@@ -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.32
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-13 00:00:00 -05:00
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 12612
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