hybridanalysisx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 20b4903edd839b85fb14e303977fbfccf6edf3ff6ce93b181aae09bebdc74e1a
4
+ data.tar.gz: 0017fe61e806da4b6aea9ce4232aa1aa606a0e5a25e4b426cf653333a0113071
5
+ SHA512:
6
+ metadata.gz: c2c0886fd20889ab3c9076e3fda4b4073fa849ef49cdb4b5f13be22bb67291a3c94dd3f2877d528978d0c0dca8f70d80accf3c56c99cf9cba0afbb08cbbb3695
7
+ data.tar.gz: a6c1bcf0c0c2fb85e258f2d348fbc611bbafc268bc776cdc71633fde9751d005bc0f159cc4d50be23cc324f35280109ac29108cbf9860ddb8c3bac9670ec104e
@@ -0,0 +1,58 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ Gemfile.lock
49
+ .ruby-version
50
+ .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
57
+
58
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6
7
+ before_install: gem install bundler -v 2.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in hybridanalysisx.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Manabu Niseki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ # hybridanalysisx
2
+
3
+ [![Build Status](https://travis-ci.com/ninoseki/hybridanalysisx.svg?branch=master)](https://travis-ci.com/ninoseki/hybridanalysisx)
4
+ [![Coverage Status](https://coveralls.io/repos/github/ninoseki/hybridanalysisx/badge.svg?branch=master)](https://coveralls.io/github/ninoseki/hybridanalysisx?branch=master)
5
+ [![CodeFactor](https://www.codefactor.io/repository/github/ninoseki/hybridanalysisx/badge)](https://www.codefactor.io/repository/github/ninoseki/hybridanalysisx)
6
+
7
+ Yet another Hybrid Analysis API wrapper for Ruby.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ gem install hybridanalysisx
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ require "hybridanalysis"
19
+
20
+ # when given nothing, it tries to load your usernamem & API key via ENV["HA_API_KEY"] or ENV["HYBRIDANALYSIS_API_KEY"]
21
+ api = HybridAnalysis::API.new
22
+
23
+ api.feed.latest
24
+ api.quick_scan(file: "/tmp/foo.exe", scan_type: "all")
25
+ api.submit.file(file: "/tmp/foo.exe", environment_id: "110")
26
+ ```
27
+
28
+ ## License
29
+
30
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "hybridanalysisx"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/hybridanalysis/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "hybridanalysisx"
7
+ spec.version = HybridAnalysis::VERSION
8
+ spec.authors = ["Manabu Niseki"]
9
+ spec.email = ["manabu.niseki@gmail.com"]
10
+
11
+ spec.summary = 'Yet another Hybrid Analysis API wrapper for Ruby'
12
+ spec.description = 'Yet another Hybrid Analysis API wrapper for Ruby'
13
+ spec.homepage = "https://github.com/ninoseki/hybridanalysisx"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/ninoseki/hybridanalysisx"
19
+ spec.metadata["changelog_uri"] = "https://github.com/ninoseki/hybridanalysisx/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 2.1"
31
+ spec.add_development_dependency "coveralls", "~> 0.8"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
+ spec.add_development_dependency "rspec", "~> 3.9"
34
+ spec.add_development_dependency "vcr", "~> 5.0"
35
+ spec.add_development_dependency "webmock", "~> 3.8"
36
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hybridanalysis/version"
4
+
5
+ require "hybridanalysis/clients/client"
6
+
7
+ require "hybridanalysis/clients/abuse_reports"
8
+ require "hybridanalysis/clients/feed"
9
+ require "hybridanalysis/clients/file_collection"
10
+ require "hybridanalysis/clients/overview"
11
+ require "hybridanalysis/clients/quick_scan"
12
+ require "hybridanalysis/clients/report"
13
+ require "hybridanalysis/clients/search"
14
+ require "hybridanalysis/clients/submit"
15
+ require "hybridanalysis/clients/system"
16
+
17
+ require "hybridanalysis/api"
18
+
19
+ module HybridAnalysis
20
+ class Error < StandardError; end
21
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HybridAnalysis
4
+ class API
5
+ def initialize(key: ENV["HYBRIDANALYSIS_API_KEY"] || ENV["HA_API_KEY"])
6
+ @key = key
7
+ end
8
+
9
+ def abuse_reports
10
+ @abuse_reports ||= Clients::AbuseReports.new(@key)
11
+ end
12
+
13
+ def feed
14
+ @feed ||= Clients::Feed.new(@key)
15
+ end
16
+
17
+ def file_collection
18
+ @file_collection ||= Clients::FileCollection.new(@key)
19
+ end
20
+
21
+ def overview
22
+ @overview ||= Clients::Overview.new(@key)
23
+ end
24
+
25
+ def quick_scan
26
+ @quick_scan ||= Clients::QuickScan.new(@key)
27
+ end
28
+
29
+ def report
30
+ @report ||= Clients::Report.new(@key)
31
+ end
32
+
33
+ def search
34
+ @search ||= Clients::Search.new(@key)
35
+ end
36
+
37
+ def submit
38
+ @submit ||= Clients::Submit.new(@key)
39
+ end
40
+
41
+ def system
42
+ @system ||= Clients::System.new(@key)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HybridAnalysis
4
+ module Clients
5
+ class AbuseReports < Client
6
+ #
7
+ # Allows to request removal
8
+ #
9
+ # @param [String] sha256 SHA256 of the sample you want to report
10
+ # @param [String] reason Report reason
11
+ #
12
+ # @return [Hash]
13
+ #
14
+ def new(sha256:, reason: )
15
+ params = {
16
+ sha256: sha256,
17
+ reason: reason
18
+ }.compact
19
+ _post("/abuse-reports/new", params) { |json| json }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/https"
4
+ require "json"
5
+ require "uri"
6
+ require "zlib"
7
+
8
+ module HybridAnalysis
9
+ module Clients
10
+ class Client
11
+ attr_reader :key
12
+
13
+ HOST = "www.hybrid-analysis.com"
14
+ VERSION = "v2"
15
+ BASE_URL = "https://#{HOST}/api/#{VERSION}"
16
+ DEFAULT_UA = "Falcon Sandbox"
17
+
18
+ def initialize(key)
19
+ @key = key
20
+ end
21
+
22
+ private
23
+
24
+ def url_for(path)
25
+ URI(BASE_URL + path)
26
+ end
27
+
28
+ def https_options
29
+ if proxy = ENV["HTTPS_PROXY"] || ENV["https_proxy"]
30
+ uri = URI(proxy)
31
+ {
32
+ proxy_address: uri.hostname,
33
+ proxy_port: uri.port,
34
+ proxy_from_env: false,
35
+ use_ssl: true
36
+ }
37
+ else
38
+ { use_ssl: true }
39
+ end
40
+ end
41
+
42
+ def request(req)
43
+ Net::HTTP.start(HOST, 443, https_options) do |http|
44
+ req["api-key"] = key
45
+ req["user-agent"] = DEFAULT_UA
46
+
47
+ response = http.request(req)
48
+
49
+ code = response.code.to_i
50
+ body = response.body
51
+ json = JSON.parse(body) if response["Content-Type"].to_s.include?("application/json")
52
+ body = unzip(body) if response["Content-Type"].to_s.include?("application/gzip")
53
+
54
+ case code
55
+ when 200, 201, 202
56
+ if json
57
+ yield json
58
+ else
59
+ yield body
60
+ end
61
+ else
62
+ message = json&.dig("message") || body
63
+ raise Error, "Unsupported response code returned: #{code} (#{message})"
64
+ end
65
+ end
66
+ end
67
+
68
+ def _get(path, params = {}, &block)
69
+ uri = url_for(path)
70
+ uri.query = URI.encode_www_form(params)
71
+ get = Net::HTTP::Get.new(uri)
72
+
73
+ request(get, &block)
74
+ end
75
+
76
+ def _post(path, params = {}, &block)
77
+ post = Net::HTTP::Post.new(url_for(path))
78
+ post.set_form params
79
+
80
+ request(post, &block)
81
+ end
82
+
83
+ def _post_with_file(path, file:, filename:, params: {}, &block)
84
+ post = Net::HTTP::Post.new(url_for(path))
85
+ data = [
86
+ ["file", file, { filename: filename }],
87
+ ]
88
+ data += stringfy_keys(params)
89
+ post.set_form(data, "multipart/form-data")
90
+
91
+ request(post, &block)
92
+ end
93
+
94
+ def _delete(path, params = {}, &block)
95
+ delete = Net::HTTP::Delete.new(url_for(path))
96
+ delete.body = JSON.generate(params) if params
97
+
98
+ request(delete, &block)
99
+ end
100
+
101
+ def stringfy_keys(hash)
102
+ hash.map do |k, v|
103
+ [k.to_s, v.to_s]
104
+ end
105
+ end
106
+
107
+ def path?(path)
108
+ File.exist? path
109
+ end
110
+
111
+ def unzip(data)
112
+ sio = StringIO.new(data)
113
+ gz = Zlib::GzipReader.new(sio)
114
+ gz.read
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HybridAnalysis
4
+ module Clients
5
+ class Feed < Client
6
+ #
7
+ # access a JSON feed (summary information) of last 250 reports from 24h
8
+ #
9
+ # @return [Hash]
10
+ #
11
+ def latest
12
+ _get("/feed/latest") { |json| json }
13
+ end
14
+ end
15
+ end
16
+ end