htb 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2e6caea0b99b8c05235a7d882577af1a106b5313efdbe8e8034bdd18a18f1c83
4
+ data.tar.gz: d8e9addfbe08acc7acaaf30d5a033871b93b9271bcc93a0d85dd2bd33c914da5
5
+ SHA512:
6
+ metadata.gz: 053eb8609fd604dd1921c30279a686bc86d4362f9e4756e518168a505deeb720210d75aea4e2d84ddedf8510da71e49a036e7076560f304ab19076a2a96f3787
7
+ data.tar.gz: 853a12f640c67d268078cbf8fbf540bf5d7875d186ee8c1b0896d58db2b3f1f0f64b5c58bfcc3d4702fae675a2b902c401d631bdbd9c53cc71be2b2d94294e81
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-01-17
9
+
10
+ ### Added
11
+
12
+ - Initial release
13
+ - Machine management (list, profile, play, stop, own)
14
+ - VM management (spawn, terminate, reset, extend)
15
+ - User profiles and activity
16
+ - Challenge management
17
+ - VPN and lab information
18
+ - Support for the updated base URI (`labs.hackthebox.com`)
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 usiegj00
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,369 @@
1
+ # HTB Ruby
2
+
3
+ A Ruby gem for interacting with the [Hack The Box](https://www.hackthebox.com/) API v4.
4
+
5
+ ## Important: Base URI Change
6
+
7
+ The HTB API base URI has changed from the legacy `www.hackthebox.com` to `labs.hackthebox.com`. This gem uses the correct, updated base URI.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'htb'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ ```bash
20
+ bundle install
21
+ ```
22
+
23
+ Or install it yourself as:
24
+
25
+ ```bash
26
+ gem install htb
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ You'll need an HTB API token. You can obtain one from your [HTB Account Settings](https://app.hackthebox.com/profile/settings).
32
+
33
+ ### Interactive Login (Recommended)
34
+
35
+ The easiest way to configure your token:
36
+
37
+ ```bash
38
+ htb login
39
+ ```
40
+
41
+ This will:
42
+ 1. Prompt you for your API token (input is masked)
43
+ 2. Validate the token with HTB
44
+ 3. Save it securely to `~/.htbrc` (with 600 permissions)
45
+
46
+ ### Environment Variable
47
+
48
+ Alternatively, set an environment variable (takes priority over config file):
49
+
50
+ ```bash
51
+ export HTB_API_TOKEN=your_token_here
52
+ ```
53
+
54
+ ### Managing Configuration
55
+
56
+ ```bash
57
+ htb config # Show current configuration
58
+ htb login # Set/update API token
59
+ htb logout # Remove saved token
60
+ ```
61
+
62
+ ## CLI Usage
63
+
64
+ The gem includes a full-featured command-line interface.
65
+
66
+ ### Quick Start
67
+
68
+ ```bash
69
+ # First time? Login to save your token
70
+ htb login
71
+
72
+ # Show your profile
73
+ htb me
74
+
75
+ # Show current status (VM + VPN)
76
+ htb status
77
+
78
+ # List machines
79
+ htb machines list
80
+ htb machines list --retired
81
+ htb machines list --sp
82
+
83
+ # Get machine info
84
+ htb machines info Gavel
85
+ htb machines info 811
86
+
87
+ # Spawn/terminate machines
88
+ htb spawn 811
89
+ htb terminate 811
90
+
91
+ # Or using subcommands
92
+ htb vm spawn 811
93
+ htb vm terminate 811
94
+ htb vm reset 811
95
+ htb vm extend 811
96
+
97
+ # Submit flags
98
+ htb machines own 811 --flag "HTB{...}"
99
+ ```
100
+
101
+ ### All CLI Commands
102
+
103
+ ```bash
104
+ # Main commands
105
+ htb status # Show VM and VPN status
106
+ htb me # Show your profile
107
+ htb spawn MACHINE_ID # Spawn a machine (shortcut)
108
+ htb terminate MACHINE_ID # Terminate a machine (shortcut)
109
+ htb version # Show version
110
+
111
+ # Machine commands
112
+ htb machines list # List active machines
113
+ htb machines list --retired # List retired machines
114
+ htb machines list --sp # List Starting Point machines
115
+ htb machines info NAME # Show machine details
116
+ htb machines active # Show active machine
117
+ htb machines play ID # Start machine (free VPN)
118
+ htb machines stop # Stop current machine
119
+ htb machines own ID --flag FLAG # Submit a flag
120
+ htb machines search QUERY # Search machines
121
+ htb machines recommended # Show recommendations
122
+
123
+ # VM commands
124
+ htb vm spawn ID # Spawn machine (VIP/SP)
125
+ htb vm terminate ID # Terminate machine
126
+ htb vm reset ID # Reset machine
127
+ htb vm extend ID # Extend time
128
+ htb vm status # Show VM status
129
+ htb vm active # Show active VM
130
+
131
+ # User commands
132
+ htb users me # Your profile
133
+ htb users info USER_ID # User profile by ID
134
+ htb users activity USER_ID # User activity
135
+ htb users bloods USER_ID # User's first bloods
136
+ htb users badges USER_ID # User's badges
137
+ htb users subscriptions # Your subscriptions
138
+
139
+ # Challenge commands
140
+ htb challenges list # List challenges
141
+ htb challenges list --retired # Retired challenges
142
+ htb challenges info ID # Challenge details
143
+ htb challenges start ID # Start a challenge
144
+ htb challenges stop ID # Stop a challenge
145
+ htb challenges spawn ID # Spawn instance
146
+ htb challenges own ID --flag FLAG # Submit flag
147
+ htb challenges categories # List categories
148
+ htb challenges active # Show active challenge
149
+
150
+ # VPN commands
151
+ htb vpn status # Connection status
152
+ htb vpn servers # List VPN servers
153
+ htb vpn switch ID # Switch server
154
+ htb vpn regenerate # Regenerate config
155
+ htb vpn labs # List labs
156
+ htb vpn prolabs # List Pro Labs
157
+ htb vpn endgames # List Endgames
158
+ htb vpn fortresses # List Fortresses
159
+ ```
160
+
161
+ ## Ruby Library Usage
162
+
163
+ ```ruby
164
+ require 'htb'
165
+
166
+ # Configure globally
167
+ HTB.configure do |config|
168
+ config.api_token = ENV['HTB_API_TOKEN']
169
+ end
170
+
171
+ # Or create a client directly
172
+ client = HTB::Client.new(api_token: ENV['HTB_API_TOKEN'])
173
+ ```
174
+
175
+ ## Library Examples
176
+
177
+ ### Machines
178
+
179
+ ```ruby
180
+ client = HTB::Client.new(api_token: ENV['HTB_API_TOKEN'])
181
+
182
+ # List all machines
183
+ machines = client.machines.list
184
+
185
+ # Get machine profile
186
+ machine = client.machines.profile("Gavel") # by name
187
+ machine = client.machines.profile(811) # by ID
188
+
189
+ # Get active machine
190
+ active = client.machines.active
191
+
192
+ # Get retired machines
193
+ retired = client.machines.retired
194
+
195
+ # Get Starting Point machines
196
+ sp = client.machines.starting_point
197
+
198
+ # Submit a flag
199
+ client.machines.own(machine_id: 811, flag: "HTB{...}", difficulty: 50)
200
+ ```
201
+
202
+ ### VM Management (Spawn/Terminate)
203
+
204
+ ```ruby
205
+ # Spawn a machine (VIP/Starting Point)
206
+ client.vm.spawn(811)
207
+
208
+ # Get VM status
209
+ status = client.vm.status
210
+
211
+ # Get active VM
212
+ active = client.vm.active
213
+
214
+ # Terminate a machine
215
+ client.vm.terminate(811)
216
+
217
+ # Reset a machine
218
+ client.vm.reset(811)
219
+
220
+ # Extend machine time
221
+ client.vm.extend(811)
222
+ ```
223
+
224
+ ### Users
225
+
226
+ ```ruby
227
+ # Get current user info
228
+ me = client.users.me
229
+
230
+ # Get user profile by ID
231
+ user = client.users.profile(12345)
232
+
233
+ # Get user activity
234
+ activity = client.users.activity(12345)
235
+
236
+ # Get user badges
237
+ badges = client.users.badges(12345)
238
+
239
+ # Get subscriptions
240
+ subs = client.users.subscriptions
241
+ ```
242
+
243
+ ### Challenges
244
+
245
+ ```ruby
246
+ # List all challenges
247
+ challenges = client.challenges.list
248
+
249
+ # Get challenge info
250
+ challenge = client.challenges.info(123)
251
+
252
+ # Start a challenge
253
+ client.challenges.start(123)
254
+
255
+ # Submit flag
256
+ client.challenges.own(challenge_id: 123, flag: "HTB{...}", difficulty: 50)
257
+
258
+ # Stop a challenge
259
+ client.challenges.stop(123)
260
+ ```
261
+
262
+ ### VPN
263
+
264
+ ```ruby
265
+ # Get VPN servers
266
+ servers = client.vpn.servers
267
+
268
+ # Get connection status
269
+ status = client.vpn.status
270
+
271
+ # Get available labs
272
+ labs = client.vpn.labs
273
+
274
+ # Get Prolabs list
275
+ prolabs = client.vpn.prolabs
276
+
277
+ # Get Endgames list
278
+ endgames = client.vpn.endgames
279
+ ```
280
+
281
+ ## API Endpoints Reference
282
+
283
+ This gem implements the HTB v4 API endpoints. The base URI is `https://labs.hackthebox.com/api/v4`.
284
+
285
+ ### Machines
286
+ | Method | Endpoint | Description |
287
+ |--------|----------|-------------|
288
+ | GET | `/machine/list` | List all machines |
289
+ | GET | `/machine/profile/{id_or_name}` | Get machine profile |
290
+ | GET | `/machine/active` | Get active machine |
291
+ | POST | `/machine/play/{machine_id}` | Play machine (free VPN) |
292
+ | POST | `/machine/stop` | Stop machine |
293
+ | POST | `/machine/own` | Submit flag |
294
+ | GET | `/machine/recommended` | Get recommended machines |
295
+ | GET | `/machine/list/retired` | List retired machines |
296
+ | GET | `/machine/list/sp` | List Starting Point machines |
297
+
298
+ ### VM Management
299
+ | Method | Endpoint | Description |
300
+ |--------|----------|-------------|
301
+ | POST | `/vm/spawn` | Spawn a machine (VIP/SP) |
302
+ | POST | `/vm/terminate` | Terminate a machine |
303
+ | POST | `/vm/reset` | Reset a machine |
304
+ | POST | `/vm/extend` | Extend machine time |
305
+ | GET | `/vm/status` | Get VM status |
306
+ | GET | `/vm/active` | Get active VM |
307
+
308
+ ### Users
309
+ | Method | Endpoint | Description |
310
+ |--------|----------|-------------|
311
+ | GET | `/user/info` | Get current user info |
312
+ | GET | `/user/profile/basic/{user_id}` | Get user profile |
313
+ | GET | `/user/profile/basic/me` | Get own profile |
314
+ | GET | `/user/profile/activity/{user_id}` | Get user activity |
315
+ | GET | `/user/profile/bloods/{user_id}` | Get user bloods |
316
+ | GET | `/user/profile/badges/{user_id}` | Get user badges |
317
+
318
+ ### Challenges
319
+ | Method | Endpoint | Description |
320
+ |--------|----------|-------------|
321
+ | GET | `/challenge/list` | List all challenges |
322
+ | GET | `/challenge/info/{id}` | Get challenge info |
323
+ | POST | `/challenge/start/{id}` | Start a challenge |
324
+ | POST | `/challenge/stop/{id}` | Stop a challenge |
325
+ | POST | `/challenge/own` | Submit flag |
326
+ | GET | `/challenge/categories/list` | Get categories |
327
+
328
+ ### VPN & Labs
329
+ | Method | Endpoint | Description |
330
+ |--------|----------|-------------|
331
+ | GET | `/connections/servers` | Get VPN servers |
332
+ | GET | `/connections/status` | Get VPN status |
333
+ | GET | `/labs/list` | Get labs list |
334
+ | GET | `/prolab/list` | Get Prolabs list |
335
+ | GET | `/endgame/list` | Get Endgames list |
336
+
337
+ ## Error Handling
338
+
339
+ ```ruby
340
+ begin
341
+ client.machines.profile("nonexistent")
342
+ rescue HTB::AuthenticationError => e
343
+ puts "Invalid API token"
344
+ rescue HTB::NotFoundError => e
345
+ puts "Resource not found"
346
+ rescue HTB::RateLimitError => e
347
+ puts "Rate limited, slow down"
348
+ rescue HTB::Error => e
349
+ puts "API error: #{e.message}"
350
+ end
351
+ ```
352
+
353
+ ## Development
354
+
355
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
356
+
357
+ To install this gem onto your local machine, run `bundle exec rake install`.
358
+
359
+ ## Contributing
360
+
361
+ Bug reports and pull requests are welcome on GitHub at https://github.com/aluminumio/htb-ruby.
362
+
363
+ ## License
364
+
365
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
366
+
367
+ ## Disclaimer
368
+
369
+ This gem is not officially affiliated with or endorsed by Hack The Box. Use responsibly and in accordance with HTB's Terms of Service.
data/Rakefile ADDED
@@ -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
data/exe/htb ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "htb"
5
+ require "htb/cli"
6
+
7
+ HTB::CLI::Main.start(ARGV)
data/htb.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "htb"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["usiegj00"]
7
+ spec.email = ["usiegj00@users.noreply.github.com"]
8
+
9
+ spec.summary = "Ruby client for the Hack The Box API v4"
10
+ spec.description = "A Ruby gem for interacting with the Hack The Box (HTB) API v4. " \
11
+ "Supports machine management, user profiles, VM spawning, flag submission, and more."
12
+ spec.homepage = "https://github.com/aluminumio/htb-ruby"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 2.7.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/aluminumio/htb-ruby"
18
+ spec.metadata["changelog_uri"] = "https://github.com/aluminumio/htb-ruby/blob/main/CHANGELOG.md"
19
+
20
+ spec.files = Dir.chdir(__dir__) do
21
+ `git ls-files -z`.split("\x0").reject do |f|
22
+ (File.expand_path(f) == __FILE__) ||
23
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
24
+ end
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_dependency "faraday", "~> 2.0"
31
+ spec.add_dependency "faraday-multipart", "~> 1.0"
32
+ spec.add_dependency "thor", "~> 1.0"
33
+ spec.add_dependency "tty-table", "~> 0.12"
34
+ spec.add_dependency "tty-spinner", "~> 0.9"
35
+ spec.add_dependency "tty-prompt", "~> 0.23"
36
+ spec.add_dependency "pastel", "~> 0.8"
37
+
38
+ spec.add_development_dependency "bundler", "~> 2.0"
39
+ spec.add_development_dependency "rake", "~> 13.0"
40
+ spec.add_development_dependency "rspec", "~> 3.0"
41
+ spec.add_development_dependency "webmock", "~> 3.0"
42
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTB
4
+ class Challenges
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ # List all challenges
10
+ # GET /api/v4/challenge/list
11
+ def list
12
+ @client.get("/challenge/list")
13
+ end
14
+
15
+ # Get challenge info by ID
16
+ # GET /api/v4/challenge/info/{challenge_id}
17
+ def info(challenge_id)
18
+ @client.get("/challenge/info/#{challenge_id}")
19
+ end
20
+
21
+ # Get active challenge
22
+ # GET /api/v4/challenge/active
23
+ def active
24
+ @client.get("/challenge/active")
25
+ end
26
+
27
+ # Start a challenge
28
+ # POST /api/v4/challenge/start/{challenge_id}
29
+ def start(challenge_id)
30
+ @client.post("/challenge/start/#{challenge_id}")
31
+ end
32
+
33
+ # Stop a challenge
34
+ # POST /api/v4/challenge/stop/{challenge_id}
35
+ def stop(challenge_id)
36
+ @client.post("/challenge/stop/#{challenge_id}")
37
+ end
38
+
39
+ # Submit flag for challenge
40
+ # POST /api/v4/challenge/own
41
+ # @param challenge_id [Integer] Challenge ID
42
+ # @param flag [String] The flag to submit
43
+ # @param difficulty [Integer] Difficulty rating
44
+ def own(challenge_id:, flag:, difficulty: 50)
45
+ @client.post("/challenge/own", {
46
+ id: challenge_id,
47
+ flag: flag,
48
+ difficulty: difficulty
49
+ })
50
+ end
51
+
52
+ # Download challenge files
53
+ # GET /api/v4/challenge/download/{challenge_id}
54
+ def download(challenge_id)
55
+ @client.get("/challenge/download/#{challenge_id}")
56
+ end
57
+
58
+ # Get challenge categories
59
+ # GET /api/v4/challenge/categories/list
60
+ def categories
61
+ @client.get("/challenge/categories/list")
62
+ end
63
+
64
+ # Get retired challenges
65
+ # GET /api/v4/challenge/list/retired
66
+ def retired
67
+ @client.get("/challenge/list/retired")
68
+ end
69
+
70
+ # Get challenge activity
71
+ # GET /api/v4/challenge/activity/{challenge_id}
72
+ def activity(challenge_id)
73
+ @client.get("/challenge/activity/#{challenge_id}")
74
+ end
75
+
76
+ # Submit challenge review
77
+ # POST /api/v4/challenge/review
78
+ def review(challenge_id:, stars:, headline:, review:)
79
+ @client.post("/challenge/review", {
80
+ id: challenge_id,
81
+ stars: stars,
82
+ headline: headline,
83
+ review: review
84
+ })
85
+ end
86
+
87
+ # Get recommended challenges
88
+ # GET /api/v4/challenge/recommended
89
+ def recommended
90
+ @client.get("/challenge/recommended")
91
+ end
92
+
93
+ # Get challenge todo status
94
+ # GET /api/v4/challenge/todo/{challenge_id}
95
+ def todo(challenge_id)
96
+ @client.get("/challenge/todo/#{challenge_id}")
97
+ end
98
+
99
+ # Spawn challenge instance
100
+ # POST /api/v4/challenge/spawn
101
+ def spawn(challenge_id)
102
+ @client.post("/challenge/spawn", { challenge_id: challenge_id })
103
+ end
104
+
105
+ # Terminate challenge instance
106
+ # POST /api/v4/challenge/terminate
107
+ def terminate(challenge_id)
108
+ @client.post("/challenge/terminate", { challenge_id: challenge_id })
109
+ end
110
+ end
111
+ end