rex-core 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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/README.md +33 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rex/compat.rb +385 -0
- data/lib/rex/core.rb +9 -0
- data/lib/rex/core/version.rb +5 -0
- data/lib/rex/file.rb +160 -0
- data/rex-core.gemspec +26 -0
- metadata +176 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3d83c3ce2623cc1100697dd1748d2bee34258691
|
4
|
+
data.tar.gz: b5936fc069cb83cd4d5c568e92de8685fdf72a4c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8193d68e6f91eb307db2a187cb02953f009c3632c3acd462157ddba3a5c4243e57d09a14b9e52abad8904ac7afb2d8e2ab7e086ca012fe763952ca07f775b38c
|
7
|
+
data.tar.gz: fc3d6d4ef29eb3ece0c406f397c3f637bae55ece693267061a487119c1eece4d7f69d93cf870f44a1c97309a05f339a15c4fb08d1ff53c3efd9d7e8519182a81
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
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 a project maintainer at DMaloney@rapid7.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Rex::Core
|
2
|
+
|
3
|
+
The Ruby Exploitation (rex) Core Gem. This Gem contains the odds and ends of code that so many other pieces of Rex rely upon, but that
|
4
|
+
are too small to be put into their own seperate gems. This include some of the ruby cross-platform compatibility and file utility code.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'rex-core'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install rex-core
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
## Development
|
25
|
+
|
26
|
+
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.
|
27
|
+
|
28
|
+
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).
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
|
32
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/rapid7/rex-core. 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.
|
33
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "rex/core"
|
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
|
data/bin/setup
ADDED
data/lib/rex/compat.rb
ADDED
@@ -0,0 +1,385 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
module Rex
|
3
|
+
|
4
|
+
###
|
5
|
+
#
|
6
|
+
# This class provides os-specific functionality
|
7
|
+
#
|
8
|
+
###
|
9
|
+
module Compat
|
10
|
+
|
11
|
+
STD_INPUT_HANDLE = -10
|
12
|
+
STD_OUTPUT_HANDLE = -11
|
13
|
+
STD_ERROR_HANDLE = -12
|
14
|
+
|
15
|
+
GENERIC_READ = 0x80000000
|
16
|
+
GENERIC_WRITE = 0x40000000
|
17
|
+
GENERIC_EXECUTE = 0x20000000
|
18
|
+
|
19
|
+
FILE_SHARE_READ = 0x00000001
|
20
|
+
FILE_SHARE_WRITE = 0x00000002
|
21
|
+
OPEN_EXISTING = 0x00000003
|
22
|
+
|
23
|
+
ENABLE_LINE_INPUT = 2
|
24
|
+
ENABLE_ECHO_INPUT = 4
|
25
|
+
ENABLE_PROCESSED_INPUT = 1
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Platform detection
|
31
|
+
#
|
32
|
+
|
33
|
+
@@is_windows = @@is_cygwin = @@is_macosx = @@is_linux = @@is_bsdi = @@is_freebsd = @@is_netbsd = @@is_openbsd = @@is_java = false
|
34
|
+
@@loaded_win32api = false
|
35
|
+
@@loaded_tempfile = false
|
36
|
+
@@loaded_fileutils = false
|
37
|
+
|
38
|
+
|
39
|
+
def self.is_windows
|
40
|
+
return @@is_windows if @@is_windows
|
41
|
+
@@is_windows = (RUBY_PLATFORM =~ /mswin(32|64)|mingw(32|64)/) ? true : false
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.is_cygwin
|
45
|
+
return @@is_cygwin if @@is_cygwin
|
46
|
+
@@is_cygwin = (RUBY_PLATFORM =~ /cygwin/) ? true : false
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.is_macosx
|
50
|
+
return @@is_macosx if @@is_macosx
|
51
|
+
@@is_macosx = (RUBY_PLATFORM =~ /darwin/) ? true : false
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.is_linux
|
55
|
+
return @@is_linux if @@is_linux
|
56
|
+
@@is_linux = (RUBY_PLATFORM =~ /linux/) ? true : false
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.is_bsdi
|
60
|
+
return @@is_bsdi if @@is_bsdi
|
61
|
+
@@is_bsdi = (RUBY_PLATFORM =~ /bsdi/i) ? true : false
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.is_netbsd
|
65
|
+
return @@is_netbsd if @@is_netbsd
|
66
|
+
@@is_netbsd = (RUBY_PLATFORM =~ /netbsd/) ? true : false
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.is_freebsd
|
70
|
+
return @@is_freebsd if @@is_freebsd
|
71
|
+
@@is_freebsd = (RUBY_PLATFORM =~ /freebsd/) ? true : false
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.is_openbsd
|
75
|
+
return @@is_openbsd if @@is_openbsd
|
76
|
+
@@is_openbsd = (RUBY_PLATFORM =~ /openbsd/) ? true : false
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.is_java
|
80
|
+
return @@is_java if @@is_java
|
81
|
+
@@is_java = (RUBY_PLATFORM =~ /java/) ? true : false
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.is_wow64
|
85
|
+
return false if not is_windows
|
86
|
+
is64 = false
|
87
|
+
begin
|
88
|
+
buff = "\x00" * 4
|
89
|
+
Win32API.new("kernel32","IsWow64Process",['L','P'],'L').call(-1, buff)
|
90
|
+
is64 = (buff.unpack("V")[0]) == 1 ? true : false
|
91
|
+
rescue ::Exception
|
92
|
+
end
|
93
|
+
is64
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.cygwin_to_win32(path)
|
97
|
+
if(path !~ /^\/cygdrive/)
|
98
|
+
return ::IO.popen("cygpath -w #{path}", "rb").read.strip
|
99
|
+
end
|
100
|
+
dir = path.split("/")
|
101
|
+
dir.shift
|
102
|
+
dir.shift
|
103
|
+
dir[0] = dir[0] + ":"
|
104
|
+
dir.join("\\")
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.open_file(url='')
|
108
|
+
case RUBY_PLATFORM
|
109
|
+
when /cygwin/
|
110
|
+
path = self.cygwin_to_win32(url)
|
111
|
+
system(["cmd", "cmd"], "/c", "explorer", path)
|
112
|
+
else
|
113
|
+
self.open_browser(url)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.open_browser(url='http://google.com/')
|
118
|
+
case RUBY_PLATFORM
|
119
|
+
when /cygwin/
|
120
|
+
if(url[0,1] == "/")
|
121
|
+
self.open_file(url)
|
122
|
+
end
|
123
|
+
return if not @@loaded_win32api
|
124
|
+
Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0)
|
125
|
+
when /mswin32|mingw/
|
126
|
+
return if not @@loaded_win32api
|
127
|
+
Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0)
|
128
|
+
when /darwin/
|
129
|
+
system("open #{url}")
|
130
|
+
else
|
131
|
+
# Search through the PATH variable (if it exists) and chose a browser
|
132
|
+
# We are making an assumption about the nature of "PATH" so tread lightly
|
133
|
+
if defined? ENV['PATH']
|
134
|
+
# "xdg-open" is more general than "sensible-browser" and can be useful for lots of
|
135
|
+
# file types -- text files, pcaps, or URLs. It's nearly always
|
136
|
+
# going to use the application the user is expecting. If we're not
|
137
|
+
# on something Debian-based, fall back to likely browsers.
|
138
|
+
['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser|
|
139
|
+
ENV['PATH'].split(':').each do |path|
|
140
|
+
# Does the browser exists?
|
141
|
+
if File.exist?("#{path}/#{browser}")
|
142
|
+
system("#{browser} #{url} &")
|
143
|
+
return
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.open_webrtc_browser(url='http://google.com/')
|
152
|
+
case RUBY_PLATFORM
|
153
|
+
when /mswin2|mingw|cygwin/
|
154
|
+
paths = [
|
155
|
+
"Google\\Chrome\\Application\\chrome.exe",
|
156
|
+
"Mozilla Firefox\\firefox.exe",
|
157
|
+
"Opera\\launcher.exe"
|
158
|
+
]
|
159
|
+
|
160
|
+
prog_files = ENV['ProgramFiles']
|
161
|
+
paths = paths.map { |p| "#{prog_files}\\#{p}" }
|
162
|
+
|
163
|
+
# Old chrome path
|
164
|
+
app_data = ENV['APPDATA']
|
165
|
+
paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe"
|
166
|
+
|
167
|
+
paths.each do |path|
|
168
|
+
if File.exist?(path)
|
169
|
+
args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : ""
|
170
|
+
system("\"#{path}\" #{args} \"#{url}\"")
|
171
|
+
return true
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
when /darwin/
|
176
|
+
['Google Chrome.app', 'Firefox.app'].each do |browser|
|
177
|
+
browser_path = "/Applications/#{browser}"
|
178
|
+
if File.directory?(browser_path)
|
179
|
+
args = (browser_path =~ /Chrome/) ? "--args --allow-file-access-from-files" : ""
|
180
|
+
|
181
|
+
system("open #{url} -a \"#{browser_path}\" #{args} &")
|
182
|
+
return true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
else
|
186
|
+
if defined? ENV['PATH']
|
187
|
+
['google-chrome', 'chrome', 'chromium', 'firefox' , 'firefox', 'opera'].each do |browser|
|
188
|
+
ENV['PATH'].split(':').each do |path|
|
189
|
+
browser_path = "#{path}/#{browser}"
|
190
|
+
if File.exist?(browser_path)
|
191
|
+
args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : ""
|
192
|
+
system("#{browser_path} #{args} #{url} &")
|
193
|
+
return true
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
false
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.open_email(addr)
|
204
|
+
case RUBY_PLATFORM
|
205
|
+
when /mswin32|cygwin/
|
206
|
+
return if not @@loaded_win32api
|
207
|
+
Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", "mailto:"+addr, nil, nil, 0)
|
208
|
+
when /darwin/
|
209
|
+
system("open mailto:#{addr}")
|
210
|
+
else
|
211
|
+
# ?
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.play_sound(path)
|
216
|
+
case RUBY_PLATFORM
|
217
|
+
when /cygwin/
|
218
|
+
path = self.cygwin_to_win32(path)
|
219
|
+
return if not @@loaded_win32api
|
220
|
+
Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000)
|
221
|
+
when /mswin32/
|
222
|
+
return if not @@loaded_win32api
|
223
|
+
Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000)
|
224
|
+
when /darwin/
|
225
|
+
system("afplay #{path} >/dev/null 2>&1")
|
226
|
+
else
|
227
|
+
system("aplay #{path} >/dev/null 2>&1")
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.getenv(var)
|
232
|
+
if (is_windows and @@loaded_win32api)
|
233
|
+
f = Win32API.new("kernel32", "GetEnvironmentVariable", ["P", "P", "I"], "I")
|
234
|
+
buff = "\x00" * 16384
|
235
|
+
sz = f.call(var, buff, buff.length)
|
236
|
+
return nil if sz == 0
|
237
|
+
buff[0,sz]
|
238
|
+
else
|
239
|
+
ENV[var]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.setenv(var,val)
|
244
|
+
if (is_windows and @@loaded_win32api)
|
245
|
+
f = Win32API.new("kernel32", "SetEnvironmentVariable", ["P", "P"], "I")
|
246
|
+
f.call(var, val + "\x00")
|
247
|
+
else
|
248
|
+
ENV[var]= val
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
|
253
|
+
#
|
254
|
+
# Obtain the path to our interpreter
|
255
|
+
#
|
256
|
+
def self.win32_ruby_path
|
257
|
+
return nil if ! (is_windows and @@loaded_win32api)
|
258
|
+
gmh = Win32API.new("kernel32", "GetModuleHandle", ["P"], "L")
|
259
|
+
gmf = Win32API.new("kernel32", "GetModuleFileName", ["LPL"], "L")
|
260
|
+
mod = gmh.call(nil)
|
261
|
+
inf = "\x00" * 1024
|
262
|
+
gmf.call(mod, inf, 1024)
|
263
|
+
inf.unpack("Z*")[0]
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Call WinExec (equiv to system("cmd &"))
|
268
|
+
#
|
269
|
+
def self.win32_winexec(cmd)
|
270
|
+
return nil if ! (is_windows and @@loaded_win32api)
|
271
|
+
exe = Win32API.new("kernel32", "WinExec", ["PL"], "L")
|
272
|
+
exe.call(cmd, 0)
|
273
|
+
end
|
274
|
+
|
275
|
+
#
|
276
|
+
# Verify the Console2 environment
|
277
|
+
#
|
278
|
+
def self.win32_console2_verify
|
279
|
+
return nil if ! (is_windows and @@loaded_win32api)
|
280
|
+
buf = "\x00" * 512
|
281
|
+
out = Win32API.new("kernel32", "GetStdHandle", ["L"], "L").call(STD_OUTPUT_HANDLE)
|
282
|
+
res = Win32API.new("kernel32","GetConsoleTitle", ["PL"], "L").call(buf, buf.length-1) rescue 0
|
283
|
+
( res > 0 and buf.index("Console2 command").nil? ) ? false : true
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
# Expand a 8.3 path to a full path
|
288
|
+
#
|
289
|
+
def self.win32_expand_path(path)
|
290
|
+
return nil if ! (is_windows and @@loaded_win32api)
|
291
|
+
glp = Win32API.new('kernel32', 'GetLongPathName', 'PPL', 'L')
|
292
|
+
buf = "\x00" * 260
|
293
|
+
len = glp.call(path, buf, buf.length)
|
294
|
+
buf[0, len]
|
295
|
+
end
|
296
|
+
|
297
|
+
#
|
298
|
+
# Platform independent socket pair
|
299
|
+
#
|
300
|
+
def self.pipe
|
301
|
+
|
302
|
+
if (! is_windows())
|
303
|
+
# Standard pipes should be fine
|
304
|
+
return ::IO.pipe
|
305
|
+
end
|
306
|
+
|
307
|
+
# Create a socket connection for Windows
|
308
|
+
serv = nil
|
309
|
+
port = 1024
|
310
|
+
|
311
|
+
while (! serv and port < 65535)
|
312
|
+
begin
|
313
|
+
serv = TCPServer.new('127.0.0.1', (port += 1))
|
314
|
+
rescue ::Exception
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
pipe1 = TCPSocket.new('127.0.0.1', port)
|
319
|
+
|
320
|
+
# Accept the forked child
|
321
|
+
pipe2 = serv.accept
|
322
|
+
|
323
|
+
# Shutdown the server
|
324
|
+
serv.close
|
325
|
+
|
326
|
+
return [pipe1, pipe2]
|
327
|
+
end
|
328
|
+
|
329
|
+
#
|
330
|
+
# Copy a file to a temporary path
|
331
|
+
#
|
332
|
+
|
333
|
+
def self.temp_copy(path)
|
334
|
+
raise RuntimeError,"missing Tempfile" if not @@loaded_tempfile
|
335
|
+
fd = File.open(path, "rb")
|
336
|
+
tp = Tempfile.new("msftemp")
|
337
|
+
tp.binmode
|
338
|
+
tp.write(fd.read(File.size(path)))
|
339
|
+
tp.close
|
340
|
+
fd.close
|
341
|
+
tp
|
342
|
+
end
|
343
|
+
|
344
|
+
#
|
345
|
+
# Delete an opened temporary file
|
346
|
+
#
|
347
|
+
|
348
|
+
def self.temp_delete(tp)
|
349
|
+
raise RuntimeError,"missing FileUtils" if not @@loaded_fileutils
|
350
|
+
begin
|
351
|
+
FileUtils.rm(tp.path)
|
352
|
+
rescue
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
|
357
|
+
#
|
358
|
+
# Initialization
|
359
|
+
#
|
360
|
+
|
361
|
+
if(is_windows or is_cygwin)
|
362
|
+
begin
|
363
|
+
require "Win32API"
|
364
|
+
@@loaded_win32api = true
|
365
|
+
rescue ::Exception
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
begin
|
370
|
+
require "tempfile"
|
371
|
+
@@loaded_tempfile = true
|
372
|
+
rescue ::Exception
|
373
|
+
end
|
374
|
+
|
375
|
+
begin
|
376
|
+
require "fileutils"
|
377
|
+
@@loaded_fileutils = true
|
378
|
+
rescue ::Exception
|
379
|
+
end
|
380
|
+
|
381
|
+
|
382
|
+
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
data/lib/rex/core.rb
ADDED
data/lib/rex/file.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'find'
|
3
|
+
require 'rex/compat'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Rex
|
7
|
+
|
8
|
+
###
|
9
|
+
#
|
10
|
+
# This class provides helper methods for dealing with files that are not
|
11
|
+
# supplied by the standard ruby API.
|
12
|
+
#
|
13
|
+
###
|
14
|
+
module FileUtils
|
15
|
+
|
16
|
+
#
|
17
|
+
# This method joins the paths together in Unix format.
|
18
|
+
#
|
19
|
+
def self.normalize_unix_path(*strs)
|
20
|
+
new_str = strs * '/'
|
21
|
+
new_str = new_str.gsub!("//", "/") while new_str.index("//")
|
22
|
+
|
23
|
+
new_str
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# This method joins the paths together in Windows format.
|
28
|
+
# All reserved characters will be filtered out, including:
|
29
|
+
# " * : < > ? \ / |
|
30
|
+
#
|
31
|
+
def self.normalize_win_path(*strs)
|
32
|
+
# Convert to the same format so the parsing is easier
|
33
|
+
s = strs * '\\'
|
34
|
+
|
35
|
+
# Filter out double slashes
|
36
|
+
s = s.gsub(/\\\\/, '\\') while s.index('\\\\')
|
37
|
+
|
38
|
+
# Keep the trailing slash if exists
|
39
|
+
trailing_s = ('\\' if s =~ /\\$/) || ''
|
40
|
+
|
41
|
+
# Check the items (fie/dir) individually
|
42
|
+
s = s.split(/\\/)
|
43
|
+
|
44
|
+
# Parse the path prefix
|
45
|
+
prefix = (s[0] || '').gsub(/[\*<>\?\/]/, '')
|
46
|
+
|
47
|
+
# Delete the original prefix. We want the new one later.
|
48
|
+
s.delete_at(0)
|
49
|
+
|
50
|
+
# Filter out all the reserved characters
|
51
|
+
s.map! {|e| e.gsub(/["\*:<>\?\\\/|]/, '') }
|
52
|
+
|
53
|
+
# Put the modified prefix back
|
54
|
+
s.insert(0, prefix)
|
55
|
+
|
56
|
+
# And then safely join the items
|
57
|
+
s *= '\\'
|
58
|
+
|
59
|
+
# Add the trailing slash back if exists
|
60
|
+
s << trailing_s
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# This method cleans the supplied path of directory traversal sequences
|
65
|
+
# It must accept path/with/..a/folder../starting/or/ending/in/two/dots
|
66
|
+
# but clean ../something as well as path/with/..\traversal
|
67
|
+
#
|
68
|
+
def self.clean_path(old)
|
69
|
+
path = old
|
70
|
+
while(path.index(/\/..\/|\/..\\|\\..\\|\\..\/|\A..\\|\A..\//) != nil)
|
71
|
+
path.gsub!(/\A..\\|\A..\//,'') #eliminate starting ..\ or ../
|
72
|
+
path.gsub!(/\/..\/|\/..\\/,'/') #clean linux style
|
73
|
+
path.gsub!(/\\..\\|\\..\//,'\\') #clean windows style
|
74
|
+
end
|
75
|
+
path
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# This method searches the PATH environment variable for
|
80
|
+
# a fully qualified path to the supplied file name.
|
81
|
+
#
|
82
|
+
def self.find_full_path(file_name)
|
83
|
+
|
84
|
+
# Check for the absolute fast first
|
85
|
+
if (file_name[0,1] == "/" and ::File.exist?(file_name) and ::File::Stat.new(file_name))
|
86
|
+
return file_name
|
87
|
+
end
|
88
|
+
|
89
|
+
path = Rex::Compat.getenv('PATH')
|
90
|
+
if (path)
|
91
|
+
path.split(::File::PATH_SEPARATOR).each { |base|
|
92
|
+
begin
|
93
|
+
# Deal with Windows paths surrounded by quotes. Prevents
|
94
|
+
# silliness like trying to look for
|
95
|
+
# '"C:\\framework\\nmap"\\nmap.exe' which will always fail.
|
96
|
+
base = $1 if base =~ /^"(.*)"$/
|
97
|
+
path = base + ::File::SEPARATOR + file_name
|
98
|
+
if (::File::Stat.new(path) and not ::File.directory?(path))
|
99
|
+
return path
|
100
|
+
end
|
101
|
+
rescue
|
102
|
+
end
|
103
|
+
}
|
104
|
+
end
|
105
|
+
return nil
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class Quickfile < ::Tempfile
|
111
|
+
def initialize(*args)
|
112
|
+
super(*args)
|
113
|
+
self.binmode
|
114
|
+
ObjectSpace.undefine_finalizer(self)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module Find
|
119
|
+
#
|
120
|
+
# Identical to Find.find from Ruby, but follows symlinks to directories.
|
121
|
+
# See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/68671
|
122
|
+
#
|
123
|
+
def self.find(*paths)
|
124
|
+
paths.collect!{|d| d.dup}
|
125
|
+
while file = paths.shift
|
126
|
+
catch(:prune) do
|
127
|
+
yield file.dup.taint
|
128
|
+
next unless File.exist? file
|
129
|
+
begin
|
130
|
+
if File.stat(file).directory? then
|
131
|
+
d = Dir.open(file)
|
132
|
+
begin
|
133
|
+
for f in d
|
134
|
+
next if f == "." or f == ".."
|
135
|
+
if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then
|
136
|
+
f = file + f
|
137
|
+
elsif file == "/" then
|
138
|
+
f = "/" + f
|
139
|
+
else
|
140
|
+
f = File.join(file, f)
|
141
|
+
end
|
142
|
+
paths.unshift f.untaint
|
143
|
+
end
|
144
|
+
ensure
|
145
|
+
d.close
|
146
|
+
end
|
147
|
+
end
|
148
|
+
rescue Errno::ENOENT, Errno::EACCES
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.prune
|
155
|
+
throw :prune
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
data/rex-core.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rex/core/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rex-core"
|
8
|
+
spec.version = Rex::Core::VERSION
|
9
|
+
spec.authors = ["David Maloney"]
|
10
|
+
spec.email = ["DMaloney@rapid7.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Core libraries required for the Ruby Exploitation(Rex) Suite.}
|
13
|
+
spec.description = %q{Core libraries required for the Ruby Exploitation(Rex) Suite.}
|
14
|
+
spec.homepage = "https://github.com/rapid7/rex-core"
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rex-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Maloney
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
|
14
|
+
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
|
15
|
+
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
|
16
|
+
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
|
17
|
+
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
|
18
|
+
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
|
19
|
+
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
|
20
|
+
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
|
21
|
+
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
|
22
|
+
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
|
23
|
+
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
|
24
|
+
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
|
25
|
+
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
|
26
|
+
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
|
27
|
+
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
|
28
|
+
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
|
29
|
+
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
|
30
|
+
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
|
31
|
+
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
- |
|
34
|
+
-----BEGIN CERTIFICATE-----
|
35
|
+
MIIEKDCCAxCgAwIBAgILBAAAAAABL07hNVwwDQYJKoZIhvcNAQEFBQAwVzELMAkG
|
36
|
+
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
|
37
|
+
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
|
38
|
+
MDBaFw0xOTA0MTMxMDAwMDBaMFExCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
|
39
|
+
YWxTaWduIG52LXNhMScwJQYDVQQDEx5HbG9iYWxTaWduIENvZGVTaWduaW5nIENB
|
40
|
+
IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyTxTnEL7XJnKr
|
41
|
+
NpfvU79ChF5Y0Yoo/ENGb34oRFALdV0A1zwKRJ4gaqT3RUo3YKNuPxL6bfq2RsNq
|
42
|
+
o7gMJygCVyjRUPdhOVW4w+ElhlI8vwUd17Oa+JokMUnVoqni05GrPjxz7/Yp8cg1
|
43
|
+
0DB7f06SpQaPh+LO9cFjZqwYaSrBXrta6G6V/zuAYp2Zx8cvZtX9YhqCVVrG+kB3
|
44
|
+
jskwPBvw8jW4bFmc/enWyrRAHvcEytFnqXTjpQhU2YM1O46MIwx1tt6GSp4aPgpQ
|
45
|
+
STic0qiQv5j6yIwrJxF+KvvO3qmuOJMi+qbs+1xhdsNE1swMfi9tBoCidEC7tx/0
|
46
|
+
O9dzVB/zAgMBAAGjgfowgfcwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB
|
47
|
+
Af8CAQAwHQYDVR0OBBYEFAhu2Lacir/tPtfDdF3MgB+oL1B6MEcGA1UdIARAMD4w
|
48
|
+
PAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNv
|
49
|
+
bS9yZXBvc2l0b3J5LzAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmdsb2Jh
|
50
|
+
bHNpZ24ubmV0L3Jvb3QuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQY
|
51
|
+
MBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA0GCSqGSIb3DQEBBQUAA4IBAQAiXMXd
|
52
|
+
PfQLcNjj9efFjgkBu7GWNlxaB63HqERJUSV6rg2kGTuSnM+5Qia7O2yX58fOEW1o
|
53
|
+
kdqNbfFTTVQ4jGHzyIJ2ab6BMgsxw2zJniAKWC/wSP5+SAeq10NYlHNUBDGpeA07
|
54
|
+
jLBwwT1+170vKsPi9Y8MkNxrpci+aF5dbfh40r5JlR4VeAiR+zTIvoStvODG3Rjb
|
55
|
+
88rwe8IUPBi4A7qVPiEeP2Bpen9qA56NSvnwKCwwhF7sJnJCsW3LZMMSjNaES2dB
|
56
|
+
fLEDF3gJ462otpYtpH6AA0+I98FrWkYVzSwZi9hwnOUtSYhgcqikGVJwQ17a1kYD
|
57
|
+
sGgOJO9K9gslJO8k
|
58
|
+
-----END CERTIFICATE-----
|
59
|
+
- |
|
60
|
+
-----BEGIN CERTIFICATE-----
|
61
|
+
MIIEyjCCA7KgAwIBAgISESEyE8rNriS4+1dc8jOHEUL8MA0GCSqGSIb3DQEBBQUA
|
62
|
+
MFExCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMScwJQYD
|
63
|
+
VQQDEx5HbG9iYWxTaWduIENvZGVTaWduaW5nIENBIC0gRzIwHhcNMTMxMDExMTUx
|
64
|
+
NTM4WhcNMTYxMDExMTUxNTM4WjBgMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTWFz
|
65
|
+
c2FjaHVzZXR0czEPMA0GA1UEBxMGQm9zdG9uMRMwEQYDVQQKEwpSYXBpZDcgTExD
|
66
|
+
MRMwEQYDVQQDEwpSYXBpZDcgTExDMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
67
|
+
CgKCAQEAhD//7+739c69hssg0mD6CXgf2JkuWTcU81dgD7aKcoEPqU8e1FseBvDW
|
68
|
+
/Q5fNK2H2NgHV/Msn18zXuK0PkaJXqj/vDsuKB3Hq0BiR2AwyDdEw8K5MK5bgQc2
|
69
|
+
tmcVtEAejRoy1Uv5UyfaAYAxG6zsma3buV1fjnEAC3VouRg4+EX/f65H/a6srntK
|
70
|
+
5Etp3D71k2f0oUl8dOqOmSsRJQQ5zSs4ktDvpjAmsvzoA+1svceLYU95mvQsIw2T
|
71
|
+
edpmibGMwGw/HmgV+YWBgF5UGvax6zbC2i6DF2YHnDfkNb8/1MEIaxOTAbJTazTK
|
72
|
+
8laCQOyay6L1BNPQKjZBgOge8LZq1wIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQD
|
73
|
+
AgeAMEwGA1UdIARFMEMwQQYJKwYBBAGgMgEyMDQwMgYIKwYBBQUHAgEWJmh0dHBz
|
74
|
+
Oi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAkGA1UdEwQCMAAwEwYD
|
75
|
+
VR0lBAwwCgYIKwYBBQUHAwMwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cDovL2NybC5n
|
76
|
+
bG9iYWxzaWduLmNvbS9ncy9nc2NvZGVzaWduZzIuY3JsMIGGBggrBgEFBQcBAQR6
|
77
|
+
MHgwQAYIKwYBBQUHMAKGNGh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2Fj
|
78
|
+
ZXJ0L2dzY29kZXNpZ25nMi5jcnQwNAYIKwYBBQUHMAGGKGh0dHA6Ly9vY3NwMi5n
|
79
|
+
bG9iYWxzaWduLmNvbS9nc2NvZGVzaWduZzIwHQYDVR0OBBYEFE536JwFx9SpaEi3
|
80
|
+
w8pcq2GRFA5BMB8GA1UdIwQYMBaAFAhu2Lacir/tPtfDdF3MgB+oL1B6MA0GCSqG
|
81
|
+
SIb3DQEBBQUAA4IBAQAGpGXHtFLjTTivV+xQPwtZhfPuJ7f+VGTMSAAYWmfzyHXM
|
82
|
+
YMFYUWJzSFcuVR2YfxtbS45P7U5Qopd7jBQ0Ygk5h2a+B5nE4+UlhHj665d0zpYM
|
83
|
+
1eWndMaO6WBOYnqtNyi8Dqqc1foKZDNHEDggYhGso7OIBunup+N4sPL9PwQ3eYe6
|
84
|
+
mUu8z0E4GXYViaMPOFkqaYnoYgf2L+7L5zKYT4h/NE/P7kj7EbduHgy/v/aAIrNl
|
85
|
+
2SpuQH+SWteq3NXkAmFEEqvLJQ4sbptZt8OP8ghL3pVAvZNFmww/YVszSkShSzcg
|
86
|
+
QdihYCSEL2drS2cFd50jBeq71sxUtxbv82DUa2b+
|
87
|
+
-----END CERTIFICATE-----
|
88
|
+
date: 2016-08-15 00:00:00.000000000 Z
|
89
|
+
dependencies:
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: bundler
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.12'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.12'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: rake
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '10.0'
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: rspec
|
120
|
+
requirement: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.0'
|
125
|
+
type: :development
|
126
|
+
prerelease: false
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.0'
|
132
|
+
description: Core libraries required for the Ruby Exploitation(Rex) Suite.
|
133
|
+
email:
|
134
|
+
- DMaloney@rapid7.com
|
135
|
+
executables: []
|
136
|
+
extensions: []
|
137
|
+
extra_rdoc_files: []
|
138
|
+
files:
|
139
|
+
- ".gitignore"
|
140
|
+
- ".rspec"
|
141
|
+
- ".travis.yml"
|
142
|
+
- CODE_OF_CONDUCT.md
|
143
|
+
- Gemfile
|
144
|
+
- README.md
|
145
|
+
- Rakefile
|
146
|
+
- bin/console
|
147
|
+
- bin/setup
|
148
|
+
- lib/rex/compat.rb
|
149
|
+
- lib/rex/core.rb
|
150
|
+
- lib/rex/core/version.rb
|
151
|
+
- lib/rex/file.rb
|
152
|
+
- rex-core.gemspec
|
153
|
+
homepage: https://github.com/rapid7/rex-core
|
154
|
+
licenses: []
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.4.8
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: Core libraries required for the Ruby Exploitation(Rex) Suite.
|
176
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|