rex-zip 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a95759c12cde8b1cf3896b04ed2ff165bed20426
4
+ data.tar.gz: a0a2731839cbecedf333df2f3d4fac6a21872cb8
5
+ SHA512:
6
+ metadata.gz: 5f7bd388a005d6a785845c24207378652ab6429c95be8d08c78f11fd38e8881d1c271060bd0a73e444cc370802f649870e58870d359f940f37fd59f7fc5ec7f7
7
+ data.tar.gz: f446e3502dbf5a11c75f3bc64de0c8c0962e20cd45d107a9f863005efd1616844e0cc4a85cc5a98e3235b422674c71b1d98813de69310ca5db60ed1a1c7c7da4
Binary file
@@ -0,0 +1,2 @@
1
+ 5�<Γ�� �g�cOƹWT��q���,5�;�d��?!�I)����>�ㆹ�h�e�(���{d=�P�����ax�t3��t0�# Ր۞�s��98o�U6d��jR��ىϔ
2
+ *�͆~�VA���̖�a�Ґ�k�^ ��,��i �|�T�(,��K�_y�����g�Eo�n�
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
@@ -0,0 +1,52 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This Code of Conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting the project maintainers at msfdev@metasploit.com. If
39
+ the incident involves a committer, you may report directly to
40
+ egypt@metasploit.com or todb@metasploit.com.
41
+
42
+ All complaints will be reviewed and investigated and will result in a
43
+ response that is deemed necessary and appropriate to the circumstances.
44
+ Maintainers are obligated to maintain confidentiality with regard to the
45
+ reporter of an incident.
46
+
47
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
48
+ version 1.3.0, available at
49
+ [http://contributor-covenant.org/version/1/3/0/][version]
50
+
51
+ [homepage]: http://contributor-covenant.org
52
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rex-zip.gemspec
4
+ gemspec
5
+
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (C) 2012-2013, Rapid7, Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of Rapid7 LLC nor the names of its contributors
15
+ may be used to endorse or promote products derived from this software
16
+ without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,52 @@
1
+ # Rex::Zip
2
+
3
+ Ruby Exploitation(Rex) Library for creating Zip based archives such as *.zip, *.war, and *.jar files. Ported from the original
4
+ Metasploit Framework code written by jduck.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'rex-zip'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install rex-zip
21
+
22
+ ## Usage
23
+
24
+ Creating a .zip example:
25
+
26
+ ```ruby
27
+ msfbase = __FILE__
28
+ while File.symlink?(msfbase)
29
+ msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
30
+ end
31
+ inc = File.dirname(msfbase) + '/../../..'
32
+ $:.unshift(inc)
33
+
34
+ require 'rex/zip'
35
+
36
+ # example usage
37
+ zip = Rex::Zip::Archive.new
38
+ zip.add_file("elite.txt", "A" * 1024)
39
+ zip.save_to("lolz.zip")
40
+ ```
41
+
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rapid7/rex-zip. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
52
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rex/zip"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,97 @@
1
+ # -*- coding: binary -*-
2
+ #
3
+ # Zip library
4
+ #
5
+ # Written by Joshua J. Drake <jduck [at] metasploit.com>
6
+ #
7
+ # Based on code contributed by bannedit, and the following SPEC:
8
+ # Reference: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
9
+ #
10
+ require 'rex/zip/version'
11
+ require 'zlib'
12
+ require 'rex/text'
13
+
14
+ module Rex
15
+ module Zip
16
+
17
+ # various parts of the structure
18
+ require 'rex/zip/blocks'
19
+
20
+ # an entry in a zip file
21
+ require 'rex/zip/entry'
22
+
23
+ # the archive class
24
+ require 'rex/zip/archive'
25
+
26
+ # a child of Archive, implements Java ARchives for creating java applications
27
+ require 'rex/zip/jar'
28
+
29
+ ZIP_VERSION = 0x14
30
+
31
+ # general purpose bit flag values
32
+ #
33
+ # bit 0
34
+ GPBF_ENCRYPTED = 0x0001
35
+ # bits 1 & 2
36
+ # implode only
37
+ GPBF_IMP_8KDICT = 0x0002
38
+ GPBF_IMP_3SFT = 0x0004
39
+ # deflate only
40
+ GPBF_DEF_MAX = 0x0002
41
+ GPBF_DEF_FAST = 0x0004
42
+ GPBF_DEF_SUPERFAST = 0x0006
43
+ # lzma only
44
+ GPBF_LZMA_EOSUSED = 0x0002
45
+ # bit 3
46
+ GPBF_USE_DATADESC = 0x0008
47
+ # bit 4
48
+ GPBF_DEF_ENHANCED = 0x0010
49
+ # bit 5
50
+ GPBF_COMP_PATHCED = 0x0020
51
+ # bit 6
52
+ GPBF_STRONG_ENC = 0x0040
53
+ # bit 7-10 unused
54
+ # bit 11
55
+ GPBF_STRS_UTF8 = 0x0800
56
+ # bit 12 (reserved)
57
+ # bit 13
58
+ GPBF_DIR_ENCRYPTED = 0x2000
59
+ # bit 14,15 (reserved)
60
+
61
+
62
+ # compression methods
63
+ CM_STORE = 0
64
+ CM_SHRINK = 1
65
+ CM_REDUCE1 = 2
66
+ CM_REDUCE2 = 3
67
+ CM_REDUCE3 = 4
68
+ CM_REDUCE4 = 5
69
+ CM_IMPLODE = 6
70
+ CM_TOKENIZE = 7
71
+ CM_DEFLATE = 8
72
+ CM_DEFLATE64 = 9
73
+ CM_PKWARE_IMPLODE = 10
74
+ # 11 - reserved
75
+ CM_BZIP2 = 12
76
+ # 13 - reserved
77
+ CM_LZMA_EFS = 14
78
+ # 15-17 reserved
79
+ CM_IBM_TERSE = 18
80
+ CM_IBM_LZ77 = 19
81
+ # 20-96 reserved
82
+ CM_WAVPACK = 97
83
+ CM_PPMD_V1R1 = 98
84
+
85
+
86
+ # internal file attributes
87
+ IFA_ASCII = 0x0001
88
+ # bits 2 & 3 are reserved
89
+ IFA_MAINFRAME_MODE = 0x0002 # ??
90
+
91
+
92
+ # external file attributes
93
+ EFA_ISDIR = 0x0001
94
+
95
+ end
96
+ end
97
+
@@ -0,0 +1,130 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+ module Zip
5
+
6
+ #
7
+ # This represents an entire archive.
8
+ #
9
+ class Archive
10
+
11
+ # An array of the Entry objects stored in this Archive.
12
+ attr_reader :entries
13
+
14
+
15
+ def initialize(compmeth=CM_DEFLATE)
16
+ @compmeth = compmeth
17
+ @entries = []
18
+ end
19
+
20
+ #
21
+ # Recursively adds a directory of files into the archive.
22
+ #
23
+ def add_r(dir)
24
+ path = File.dirname(dir)
25
+ Dir[File.join(dir, "**", "**")].each do |file|
26
+ relative = file.sub(/^#{path.chomp('/')}\//, '')
27
+ if File.directory?(file)
28
+ @entries << Entry.new(relative.chomp('/') + '/', '', @compmeth, nil, EFA_ISDIR, nil, nil)
29
+ else
30
+ contents = File.read(file, :mode => 'rb')
31
+ @entries << Entry.new(relative, contents, @compmeth, nil, nil, nil, nil)
32
+ end
33
+ end
34
+ end
35
+
36
+ #
37
+ # Create a new Entry and add it to the archive.
38
+ #
39
+ # If fdata is set, the file is populated with that data
40
+ # from the calling method. If fdata is nil, then the
41
+ # fs is checked for the file. If central_dir_name is set
42
+ # it will be used to spoof the name at the Central Directory
43
+ # at packing time.
44
+ #
45
+ def add_file(fname, fdata=nil, xtra=nil, comment=nil, central_dir_name=nil)
46
+ if (not fdata)
47
+ begin
48
+ st = File.stat(fname)
49
+ rescue
50
+ return nil
51
+ end
52
+
53
+ ts = st.mtime
54
+ if (st.directory?)
55
+ attrs = EFA_ISDIR
56
+ fdata = ''
57
+ unless fname[-1,1] == '/'
58
+ fname += '/'
59
+ end
60
+ else
61
+ f = File.open(fname, 'rb')
62
+ fdata = f.read(f.stat.size)
63
+ f.close
64
+ end
65
+ end
66
+
67
+ @entries << Entry.new(fname, fdata, @compmeth, ts, attrs, xtra, comment, central_dir_name)
68
+ end
69
+
70
+
71
+ def set_comment(comment)
72
+ @comment = comment
73
+ end
74
+
75
+
76
+ #
77
+ # Write the compressed file to +fname+.
78
+ #
79
+ def save_to(fname)
80
+ f = File.open(fname, 'wb')
81
+ f.write(pack)
82
+ f.close
83
+ end
84
+
85
+
86
+ #
87
+ # Compress this archive and return the resulting zip file as a String.
88
+ #
89
+ def pack
90
+ ret = ''
91
+
92
+ # save the offests
93
+ offsets = []
94
+
95
+ # file 1 .. file n
96
+ @entries.each { |ent|
97
+ offsets << ret.length
98
+ ret << ent.pack
99
+ }
100
+
101
+ # archive decryption header (unsupported)
102
+ # archive extra data record (unsupported)
103
+
104
+ # central directory
105
+ cfd_offset = ret.length
106
+ idx = 0
107
+ @entries.each { |ent|
108
+ cfd = CentralDir.new(ent, offsets[idx])
109
+ ret << cfd.pack
110
+ idx += 1
111
+ }
112
+
113
+ # zip64 end of central dir record (unsupported)
114
+ # zip64 end of central dir locator (unsupported)
115
+
116
+ # end of central directory record
117
+ cur_offset = ret.length - cfd_offset
118
+ ret << CentralDirEnd.new(@entries.length, cur_offset, cfd_offset, @comment).pack
119
+
120
+ ret
121
+ end
122
+
123
+ def inspect
124
+ "#<#{self.class} entries = [#{@entries.map{|e| e.name}.join(",")}]>"
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,184 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+ module Zip
5
+
6
+
7
+ #
8
+ # This structure holds the following data pertaining to a Zip entry's data.
9
+ #
10
+ # data crc
11
+ # compressed size
12
+ # uncompressed size
13
+ #
14
+ class CompInfo
15
+
16
+ def initialize(crc, compsz, uncompsz)
17
+ @crc, @compsz, @uncompsz = crc, compsz, uncompsz
18
+ end
19
+
20
+ def pack
21
+ [ @crc, @compsz, @uncompsz ].pack('VVV')
22
+ end
23
+
24
+ end
25
+
26
+
27
+ #
28
+ # This structure holds the following data pertaining to a Zip entry.
29
+ #
30
+ # general purpose bit flag
31
+ # compression method
32
+ # modification time
33
+ # modification date
34
+ #
35
+ class CompFlags
36
+
37
+ attr_accessor :compmeth
38
+
39
+ def initialize(gpbf, compmeth, timestamp)
40
+ @gpbf = gpbf
41
+ @compmeth = compmeth
42
+ @mod_time = ((timestamp.hour << 11) | (timestamp.min << 5) | (timestamp.sec))
43
+ @mod_date = (((timestamp.year - 1980) << 9) | (timestamp.mon << 5) | (timestamp.day))
44
+ end
45
+
46
+ def pack
47
+ [ @gpbf, @compmeth, @mod_time, @mod_date ].pack('vvvv')
48
+ end
49
+
50
+ end
51
+
52
+
53
+
54
+ #
55
+ # This structure is sometimes stored after the file data and used
56
+ # instead of the fields within the Local File Header.
57
+ #
58
+ class DataDesc
59
+
60
+ SIGNATURE = 0x8074b50
61
+
62
+ def initialize(compinfo)
63
+ @compinfo = compinfo
64
+ end
65
+
66
+ def pack
67
+ ret = [ SIGNATURE ].pack('V')
68
+ ret << @compinfo.pack
69
+ ret
70
+ end
71
+
72
+ end
73
+
74
+
75
+ #
76
+ # This structure records the compression data and flags about
77
+ # a Zip entry to a file.
78
+ #
79
+ class LocalFileHdr
80
+
81
+ SIGNATURE = 0x4034b50
82
+
83
+ def initialize(entry)
84
+ @entry = entry
85
+ end
86
+
87
+ def pack
88
+ path = @entry.relative_path
89
+
90
+ ret = [ SIGNATURE, ZIP_VERSION ].pack('Vv')
91
+ ret << @entry.flags.pack
92
+ ret << @entry.info.pack
93
+ ret << [ path.length, @entry.xtra.length ].pack('vv')
94
+ ret << path
95
+ ret << @entry.xtra
96
+ ret
97
+ end
98
+
99
+ end
100
+
101
+
102
+ #
103
+ # This structure holds all of the information about a particular Zip Entry
104
+ # as it is contained within the central directory.
105
+ #
106
+ class CentralDir
107
+
108
+ SIGNATURE = 0x2014b50
109
+
110
+ def initialize(entry, offset)
111
+ @entry = entry
112
+ @disknum_start = 0
113
+ @attr_int = 0
114
+ @attr_ext = 0x20
115
+ @hdr_offset = offset
116
+ end
117
+
118
+ def pack
119
+ if @entry.central_dir_name.to_s.strip.empty?
120
+ path = @entry.relative_path
121
+ else
122
+ path = @entry.central_dir_path
123
+ end
124
+
125
+ ret = [ SIGNATURE, ZIP_VERSION ].pack('Vv')
126
+ ret << [ ZIP_VERSION ].pack('v')
127
+ ret << @entry.flags.pack
128
+ ret << @entry.info.pack
129
+ arr = []
130
+ arr << path.length
131
+ arr << @entry.xtra.length
132
+ arr << @entry.comment.length
133
+ arr << @disknum_start
134
+ arr << @attr_int
135
+ arr << @entry.attrs
136
+ arr << @hdr_offset
137
+ ret << arr.pack('vvvvvVV')
138
+ ret << path
139
+ ret << @entry.xtra
140
+ ret << @entry.comment
141
+ # digital signature not supported
142
+ ret
143
+ end
144
+
145
+ end
146
+
147
+
148
+ #
149
+ # This structure is written after the per-entry central directory records to
150
+ # provide information about the archive as a whole.
151
+ #
152
+ class CentralDirEnd
153
+
154
+ SIGNATURE = 0x6054b50
155
+
156
+ def initialize(ncfd, cfdsz, offset, comment=nil)
157
+ @disk_no = 0
158
+ @disk_dir_start = 0
159
+ @ncfd_this_disk = ncfd
160
+ @ncfd_total = ncfd
161
+ @cfd_size = cfdsz
162
+ @start_offset = offset
163
+ @comment = comment
164
+ @comment ||= ''
165
+ end
166
+
167
+
168
+ def pack
169
+ arr = []
170
+ arr << SIGNATURE
171
+ arr << @disk_no
172
+ arr << @disk_dir_start
173
+ arr << @ncfd_this_disk
174
+ arr << @ncfd_total
175
+ arr << @cfd_size
176
+ arr << @start_offset
177
+ arr << @comment.length
178
+ (arr.pack('VvvvvVVv') + @comment)
179
+ end
180
+
181
+ end
182
+
183
+ end
184
+ end