Skip to content

Commit 4a069da

Browse files
committed
Merge branch 'release/v1.0.0' into main
2 parents 4535ad5 + d7bedc3 commit 4a069da

File tree

13 files changed

+728
-1
lines changed

13 files changed

+728
-1
lines changed

.github/workflows/go.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This workflow will build a golang project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3+
4+
name: Go
5+
6+
on:
7+
push:
8+
branches: [ "main", "dev" ]
9+
pull_request:
10+
branches: [ "main", "dev" ]
11+
12+
jobs:
13+
14+
build:
15+
runs-on: ubuntu-latest
16+
strategy:
17+
matrix:
18+
go: ['1.19', '1.20', '1.21']
19+
steps:
20+
- uses: actions/checkout@v3
21+
22+
- name: Set up Go
23+
uses: actions/setup-go@v4
24+
with:
25+
go-version: ${{ matrix.go }}
26+
27+
- name: Build
28+
run: go build -v ./...

README.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,78 @@
1-
# htb-cli-reborn
1+
```
2+
This software, engineered using the Go programming language, serves to streamline and automate various tasks for the HackTheBox platform, enhancing user efficiency and productivity.
3+
4+
Usage:
5+
htb-cli [command]
6+
7+
Available Commands:
8+
active Catalogue of active machines
9+
submit Submit credentials (User and Root Flags)
10+
help Help about any command
11+
info Showcase detailed machine information
12+
reset Reset a machine - [WIP]
13+
start Start a machine
14+
stop Stop the current machine
15+
16+
Flags:
17+
-h, --help help for htb-cli
18+
-p, --proxy string Configure a URL for an HTTP proxy
19+
-v, --verbose Verbose mode
20+
21+
Use "htb-cli [command] --help" for more information about a command.
22+
```
23+
24+
## Installation
25+
26+
`go install github.com/GoToolSharing/htb-cli@latest`
27+
28+
## Configuration
29+
30+
You must add a Hackthebox **App token** in the **HTB_TOKEN** environment variable (zshrc maybe).
31+
API Token can be find here : https://app.hackthebox.com/profile/settings => Create App Token
32+
33+
```
34+
export HTB_TOKEN=eyJ...
35+
```
36+
37+
## Start
38+
39+
```
40+
> htb-cli start -m Flight
41+
Machine deployed to lab.
42+
```
43+
44+
## Stop
45+
46+
```
47+
> htb-cli stop
48+
Machine terminated.
49+
```
50+
51+
## Reset
52+
53+
```
54+
> htb-cli reset -m Flight
55+
Machine terminated.
56+
```
57+
58+
## Submit
59+
60+
This command allows to submit the user flag and the root flag of active and retired machines. The first argument is the flag and the second the difficulty /10.
61+
62+
```
63+
> htb-cli submit -f flag4testing -d 3
64+
65+
SteamCloud user is now owned.
66+
```
67+
68+
## Info
69+
70+
By default the command shows the active machine.
71+
72+
```
73+
> htb-cli info -m Zipper -m Sau
74+
75+
Name |OS |Active |Difficulty |Stars |FirstUserBlood |FirstRootBlood |Status |Release
76+
Zipper |Linux |0 |Hard |4.5 |1H 57M 59S |2H 8M 18S |❌ User - ❌ Root |2018-10-20
77+
Sau |Linux |1 |Easy |4.6 |0H 8M 39S |0H 11M 40S |✅ User - ✅ Root |2023-07-08
78+
```

cmd/active.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"text/tabwriter"
8+
"time"
9+
10+
"net/http"
11+
12+
"github.com/GoToolSharing/htb-cli/utils"
13+
"github.com/kyokomi/emoji/v2"
14+
"github.com/spf13/cobra"
15+
)
16+
17+
var activeCmd = &cobra.Command{
18+
Use: "active",
19+
Short: "Catalogue of active machines",
20+
Long: "This command serves to generate a detailed summary of the currently active machines, providing pertinent information for each.",
21+
Run: func(cmd *cobra.Command, args []string) {
22+
url := "https://www.hackthebox.com/api/v4/machine/list"
23+
resp, err := utils.HtbRequest(http.MethodGet, url, proxyParam, nil)
24+
if err != nil {
25+
log.Fatal(err)
26+
}
27+
info := utils.ParseJsonMessage(resp, "info")
28+
log.Println(info)
29+
30+
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.Debug)
31+
fmt.Fprintln(w, "Name\tOS\tDifficulty\tUser Owns\tSystem Owns\tStars\tStatus\tRelease")
32+
33+
// red_color := color.New(color.FgRed).SprintFunc()
34+
status := "Not defined"
35+
for _, value := range info.([]interface{}) {
36+
data := value.(map[string]interface{})
37+
if data["authUserInUserOwns"] == nil && data["authUserInRootOwns"] == nil {
38+
status = emoji.Sprint(":x:User - :x:Root")
39+
} else if data["authUserInUserOwns"] == true && data["authUserInRootOwns"] == nil {
40+
status = emoji.Sprint(":white_check_mark:User - :x:Root")
41+
} else if data["authUserInUserOwns"] == nil && data["authUserInRootOwns"] == true {
42+
status = emoji.Sprint(":x:User - :white_check_mark:Root")
43+
} else if data["authUserInUserOwns"] == true && data["authUserInRootOwns"] == true {
44+
status = emoji.Sprint(":white_check_mark:User - :white_check_mark:Root")
45+
}
46+
t, err := time.Parse(time.RFC3339Nano, data["release"].(string))
47+
if err != nil {
48+
fmt.Println("Erreur when date parsing :", err)
49+
return
50+
}
51+
datetime := t.Format("2006-01-02")
52+
fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", data["name"], data["os"], data["difficultyText"], data["user_owns_count"], data["root_owns_count"], data["stars"], status, datetime)
53+
}
54+
w.Flush()
55+
},
56+
}
57+
58+
func init() {
59+
rootCmd.AddCommand(activeCmd)
60+
}

cmd/info.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
"os"
8+
"text/tabwriter"
9+
"time"
10+
11+
"github.com/GoToolSharing/htb-cli/utils"
12+
"github.com/kyokomi/emoji/v2"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
var machineParam []string
17+
18+
var infoCmd = &cobra.Command{
19+
Use: "info",
20+
Short: "Showcase detailed machine information",
21+
Long: "Displays detailed information of the specified machines in a structured table.",
22+
Run: func(cmd *cobra.Command, args []string) {
23+
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.Debug)
24+
fmt.Fprintln(w, "Name\tOS\tActive\tDifficulty\tStars\tFirstUserBlood\tFirstRootBlood\tStatus\tRelease")
25+
status := "Not defined"
26+
log.Println(machineParam)
27+
for index, _ := range machineParam {
28+
machine_id := utils.SearchMachineIDByName(machineParam[index], proxyParam)
29+
30+
url := "https://www.hackthebox.com/api/v4/machine/profile/" + machine_id
31+
resp, err := utils.HtbRequest(http.MethodGet, url, proxyParam, nil)
32+
if err != nil {
33+
log.Fatal(err)
34+
}
35+
info := utils.ParseJsonMessage(resp, "info")
36+
37+
data := info.(map[string]interface{})
38+
if data["authUserInUserOwns"] == nil && data["authUserInRootOwns"] == nil {
39+
status = emoji.Sprint(":x:User - :x:Root")
40+
} else if data["authUserInUserOwns"] == true && data["authUserInRootOwns"] == nil {
41+
status = emoji.Sprint(":white_check_mark:User - :x:Root")
42+
} else if data["authUserInUserOwns"] == nil && data["authUserInRootOwns"] == true {
43+
status = emoji.Sprint(":x:User - :white_check_mark:Root")
44+
} else if data["authUserInUserOwns"] == true && data["authUserInRootOwns"] == true {
45+
status = emoji.Sprint(":white_check_mark:User - :white_check_mark:Root")
46+
}
47+
t, err := time.Parse(time.RFC3339Nano, data["release"].(string))
48+
if err != nil {
49+
fmt.Println("Erreur when date parsing :", err)
50+
return
51+
}
52+
datetime := t.Format("2006-01-02")
53+
fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n", data["name"], data["os"], data["active"], data["difficultyText"], data["stars"], data["firstUserBloodTime"], data["firstRootBloodTime"], status, datetime)
54+
}
55+
w.Flush()
56+
57+
},
58+
}
59+
60+
func init() {
61+
rootCmd.AddCommand(infoCmd)
62+
infoCmd.Flags().StringSliceVarP(&machineParam, "machine", "m", []string{}, "Machine name")
63+
infoCmd.MarkFlagRequired("machine")
64+
}

cmd/reset.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
8+
"github.com/GoToolSharing/htb-cli/utils"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var resetCmd = &cobra.Command{
13+
Use: "reset",
14+
Short: "Reset a machine - [WIP]",
15+
Long: "Initiates a reset request for the selected machine.",
16+
Run: func(cmd *cobra.Command, args []string) {
17+
machine_id := utils.GetActiveMachineID(proxyParam)
18+
log.Println("Machine ID :", machine_id)
19+
machine_type := utils.GetMachineType(machine_id, "")
20+
log.Println("Machine Type :", machine_type)
21+
22+
url := ""
23+
jsonData := []byte("")
24+
switch machine_type {
25+
case "active":
26+
url = "https://www.hackthebox.com/api/v4/vm/reset"
27+
jsonData = []byte(`{"machine_id": ` + machine_id + `}`)
28+
default:
29+
url = "https://www.hackthebox.com/api/v4/arena/reset"
30+
jsonData = []byte(`{"machine_id": ` + machine_id + `}`)
31+
}
32+
resp, err := utils.HtbRequest(http.MethodPost, url, proxyParam, jsonData)
33+
if err != nil {
34+
log.Fatal(err)
35+
}
36+
message := utils.ParseJsonMessage(resp, "message")
37+
fmt.Println(message)
38+
},
39+
}
40+
41+
func init() {
42+
rootCmd.AddCommand(resetCmd)
43+
}

cmd/root.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package cmd
2+
3+
import (
4+
"io"
5+
"log"
6+
"os"
7+
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var verbose bool
12+
var proxyParam string
13+
14+
var rootCmd = &cobra.Command{
15+
Use: "htb-cli",
16+
Short: "CLI enhancing the HackTheBox user experience.",
17+
Long: `This software, engineered using the Go programming language, serves to streamline and automate various tasks for the HackTheBox platform, enhancing user efficiency and productivity.`,
18+
PersistentPreRun: func(cmd *cobra.Command, args []string) {
19+
if verbose {
20+
log.SetOutput(os.Stdout)
21+
} else {
22+
log.SetOutput(io.Discard)
23+
}
24+
},
25+
}
26+
27+
func Execute() {
28+
err := rootCmd.Execute()
29+
if err != nil {
30+
os.Exit(1)
31+
}
32+
}
33+
34+
func init() {
35+
rootCmd.CompletionOptions.DisableDefaultCmd = true
36+
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Verbose mode")
37+
rootCmd.PersistentFlags().StringVarP(&proxyParam, "proxy", "p", "", "Configure a URL for an HTTP proxy")
38+
}

cmd/start.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/http"
7+
8+
"github.com/GoToolSharing/htb-cli/utils"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var machineChoosen string
13+
14+
var startCmd = &cobra.Command{
15+
Use: "start",
16+
Short: "Start a machine",
17+
Long: `Starts a Hackthebox machine specified in argument`,
18+
Run: func(cmd *cobra.Command, args []string) {
19+
machine_id := utils.SearchMachineIDByName(machineChoosen, proxyParam)
20+
log.Println("Machine ID :", machine_id)
21+
machine_type := utils.GetMachineType(machine_id, proxyParam)
22+
log.Println("Machine Type :", machine_type)
23+
user_subscription := utils.GetUserSubscription(proxyParam)
24+
log.Println("User subscription :", user_subscription)
25+
if machine_type == "release" {
26+
url := "https://www.hackthebox.com/api/v4/arena/start"
27+
resp, err := utils.HtbRequest(http.MethodPost, url, proxyParam, []byte(`{}`))
28+
if err != nil {
29+
log.Fatal(err)
30+
}
31+
message := utils.ParseJsonMessage(resp, "message")
32+
fmt.Println(message)
33+
return
34+
}
35+
36+
url := ""
37+
jsonData := []byte("")
38+
switch user_subscription {
39+
case "vip":
40+
url = "https://www.hackthebox.com/api/v4/vm/spawn"
41+
jsonData = []byte(`{"machine_id": ` + machine_id + `}`)
42+
default:
43+
url = "https://www.hackthebox.com/api/v4/machine/play/" + machine_id
44+
jsonData = []byte("{}")
45+
}
46+
resp, err := utils.HtbRequest(http.MethodPost, url, proxyParam, jsonData)
47+
if err != nil {
48+
log.Fatal(err)
49+
}
50+
message := utils.ParseJsonMessage(resp, "message")
51+
fmt.Println(message)
52+
},
53+
}
54+
55+
func init() {
56+
rootCmd.AddCommand(startCmd)
57+
startCmd.Flags().StringVarP(&machineChoosen, "machine", "m", "", "Machine name")
58+
startCmd.MarkFlagRequired("machine")
59+
}

0 commit comments

Comments
 (0)