uirusu 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS.markdown CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  # 0.0.1 (??)
4
4
  - Rename ruby-virustotal/virustotal gem to uirusu, to prevent being sued.
5
- - Complete rewrite of those gems
5
+ - Complete rewrite of the gem
data/README.markdown CHANGED
@@ -1,2 +1,44 @@
1
1
  # uirusu
2
2
 
3
+ uirusu is [virustotal](http://www.virustotal.com) automation and convenience tool for hash, file and URL submission.
4
+
5
+ The current version is 0.0.1
6
+
7
+ ## Requirements
8
+
9
+ * ruby
10
+ * rubygems
11
+ * json
12
+ * rest-client
13
+
14
+ * **public api key from [virustotal.com](http://www.virustotal.com)**
15
+
16
+ ## Installation
17
+
18
+ % gem install uirusu
19
+ % uirusu [options]
20
+
21
+ ## Usage
22
+
23
+ ### Searching a file of hashes
24
+
25
+ % uirusu -f <file_with_hashes_one_per_line>
26
+
27
+ ### Searching a single hash
28
+
29
+ % uirusu -h FD287794107630FA3116800E617466A9
30
+
31
+ ### Searching a file of hashes and outputting to XML
32
+ % uirusu -f <file_with_hashes_one_per_line> -x
33
+
34
+ ### Upload a file to Virustotal and wait for analysis
35
+ % uirusu -u </path/to/file>
36
+
37
+ ### Search for a single URL
38
+ % uirusu -s "http://www.google.com"
39
+
40
+ ### Saving results to a file
41
+ % uirusu -s "http://www.google.com" --yaml-output > file.yaml
42
+
43
+ ## Contact
44
+ You can reach me at Jacob[dot]Hammack[at]hammackj[dot]com or http://www.hammackj.com
data/Rakefile CHANGED
@@ -19,10 +19,10 @@ task :clean do
19
19
  system "rm -rf coverage"
20
20
  end
21
21
 
22
- task :default => [:test_unit]
22
+ task :default => [:test]
23
23
 
24
- Rake::TestTask.new("test_unit") { |t|
24
+ Rake::TestTask.new("test") do |t|
25
25
  t.libs << "test"
26
26
  t.pattern = 'test/*/*_test.rb'
27
27
  t.verbose = true
28
- }
28
+ end
data/bin/uirusu CHANGED
@@ -1,3 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- puts "Not implemented yet."
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '/../lib'))
4
+
5
+ require 'rubygems'
6
+ require 'uirusu'
7
+
8
+ app = Uirusu::CLI::Application.new
9
+ app.main(ARGV)
data/lib/uirusu.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Uirusu
2
2
  APP_NAME = "uirusu"
3
- VERSION = "0.0.0"
3
+ VERSION = "0.0.1"
4
4
  CONFIG_FILE = "~/.uirusu"
5
5
  end
6
6
 
@@ -8,3 +8,9 @@ require 'json'
8
8
  require 'rest_client'
9
9
  require 'optparse'
10
10
  require 'yaml'
11
+
12
+ require 'uirusu/vtfile'
13
+ require 'uirusu/vturl'
14
+ require 'uirusu/vtcomment'
15
+ require 'uirusu/vtresult'
16
+ require 'uirusu/cli/application'
@@ -0,0 +1,243 @@
1
+ module Uirusu
2
+ module CLI
3
+ class Application
4
+
5
+ # Creates a new instance of the [Application] class
6
+ #
7
+ def initialize
8
+ @options = {}
9
+ @config = {}
10
+ @hashes = Array.new
11
+ @files_of_hashes = Array.new
12
+ @sites = Array.new
13
+ @uploads = Array.new
14
+ end
15
+
16
+ # Parses the command the line options and returns the parsed options hash
17
+ #
18
+ # @return [Hash] of the parsed options
19
+ def parse_options(args)
20
+ begin
21
+ @options['output'] = :stdout
22
+ @options['verbose'] = false
23
+
24
+ opt = OptionParser.new do |opt|
25
+ opt.banner = "#{APP_NAME} v#{VERSION}\nJacob Hammack\nhttp://www.hammackj.com\n\n"
26
+ opt.banner << "Usage: #{APP_NAME} <options>"
27
+ opt.separator('')
28
+ opt.separator("File Options")
29
+
30
+ opt.on('-h HASH', '--search-hash HASH', 'Searches a single hash on virustotal.com') do |hash|
31
+ @hashes.push(hash)
32
+ end
33
+
34
+ opt.on('-f FILE', '--search-hash-file FILE', 'Searches a each hash in a file of hashes on virustotal.com') do |file|
35
+ if File.exists?(file)
36
+ puts "[+] Adding file #{file}" if @options["verbose"]
37
+ @files_of_hashes.push(file)
38
+ else
39
+ puts "[!] #{file} does not exist, please check your input!\n"
40
+ end
41
+ end
42
+
43
+ opt.on('-u FILE', '--upload-file FILE', 'Uploads a file to virustotal.com for analysis') do |file|
44
+ if File.exists?(file)
45
+ puts "[+] Adding file #{file}" if @options["verbose"]
46
+ @uploads.push(file)
47
+ else
48
+ puts "[!] #{file} does not exist, please check your input!\n"
49
+ end
50
+ end
51
+
52
+ opt.separator('')
53
+ opt.separator("Url Options")
54
+
55
+ opt.on('-s SITE', '--search-site SITE', 'Searches for a single url on virustotal.com') { |site|
56
+ @sites.push(site)
57
+ }
58
+
59
+ opt.separator('')
60
+ opt.separator('Output Options')
61
+
62
+ opt.on('-x', '--xml-output', 'Print results as xml to stdout') do
63
+ @options["output"] = :xml
64
+ end
65
+
66
+ opt.on('-y', '--yaml-output', 'Print results as yaml to stdout') do
67
+ @options['output'] = :yaml
68
+ end
69
+
70
+ opt.on('--stdout-output', 'Print results as normal text line to stdout, this is default') do
71
+ @options['output'] = :stdout
72
+ end
73
+
74
+ opt.separator ''
75
+ opt.separator 'Advanced Options'
76
+
77
+ opt.on('-c', '--create-config', 'Creates a skeleton config file to use') do
78
+ if File.exists?(File.expand_path(CONFIG_FILE)) == false
79
+ File.open(File.expand_path(CONFIG_FILE), 'w+') do |f|
80
+ f.write("virustotal: \n api-key: \n timeout: 25\n\n")
81
+ end
82
+
83
+ puts "[*] An empty #{File.expand_path(CONFIG_FILE)} has been created. Please edit and fill in the correct values."
84
+ exit
85
+ else
86
+ puts "[!] #{File.expand_path(CONFIG_FILE)} already exists. Please delete it if you wish to re-create it."
87
+ exit
88
+ end
89
+ end
90
+
91
+ opt.on('--[no-]verbose', 'Print verbose information') do |v|
92
+ @options["verbose"] = v
93
+ end
94
+
95
+ opt.separator ''
96
+ opt.separator 'Other Options'
97
+
98
+ opt.on('-v', '--version', "Shows application version information") do
99
+ puts "#{APP_NAME} - #{VERSION}"
100
+ exit
101
+ end
102
+
103
+ opt.on_tail("-?", "--help", "Show this message") { |help|
104
+ puts opt.to_s + "\n"
105
+ exit
106
+ }
107
+ end
108
+
109
+ if ARGV.length != 0
110
+ opt.parse!
111
+ else
112
+ puts opt.to_s + "\n"
113
+ exit
114
+ end
115
+ rescue OptionParser::MissingArgument => m
116
+ puts opt.to_s + "\n"
117
+ exit
118
+ end
119
+ end
120
+
121
+ # Loads the .uirusu config file for the api key
122
+ #
123
+ def load_config
124
+ if File.exists?(File.expand_path(CONFIG_FILE))
125
+ @config = YAML.load_file File.expand_path(CONFIG_FILE)
126
+ else
127
+ STDERR.puts "[!] #{CONFIG_FILE} does not exist. Please run #{APP_NAME} --create-config, to create it."
128
+ exit
129
+ end
130
+ end
131
+
132
+ # Submits a file/url and waits for analysis to be complete and returns the results.
133
+ #
134
+ # @param mod
135
+ # @param resource
136
+ # @param attempts
137
+ #
138
+ def scan_and_wait(mod, resource, attempts)
139
+ method = nil
140
+ retries = attempts
141
+
142
+ if mod.name == "Uirusu::VTFile"
143
+ method = mod.method :scan_file
144
+ else
145
+ method = mod.method :scan_url
146
+ end
147
+
148
+ begin
149
+ STDERR.puts "[*] Attempting to upload file #{resource}" if @options["verbose"]
150
+ result = method.call(@config["virustotal"]["api-key"], resource)
151
+ rescue => e
152
+ STDERR.puts "[!] An error has occured uploading the file. Retrying 60 seconds up #{retries} retries.\n" if @options["verbose"]
153
+ if retries >= 0
154
+ sleep 60
155
+ retry
156
+ retries = retries - 1
157
+ end
158
+ end
159
+
160
+ begin
161
+ if result['response_code'] == 1
162
+ results = mod.query_report(@config["virustotal"]["api-key"], result['resource'])
163
+
164
+ while results["response_code"] != 1
165
+ STDERR.puts "[*] File has not been analyized yet, waiting 60 seconds to try again" if @options["verbose"]
166
+ sleep 60
167
+ results = mod.query_report(@config["virustotal"]["api-key"], result['resource'])
168
+ end
169
+
170
+ return [result['resource'], results]
171
+ elsif result['response_code'] == -2
172
+ STDERR.puts "[!] Virustotal limits exceeded, ***do not edit the timeout values.***"
173
+ exit(1)
174
+ else
175
+ nil
176
+ end
177
+ rescue => e
178
+ STDERR.puts "[!] An error has occured retrieving the report. Retrying 60 seconds up #{retries} retries.\n" if @options["verbose"]
179
+ if retries >= 0
180
+ sleep 60
181
+ retry
182
+ retries = retries - 1
183
+ end
184
+ end
185
+ end
186
+
187
+ #
188
+ #
189
+ def main(args)
190
+ parse_options(args)
191
+ load_config
192
+
193
+ if @options['output'] == :stdout
194
+ output_method = :to_stdout
195
+ elsif @options['output'] == :yaml
196
+ output_method = :to_yaml
197
+ elsif @options['output'] == :xml
198
+ output_method = :to_xml
199
+ print "<results>\n"
200
+ end
201
+
202
+ if @files_of_hashes != nil
203
+ @files_of_hashes.each do |file|
204
+ f = File.open(file, 'r')
205
+
206
+ f.each do |hash|
207
+ hash.chomp!
208
+ @hashes.push hash
209
+ end
210
+ end
211
+ end
212
+
213
+ if @hashes != nil
214
+ @hashes.each do |hash|
215
+ results = Uirusu::VTFile.query_report(@config["virustotal"]["api-key"], hash)
216
+ result = Uirusu::VTResult.new(hash, results)
217
+ print result.send output_method if result != nil
218
+ end
219
+ end
220
+
221
+ if @sites != nil
222
+ @sites.each do |url|
223
+ results = scan_and_wait(Uirusu::VTUrl, url, 5)
224
+ result = Uirusu::VTResult.new(results[0], results[1])
225
+ print result.send output_method if result != nil
226
+ end
227
+ end
228
+
229
+ if @uploads != nil
230
+ @uploads.each do |upload|
231
+ results = scan_and_wait(Uirusu::VTFile, upload, 5)
232
+ result = Uirusu::VTResult.new(results[0], results[1])
233
+ print result.send output_method if result != nil
234
+ end
235
+ end
236
+
237
+ if @options['output'] == :xml
238
+ print "</results>\n"
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,41 @@
1
+ module Uirusu
2
+ # Module for submiting comments to Virustotal.com resources using the
3
+ # Virustotal.com public API
4
+ module VTComment
5
+ POST_URL = "https://www.virustotal.com/vtapi/v2/comments/put"
6
+
7
+ # Submits a comment to Virustotal.com for a specific resource
8
+ #
9
+ # @param [String] api_key Virustotal.com API key
10
+ # @param [String] resource MD5/sha1/sha256/scan_id to search for
11
+ # @param [String] comment Comment to post to the resource
12
+ #
13
+ # @return [JSON] Parsed response
14
+ def self.post_comment(api_key, resource, comment)
15
+ if api_key == nil
16
+ raise "Invalid API Key"
17
+ end
18
+
19
+ if resource == nil
20
+ raise "Invalid resource, must be a valid url"
21
+ end
22
+
23
+ if comment == nil
24
+ raise "You must provide a comment to submit."
25
+ end
26
+
27
+ response = RestClient.post POST_URL, :apikey => api_key, :resource => resource, :comment => comment
28
+
29
+ case response.code
30
+ when 429
31
+ raise "Virustotal limit reached. Try again later."
32
+ when 403
33
+ raise "Invalid privileges, please check your API key."
34
+ when 200
35
+ JSON.parse(response)
36
+ else
37
+ raise "Unknown Server error."
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,66 @@
1
+ module Uirusu
2
+ # Module for Accessing the File scan and report functionalities of the
3
+ # Virustotal.com public API
4
+ module VTFile
5
+ SCAN_URL = "http://www.virustotal.com/vtapi/v2/file/scan"
6
+ REPORT_URL = "https://www.virustotal.com/vtapi/v2/file/report"
7
+
8
+ # Queries a report from Virustotal.com
9
+ #
10
+ # @param api_key Virustotal.com API key
11
+ # @param resource MD5/sha1/sha256/scan_id to search for
12
+ #
13
+ # @return [JSON] Parsed response
14
+ def VTFile.query_report(api_key, resource)
15
+ if api_key == nil
16
+ raise "Invalid API Key"
17
+ end
18
+
19
+ if resource == nil
20
+ raise "Invalid resource, must be MD5/sha1/sha256/scan_id"
21
+ end
22
+
23
+ response = RestClient.post REPORT_URL, :apikey => api_key, :resource => resource
24
+
25
+ case response.code
26
+ when 429
27
+ raise "Virustotal limit reached. Try again later."
28
+ when 403
29
+ raise "Invalid privileges, please check your API key."
30
+ when 200
31
+ JSON.parse(response)
32
+ when 500
33
+ nil
34
+ end
35
+ end
36
+
37
+ # Submits a file to Virustotal.com for analysis
38
+ #
39
+ # @param api_key Virustotal.com API key
40
+ # @param path_to_file Path to file on disk to upload
41
+ #
42
+ # @return [JSON] Parsed response
43
+ def self.scan_file(api_key, path_to_file)
44
+ if !File.exists?(path_to_file)
45
+ raise Errno::ENOENT
46
+ end
47
+
48
+ if api_key == nil
49
+ raise "Invalid API Key"
50
+ end
51
+
52
+ response = RestClient.post SCAN_URL, :apikey => api_key, :filename=> path_to_file, :file => File.new(path_to_file, 'rb')
53
+
54
+ case response.code
55
+ when 429
56
+ raise "Virustotal limit reached. Try again later."
57
+ when 403
58
+ raise "Invalid privileges, please check your API key."
59
+ when 200
60
+ JSON.parse(response)
61
+ else
62
+ raise "Unknown Server error."
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,132 @@
1
+ module Uirusu
2
+ #
3
+ #
4
+ class VTResult
5
+ def initialize hash, result
6
+ if result == nil
7
+ return
8
+ end
9
+
10
+ @results = Array.new
11
+
12
+ if result["response_code"] == 0
13
+ res = Hash.new
14
+ res['hash'] = hash
15
+ res['scanner'] = '-'
16
+ res['md5'] = '-'
17
+ res['sha1'] = '-'
18
+ res['sha256'] = '-'
19
+ res['detected'] = '-'
20
+ res['version'] = '-'
21
+ res['result'] = '-'
22
+ res['update'] = '-'
23
+ res['permalink'] = '-'
24
+ res['result'] = result["verbose_msg"]
25
+
26
+ @results.push res
27
+ elsif result["response_code"] == 0
28
+ puts "[!] Invalid API KEY! Please correct this! Check ~/.uirusu"
29
+ exit
30
+ else
31
+ permalink = result["permalink"]
32
+ date = result["scan_date"]
33
+ md5 = result["md5"]
34
+ sha1 = result["sha1"]
35
+ sha256 = result["sha256"]
36
+
37
+ result["scans"].each do |scanner, value|
38
+ if value != ''
39
+ res = Hash.new
40
+ res['hash'] = hash
41
+ res['md5'] = md5
42
+ res['sha1'] = sha1
43
+ res['sha256'] = sha256
44
+ res['scanner'] = scanner
45
+ res['detected'] = value["detected"]
46
+ res['version'] = value["version"]
47
+
48
+ if value["result"] == nil
49
+ res['result'] = "Nothing detected"
50
+ else
51
+ res['result'] = value["result"]
52
+ end
53
+
54
+ res['update'] = value['update']
55
+ res['permalink'] = permalink unless permalink == nil
56
+
57
+ @results.push res
58
+ end
59
+ end
60
+ end
61
+
62
+ #if we didn't have any results let create a fake not found
63
+ if @results.size == 0
64
+ res = Hash.new
65
+ res['hash'] = hash
66
+ res['scanner'] = '-'
67
+ res['md5'] = '-'
68
+ res['sha1'] = '-'
69
+ res['sha256'] = '-'
70
+ res['permalink'] = '-'
71
+ res['detected'] = '-'
72
+ res['version'] = '-'
73
+ res['result'] = '-'
74
+ res['update'] = '-'
75
+ res['result'] = result["verbose_msg"]
76
+ @results.push res
77
+ end
78
+ end
79
+
80
+ #
81
+ #
82
+ def to_stdout
83
+ result_string = String.new
84
+ @results.each do |result|
85
+ result_string << "#{result['hash']}: Scanner: #{result['scanner']} Result: #{result['result']}\n"
86
+ end
87
+
88
+ print result_string
89
+ end
90
+
91
+ #
92
+ #
93
+ def to_yaml
94
+ result_string = String.new
95
+ @results.each do |result|
96
+ result_string << "vtresult:\n"
97
+ result_string << " hash: #{result['hash']}\n"
98
+ result_string << " md5: #{result['md5']}\n"
99
+ result_string << " sha1: #{result['sha1']}\n"
100
+ result_string << " sha256: #{result['sha256']}\n"
101
+ result_string << " scanner: #{result['scanner']}\n"
102
+ result_string << " detected: #{result['detected']}\n"
103
+ result_string << " date: #{result['date']}\n"
104
+ result_string << " permalink: #{result['permalink']}\n" unless result['permalink'] == nil
105
+ result_string << " result: #{result['result']}\n\n"
106
+ end
107
+
108
+ print result_string
109
+ end
110
+
111
+ #
112
+ #
113
+ def to_xml
114
+ result_string = String.new
115
+ @results.each do |result|
116
+ result_string << "\t<vtresult>\n"
117
+ result_string << "\t\t<hash>#{result['hash']}</hash>\n"
118
+ result_string << "\t\t<md5>#{result['md5']}</md5>\n"
119
+ result_string << "\t\t<sha1>#{result['sha1']}</sha1>\n"
120
+ result_string << "\t\t<sha256>#{result['sha256']}</sha256>\n"
121
+ result_string << "\t\t<scanner>#{result['scanner']}</scanner>\n"
122
+ result_string << "\t\t<detected>#{result['detected']}</detected>\n"
123
+ result_string << "\t\t<date>#{result['date']}</date>\n"
124
+ result_string << "\t\t<permalink>#{result['permalink']}</permalink>\n" unless result['permalink'] == nil
125
+ result_string << "\t\t<result>#{result['result']}</result>\n"
126
+ result_string << "\t</vtresult>\n"
127
+ end
128
+
129
+ print result_string
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,66 @@
1
+ module Uirusu
2
+ #
3
+ #
4
+ module VTUrl
5
+ SCAN_URL = "https://www.virustotal.com/vtapi/v2/url/scan"
6
+ REPORT_URL = "http://www.virustotal.com/vtapi/v2/url/report"
7
+
8
+ # Submits a URL to be scanned by Virustotal.com
9
+ #
10
+ # @param api_key Virustotal.com API key
11
+ # @param resource url to submit
12
+ #
13
+ # @return [JSON] Parsed response
14
+ def self.scan_url(api_key, resource)
15
+ if api_key == nil
16
+ raise "Invalid API Key"
17
+ end
18
+
19
+ if resource == nil
20
+ raise "Invalid resource, must be a valid url"
21
+ end
22
+
23
+ response = RestClient.post SCAN_URL, :apikey => api_key, :url => resource
24
+
25
+ case response.code
26
+ when 429
27
+ raise "Virustotal limit reached. Try again later."
28
+ when 403
29
+ raise "Invalid privileges, please check your API key."
30
+ when 200
31
+ JSON.parse(response)
32
+ else
33
+ raise "Unknown Server error."
34
+ end
35
+ end
36
+
37
+ # Searchs reports by URL from Virustotal.com
38
+ #
39
+ # @param api_key Virustotal.com API key
40
+ # @param resource url to search
41
+ #
42
+ # @return [JSON] Parsed response
43
+ def self.query_report(api_key, resource)
44
+ if api_key == nil
45
+ raise "Invalid API Key"
46
+ end
47
+
48
+ if resource == nil
49
+ raise "Invalid resource, must be a valid url"
50
+ end
51
+
52
+ response = RestClient.post REPORT_URL, :apikey => api_key, :resource => resource
53
+
54
+ case response.code
55
+ when 429
56
+ raise "Virustotal limit reached. Try again later."
57
+ when 403
58
+ raise "Invalid privileges, please check your API key."
59
+ when 200
60
+ JSON.parse(response)
61
+ else
62
+ raise "Unknown Server error."
63
+ end
64
+ end
65
+ end
66
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uirusu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-25 00:00:00.000000000 Z
12
+ date: 2012-03-02 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70221526495640 !ruby/object:Gem::Requirement
16
+ requirement: &70176306777160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.5.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70221526495640
24
+ version_requirements: *70176306777160
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rest-client
27
- requirement: &70221526495100 !ruby/object:Gem::Requirement
27
+ requirement: &70176306776280 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 1.6.1
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70221526495100
35
+ version_requirements: *70176306776280
36
36
  description: uirusu is library for interacting with Virustotal.org
37
37
  email: jacob.hammack@hammackj.com
38
38
  executables:
@@ -49,10 +49,14 @@ files:
49
49
  - Rakefile
50
50
  - README.markdown
51
51
  - TODO.markdown
52
+ - lib/uirusu/cli/application.rb
53
+ - lib/uirusu/vtcomment.rb
54
+ - lib/uirusu/vtfile.rb
55
+ - lib/uirusu/vtresult.rb
56
+ - lib/uirusu/vturl.rb
52
57
  - lib/uirusu.rb
53
58
  - uirusu.gemspec
54
- - !binary |-
55
- YmluL3VpcnVzdQ==
59
+ - bin/uirusu
56
60
  homepage: http://github.com/hammackj/uirusu/
57
61
  licenses:
58
62
  - BSD
@@ -74,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
78
  version: 1.8.16
75
79
  requirements: []
76
80
  rubyforge_project:
77
- rubygems_version: 1.8.16
81
+ rubygems_version: 1.8.6
78
82
  signing_key:
79
83
  specification_version: 3
80
84
  summary: uirusu